<commit_before>var _super = require('sails-auth/api/models/User');

_.merge(exports, _super);
_.merge(exports, {

  // Extend with custom logic here by adding additional fields, methods, etc.
  attributes: {
    missingPets: {
    	collection: 'missingPet',
    	via: 'creator'
    },
    pictures: {
    	collection: 'Picture',
    	via: 'uploader'
    },
    contactInfo: {
			collection: 'contactInfo',
			via: 'creator'
		},
    profilePicture: {
      type: 'string',
    },

    toJSON: function toJSON() {
      var user = _super.attributes.toJSON.apply(this);
      user.facebookProfilePicture = this.getFacebookProfilePicture();
      return user;
    },

    getFacebookProfilePicture: function getFacebookProfilePicture() {
      var facebookPassport = _.find(this.passports, _.matches({ provider: 'facebook' }));
      if (facebookPassport && facebookPassport.identifier) {
        return 'https://graph.facebook.com/v2.6/'+facebookPassport.identifier+'/picture';
      }
    },
  },

  beforeCreate: function beforeCreate(user, next) {
    user.profilePicture = _super.attributes.getGravatarUrl(user.email);
    if (_super.beforeCreate) {
      _super.beforeCreate.apply(_super, arguments);
    }
  },

});<commit_msg>use facebook profile picture after connecting User to facebook passport<commit_after>'use strict';

var _super = require('sails-auth/api/models/User');

_.merge(exports, _super);
_.merge(exports, {

  // Extend with custom logic here by adding additional fields, methods, etc.
  attributes: {
    missingPets: {
    	collection: 'missingPet',
    	via: 'creator'
    },
    pictures: {
    	collection: 'Picture',
    	via: 'uploader'
    },
    contactInfo: {
			collection: 'contactInfo',
			via: 'creator'
		},
    profilePicture: {
      type: 'string',
    },

    toJSON: function toJSON() {
      var user = _super.attributes.toJSON.apply(this);
      user.facebookProfilePicture = this.getFacebookProfilePicture();
      return user;
    },

    getFacebookProfilePicture: function getFacebookProfilePicture() {
      return User._getFacebookProfilePictureUrl(_.find(this.passports, _.matches({ provider: 'facebook' })));
    },
  },

  beforeCreate: function beforeCreate(user, next) {
    user.profilePicture = _super.attributes.getGravatarUrl(user.email);
    if (_super.beforeCreate) {
      _super.beforeCreate.apply(_super, arguments);
    }
  },

  afterConnectToPassport: function afterConnectToPassport(user, passport, next) {
    sails.log.debug('afterConnectToPassport', user, passport);
    if ('facebook' === passport.provider) {
      User.update(
        {id: user.id},
        {profilePicture: this._getFacebookProfilePictureUrl(passport)}
      ).exec(function(err, updated) {
        next(null, user);
      });
    } else {
      next(null, user);
    }
  },

  _getFacebookProfilePictureUrl: function _getFacebookProfilePictureUrl(facebookPassport) {
    if (facebookPassport && facebookPassport.identifier) {
      return 'https://graph.facebook.com/v2.6/'+facebookPassport.identifier+'/picture';
    }
  }

});<|endoftext|>


<commit_before>// Copyright © 2015 Jan Keromnes. All rights reserved.
// The following code is covered by the AGPLv3 license.

var camp = require('camp');
var http = require('http');

var db = require('./lib/db');
var log = require('./lib/log');
var routes = require('./lib/routes');
var shipyard = require('./lib/shipyard');
var users = require('./lib/users');

// Use `make ports` to set up these unprivileged ports.
var ports = {
  http: 1080,
  https: 1443
};

// Permanently redirect all HTTP requests to HTTPS.

var forwarder = http.Server(function (req, res) {
  res.writeHead(301, { 'Location': 'https://' + req.headers.host + req.url });
  res.end();
});

forwarder.listen(ports.http);

// The main Janitor server.

var app = camp.start({
  documentRoot: process.cwd() + '/static',
  port: ports.https,
  secure: true,
  key: 'https.key',
  cert: 'https.crt',
  ca: []
});

log('Janitor →  https://localhost' + (ports.https === 443 ? '' : ':' + ports.https));

// Public landing page.

app.route(/^\/$/, function (data, match, end, query) {

  users.get(data, query, function (err, user) {
    routes.landingPage(user, end);
  });

});

// User logout.

app.route(/^\/logout\/?$/, function (data, match, end, query) {

  users.logout(query, function (err) {
    routes.redirect(query, '/');
  });

});

// User login.

app.route(/^\/login\/?$/, function (data, match, end, query) {

  users.get(data, query, function (err, user) {

    if (user) {
      routes.redirect(query, '/');
      return;
    }

    routes.loginPage(end);

  });

});

// User contributions list.

app.route(/^\/contributions\/?$/, function (data, match, end, query) {

  users.get(data, query, function (err, user) {

    if (user) {
      routes.contributionsPage(user, end);
      return;
    }

    routes.loginPage(end);

  });

});

// User account.

app.route(/^\/account\/?$/, function (data, match, end, query) {

  users.get(data, query, function (err, user) {

    if (user) {
      routes.accountPage(user, end);
      return;
    }

    routes.loginPage(end);

  });

});

// 404 Not Found.

app.notfound(/.*/, function (data, match, end, query) {

  log('404', match[0]);

  users.get(data, query, function (err, user) {
    routes.notFoundPage(user, end);
  });

});

// Alpha version sign-up.

app.ajax.on('signup', function (data, end) {

  var email = data.email;
  var waitlist = db.get('waitlist');

  log('signup', email);

  if (waitlist[email]) {
    end({ status: 'already-added' });
    return;
  }

  waitlist[email] = Date.now();
  db.save();

  end({ status: 'added' });

});

// Request a log-in key via email.

app.ajax.on('login', function (data, end, query) {

  users.get(data, query, function (err, user) {

    if (user) {
      end({ status: 'logged-in' });
      return;
    }

    var email = data.email;

    users.sendLoginEmail(email, query, function (err) {
      if (err) {
        var error = err.toString();
        log(error, '(while emailing ' + email + ')');
        end({ status: 'error', message: error });
        return;
      }
      end({ status: 'email-sent' });
    });

  });

});

// Expose Shipyard over HTTPS on port 1789.

shipyard.start({
  port: 1789,
  key: 'https.key',
  cert: 'https.crt',
  ca: []
});

log('Shipyard →  https://localhost:' + 1789);
<commit_msg>Return when choosing a route or ending a connection.<commit_after>// Copyright © 2015 Jan Keromnes. All rights reserved.
// The following code is covered by the AGPLv3 license.

var camp = require('camp');
var http = require('http');

var db = require('./lib/db');
var log = require('./lib/log');
var routes = require('./lib/routes');
var shipyard = require('./lib/shipyard');
var users = require('./lib/users');

// Use `make ports` to set up these unprivileged ports.
var ports = {
  http: 1080,
  https: 1443
};

// Permanently redirect all HTTP requests to HTTPS.

var forwarder = http.Server(function (req, res) {
  res.writeHead(301, { 'Location': 'https://' + req.headers.host + req.url });
  res.end();
});

forwarder.listen(ports.http);

// The main Janitor server.

var app = camp.start({
  documentRoot: process.cwd() + '/static',
  port: ports.https,
  secure: true,
  key: 'https.key',
  cert: 'https.crt',
  ca: []
});

log('Janitor →  https://localhost' + (ports.https === 443 ? '' : ':' + ports.https));

// Public landing page.

app.route(/^\/$/, function (data, match, end, query) {

  users.get(data, query, function (err, user) {
    return routes.landingPage(user, end);
  });

});

// User logout.

app.route(/^\/logout\/?$/, function (data, match, end, query) {

  users.logout(query, function (err) {
    return routes.redirect(query, '/');
  });

});

// User login.

app.route(/^\/login\/?$/, function (data, match, end, query) {

  users.get(data, query, function (err, user) {

    if (user) {
      return routes.redirect(query, '/');
    }

    return routes.loginPage(end);

  });

});

// User contributions list.

app.route(/^\/contributions\/?$/, function (data, match, end, query) {

  users.get(data, query, function (err, user) {

    if (user) {
      return routes.contributionsPage(user, end);
    }

    return routes.loginPage(end);

  });

});

// User account.

app.route(/^\/account\/?$/, function (data, match, end, query) {

  users.get(data, query, function (err, user) {

    if (user) {
      return routes.accountPage(user, end);
    }

    return routes.loginPage(end);

  });

});

// 404 Not Found.

app.notfound(/.*/, function (data, match, end, query) {

  log('404', match[0]);

  users.get(data, query, function (err, user) {
    return routes.notFoundPage(user, end);
  });

});

// Alpha version sign-up.

app.ajax.on('signup', function (data, end) {

  var email = data.email;
  var waitlist = db.get('waitlist');

  log('signup', email);

  if (waitlist[email]) {
    return end({ status: 'already-added' });
  }

  waitlist[email] = Date.now();
  db.save();

  return end({ status: 'added' });

});

// Request a log-in key via email.

app.ajax.on('login', function (data, end, query) {

  users.get(data, query, function (err, user) {

    if (user) {
      end({ status: 'logged-in' });
      return;
    }

    var email = data.email;

    users.sendLoginEmail(email, query, function (err) {
      if (err) {
        var error = err.toString();
        log(error, '(while emailing ' + email + ')');
        return end({ status: 'error', message: error });
      }
      return end({ status: 'email-sent' });
    });

  });

});

// Expose Shipyard over HTTPS on port 1789.

shipyard.start({
  port: 1789,
  key: 'https.key',
  cert: 'https.crt',
  ca: []
});

log('Shipyard →  https://localhost:' + 1789);
<|endoftext|>


<commit_before>var _ = require('lodash');
var _super = require('sails-auth/api/models/User');

_.merge(exports, _super);
_.merge(exports, {

  // Extend with custom logic here by adding additional fields, methods, etc.
  attributes: {
    missingPets: {
    	collection: 'missingPet',
    	via: 'creator'
    },
    pictures: {
    	collection: 'Picture',
    	via: 'uploader'
    },
    contactInfo: {
			collection: 'contactInfo',
			via: 'creator'
		},
    profilePicture: {
      type: 'string',
    },

    toJSON: function toJSON() {
      sails.log.debug('user.toJSON ');
      var user = _super.attributes.toJSON.apply(this);
      user.facebookProfilePicture = this.getFacebookProfilePicture();
      sails.log.debug('user.toJSON ', user);
      return user;
    },

    getFacebookProfilePicture: function getFacebookProfilePicture() {
      sails.log.debug('user passports', this.passports);
      // var facebookPassport = _.find(this.passports, { provider: 'facebook' });
      var facebookPassport = _.find(this.passports, function(o) {
        sails.log.debug('passport', o);
        return 'facebook' === o.provider;
      });
      sails.log.debug('facebookPassport', facebookPassport);
      if (facebookPassport && facebookPassport.identifier) {
      sails.log.debug('return');
        return 'https://graph.facebook.com/v2.6/'+facebookPassport.identifier+'/picture';
      }
    },
  },

  beforeCreate: function beforeCreate(user, next) {
    sails.log.debug('user.beforeCreate', user);
    if (_super.beforeCreate) {
      _super.beforeCreate.apply(_super, arguments);
    }
  },

});<commit_msg>resolve lodash version issue and clean up debug log<commit_after>var _super = require('sails-auth/api/models/User');

_.merge(exports, _super);
_.merge(exports, {

  // Extend with custom logic here by adding additional fields, methods, etc.
  attributes: {
    missingPets: {
    	collection: 'missingPet',
    	via: 'creator'
    },
    pictures: {
    	collection: 'Picture',
    	via: 'uploader'
    },
    contactInfo: {
			collection: 'contactInfo',
			via: 'creator'
		},
    profilePicture: {
      type: 'string',
    },

    toJSON: function toJSON() {
      var user = _super.attributes.toJSON.apply(this);
      user.facebookProfilePicture = this.getFacebookProfilePicture();
      return user;
    },

    getFacebookProfilePicture: function getFacebookProfilePicture() {
      var facebookPassport = _.find(this.passports, _.matches({ provider: 'facebook' }));
      if (facebookPassport && facebookPassport.identifier) {
        return 'https://graph.facebook.com/v2.6/'+facebookPassport.identifier+'/picture';
      }
    },
  },

  beforeCreate: function beforeCreate(user, next) {
    if (_super.beforeCreate) {
      _super.beforeCreate.apply(_super, arguments);
    }
  },

});<|endoftext|>


<commit_before>Flotr.addPlugin('legend', {
  options: {
    show: true,            // => setting to true will show the legend, hide otherwise
    noColumns: 1,          // => number of colums in legend table // @todo: doesn't work for HtmlText = false
    labelFormatter: function(v){return v;}, // => fn: string -> string
    labelBoxBorderColor: '#CCCCCC', // => border color for the little label boxes
    labelBoxWidth: 14,
    labelBoxHeight: 10,
    labelBoxMargin: 5,
    labelBoxOpacity: 0.4,
    container: null,       // => container (as jQuery object) to put legend in, null means default on top of graph
    position: 'nw',        // => position of default legend container within plot
    margin: 5,             // => distance from grid edge to default legend container within plot
    backgroundColor: null, // => null means auto-detect
    backgroundOpacity: 0.85// => set to 0 to avoid background, set to 1 for a solid background
  },
  callbacks: {
    'flotr:afterinit': function() {
      this.legend.insertLegend();
    }
  },
  /**
   * Adds a legend div to the canvas container or draws it on the canvas.
   */
  insertLegend: function(){

    if(!this.options.legend.show)
      return;

    var series = this.series,
      plotOffset = this.plotOffset,
      options = this.options,
      legend = options.legend,
      fragments = [],
      rowStarted = false,
      ctx = this.ctx,
      noLegendItems = _.filter(series, function(s) {return (s.label && !s.hide);}).length,
      p = legend.position,
      m = legend.margin,
      i, label, color;

    if (noLegendItems) {
      if (!options.HtmlText && this.textEnabled && !legend.container) {
        var style = {
          size: options.fontSize*1.1,
          color: options.grid.color
        };

        var lbw = legend.labelBoxWidth,
            lbh = legend.labelBoxHeight,
            lbm = legend.labelBoxMargin,
            offsetX = plotOffset.left + m,
            offsetY = plotOffset.top + m;

        // We calculate the labels' max width
        var labelMaxWidth = 0;
        for(i = series.length - 1; i > -1; --i){
          if(!series[i].label || series[i].hide) continue;
          label = legend.labelFormatter(series[i].label);
          labelMaxWidth = Math.max(labelMaxWidth, Flotr.measureText(ctx, label, style).width);
        }

        var legendWidth  = Math.round(lbw + lbm*3 + labelMaxWidth),
            legendHeight = Math.round(noLegendItems*(lbm+lbh) + lbm);

        if(p.charAt(0) == 's') offsetY = plotOffset.top + this.plotHeight - (m + legendHeight);
        if(p.charAt(1) == 'e') offsetX = plotOffset.left + this.plotWidth - (m + legendWidth);

        // Legend box
        color = this.processColor(legend.backgroundColor || 'rgb(240,240,240)', {opacity: legend.backgroundOpacity || 0.1});

        ctx.fillStyle = color;
        ctx.fillRect(offsetX, offsetY, legendWidth, legendHeight);
        ctx.strokeStyle = legend.labelBoxBorderColor;
        ctx.strokeRect(Flotr.toPixel(offsetX), Flotr.toPixel(offsetY), legendWidth, legendHeight);

        // Legend labels
        var x = offsetX + lbm;
        var y = offsetY + lbm;
        for(i = 0; i < series.length; i++){
          if(!series[i].label || series[i].hide) continue;
          label = legend.labelFormatter(series[i].label);

          ctx.fillStyle = series[i].color;
          ctx.fillRect(x, y, lbw-1, lbh-1);

          ctx.strokeStyle = legend.labelBoxBorderColor;
          ctx.lineWidth = 1;
          ctx.strokeRect(Math.ceil(x)-1.5, Math.ceil(y)-1.5, lbw+2, lbh+2);

          // Legend text
          Flotr.drawText(ctx, label, x + lbw + lbm, y + (lbh + style.size - ctx.fontDescent(style))/2, style);

          y += lbh + lbm;
        }
      }
      else {
        for(i = 0; i < series.length; ++i){
          if(!series[i].label || series[i].hide) continue;

          if(i % legend.noColumns === 0){
            fragments.push(rowStarted ? '

' : '
');
            rowStarted = true;
          }

          // @TODO remove requirement on bars
          var s = series[i],
            boxWidth = legend.labelBoxWidth,
            boxHeight = legend.labelBoxHeight,
            opacityValue = (s.bars ? s.bars.fillOpacity : legend.labelBoxOpacity),
            opacity = 'opacity:' + opacityValue + ';filter:alpha(opacity=' + opacityValue*100 + ');';

          label = legend.labelFormatter(s.label);
          color = 'background-color:' + ((s.bars && s.bars.show && s.bars.fillColor && s.bars.fill) ? s.bars.fillColor : s.color) + ';';

          fragments.push(
            '',
              '
',
                '
', // Border
                  '

', // Background
                '
',
              '
',
            '	',
            '', label, '	'
          );
        }
        if(rowStarted) fragments.push('
');

        if(fragments.length > 0){
          var table = '
' + fragments.join('') + '
';
          if(legend.container){
            D.insert(legend.container, table);
          }
          else {
            var styles = {position: 'absolute', 'z-index': 2};

                 if(p.charAt(0) == 'n') { styles.top = (m + plotOffset.top) + 'px'; styles.bottom = 'auto'; }
            else if(p.charAt(0) == 's') { styles.bottom = (m + plotOffset.bottom) + 'px'; styles.top = 'auto'; }
                 if(p.charAt(1) == 'e') { styles.right = (m + plotOffset.right) + 'px'; styles.left = 'auto'; }
            else if(p.charAt(1) == 'w') { styles.left = (m + plotOffset.left) + 'px'; styles.right = 'auto'; }

            var div = D.create('div'), size;
            div.className = 'flotr-legend';
            D.setStyles(div, styles);
            D.insert(div, table);
            D.insert(this.el, div);

            if(legend.backgroundOpacity !== 0.0)
              return;
            /**
             * Put in the transparent background separately to avoid blended labels and
             * label boxes.
             */
            var c = legend.backgroundColor;
            if(!c){
              var tmp = (options.grid.backgroundColor) ? options.grid.backgroundColor : Flotr.Color.extract(div);
              c = this.processColor(tmp, null, {opacity: 1});
            }
            c = '#ff00ff';

            _.extend(styles, D.size(div), {
              'backgroundColor': c,
              'z-index': 1
            });
            styles.width += 'px';
            styles.height += 'px';

            div = D.create('div');
            div.className = 'flotr-legend-bg';
            D.setStyles(div, styles);
            D.opacity(div, legend.backgroundOpacity);
            D.insert(div, ' ');
            D.insert(this.el, div);
          }
        }
      }
    }
  }
});
<commit_msg>Fixing DOM declaration.<commit_after>(function () {

var D = Flotr.DOM;

Flotr.addPlugin('legend', {
  options: {
    show: true,            // => setting to true will show the legend, hide otherwise
    noColumns: 1,          // => number of colums in legend table // @todo: doesn't work for HtmlText = false
    labelFormatter: function(v){return v;}, // => fn: string -> string
    labelBoxBorderColor: '#CCCCCC', // => border color for the little label boxes
    labelBoxWidth: 14,
    labelBoxHeight: 10,
    labelBoxMargin: 5,
    labelBoxOpacity: 0.4,
    container: null,       // => container (as jQuery object) to put legend in, null means default on top of graph
    position: 'nw',        // => position of default legend container within plot
    margin: 5,             // => distance from grid edge to default legend container within plot
    backgroundColor: null, // => null means auto-detect
    backgroundOpacity: 0.85// => set to 0 to avoid background, set to 1 for a solid background
  },
  callbacks: {
    'flotr:afterinit': function() {
      this.legend.insertLegend();
    }
  },
  /**
   * Adds a legend div to the canvas container or draws it on the canvas.
   */
  insertLegend: function(){

    if(!this.options.legend.show)
      return;

    var series = this.series,
      plotOffset = this.plotOffset,
      options = this.options,
      legend = options.legend,
      fragments = [],
      rowStarted = false,
      ctx = this.ctx,
      noLegendItems = _.filter(series, function(s) {return (s.label && !s.hide);}).length,
      p = legend.position,
      m = legend.margin,
      i, label, color;

    if (noLegendItems) {
      if (!options.HtmlText && this.textEnabled && !legend.container) {
        var style = {
          size: options.fontSize*1.1,
          color: options.grid.color
        };

        var lbw = legend.labelBoxWidth,
            lbh = legend.labelBoxHeight,
            lbm = legend.labelBoxMargin,
            offsetX = plotOffset.left + m,
            offsetY = plotOffset.top + m;

        // We calculate the labels' max width
        var labelMaxWidth = 0;
        for(i = series.length - 1; i > -1; --i){
          if(!series[i].label || series[i].hide) continue;
          label = legend.labelFormatter(series[i].label);
          labelMaxWidth = Math.max(labelMaxWidth, Flotr.measureText(ctx, label, style).width);
        }

        var legendWidth  = Math.round(lbw + lbm*3 + labelMaxWidth),
            legendHeight = Math.round(noLegendItems*(lbm+lbh) + lbm);

        if(p.charAt(0) == 's') offsetY = plotOffset.top + this.plotHeight - (m + legendHeight);
        if(p.charAt(1) == 'e') offsetX = plotOffset.left + this.plotWidth - (m + legendWidth);

        // Legend box
        color = this.processColor(legend.backgroundColor || 'rgb(240,240,240)', {opacity: legend.backgroundOpacity || 0.1});

        ctx.fillStyle = color;
        ctx.fillRect(offsetX, offsetY, legendWidth, legendHeight);
        ctx.strokeStyle = legend.labelBoxBorderColor;
        ctx.strokeRect(Flotr.toPixel(offsetX), Flotr.toPixel(offsetY), legendWidth, legendHeight);

        // Legend labels
        var x = offsetX + lbm;
        var y = offsetY + lbm;
        for(i = 0; i < series.length; i++){
          if(!series[i].label || series[i].hide) continue;
          label = legend.labelFormatter(series[i].label);

          ctx.fillStyle = series[i].color;
          ctx.fillRect(x, y, lbw-1, lbh-1);

          ctx.strokeStyle = legend.labelBoxBorderColor;
          ctx.lineWidth = 1;
          ctx.strokeRect(Math.ceil(x)-1.5, Math.ceil(y)-1.5, lbw+2, lbh+2);

          // Legend text
          Flotr.drawText(ctx, label, x + lbw + lbm, y + (lbh + style.size - ctx.fontDescent(style))/2, style);

          y += lbh + lbm;
        }
      }
      else {
        for(i = 0; i < series.length; ++i){
          if(!series[i].label || series[i].hide) continue;

          if(i % legend.noColumns === 0){
            fragments.push(rowStarted ? '

' : '
');
            rowStarted = true;
          }

          // @TODO remove requirement on bars
          var s = series[i],
            boxWidth = legend.labelBoxWidth,
            boxHeight = legend.labelBoxHeight,
            opacityValue = (s.bars ? s.bars.fillOpacity : legend.labelBoxOpacity),
            opacity = 'opacity:' + opacityValue + ';filter:alpha(opacity=' + opacityValue*100 + ');';

          label = legend.labelFormatter(s.label);
          color = 'background-color:' + ((s.bars && s.bars.show && s.bars.fillColor && s.bars.fill) ? s.bars.fillColor : s.color) + ';';

          fragments.push(
            '',
              '
',
                '
', // Border
                  '

', // Background
                '
',
              '
',
            '	',
            '', label, '	'
          );
        }
        if(rowStarted) fragments.push('
');

        if(fragments.length > 0){
          var table = '
' + fragments.join('') + '
';
          if(legend.container){
            D.insert(legend.container, table);
          }
          else {
            var styles = {position: 'absolute', 'z-index': 2};

                 if(p.charAt(0) == 'n') { styles.top = (m + plotOffset.top) + 'px'; styles.bottom = 'auto'; }
            else if(p.charAt(0) == 's') { styles.bottom = (m + plotOffset.bottom) + 'px'; styles.top = 'auto'; }
                 if(p.charAt(1) == 'e') { styles.right = (m + plotOffset.right) + 'px'; styles.left = 'auto'; }
            else if(p.charAt(1) == 'w') { styles.left = (m + plotOffset.left) + 'px'; styles.right = 'auto'; }

            var div = D.create('div'), size;
            div.className = 'flotr-legend';
            D.setStyles(div, styles);
            D.insert(div, table);
            D.insert(this.el, div);

            if(legend.backgroundOpacity !== 0.0)
              return;
            /**
             * Put in the transparent background separately to avoid blended labels and
             * label boxes.
             */
            var c = legend.backgroundColor;
            if(!c){
              var tmp = (options.grid.backgroundColor) ? options.grid.backgroundColor : Flotr.Color.extract(div);
              c = this.processColor(tmp, null, {opacity: 1});
            }
            c = '#ff00ff';

            _.extend(styles, D.size(div), {
              'backgroundColor': c,
              'z-index': 1
            });
            styles.width += 'px';
            styles.height += 'px';

            div = D.create('div');
            div.className = 'flotr-legend-bg';
            D.setStyles(div, styles);
            D.opacity(div, legend.backgroundOpacity);
            D.insert(div, ' ');
            D.insert(this.el, div);
          }
        }
      }
    }
  }
});
})();
<|endoftext|>


<commit_before>window.addEvent('domready', function() {
  initTypography();
  initBGScroll();
  observeNav();

  var form = new FlippingContactForm($('contact-wrapper'), {});
});

var Project = new Class({
  Implements: [Options, Events],

  options: {
    name: '',
    description: ''
  },

  initialize: function(options) {
    this.setOptions(options);
  }
});

var Portfolio = new Class({
  Implements: [Options, Events],

  options: {
    loadAllProjectsURL: '',
    loadProjectURL: '',
    thumbnailColumns: 3,
    thumbnailWidth: 286,
    thumbnailHeight: 128,
    thumbnailMargin: 20
  },
  projects: [],

  initialize: function(container, options) {
    this.setOptions(options);
    this.container = $(container);
    this.loadAllProjects(this.options.loadAllProjectsURL);
    this.initThumbnails();
    this.renderThumbnails();
  },

  loadAllProjects: function(url) {
    for (i=0; i<9; i++) {
      position = this.computePosition(i+1);
      var p = new Hash();
      p.set('project', new Project({name:'Project '+i}));
      p.set('position', {
        x:position.get('x'),
        y:position.get('y')
      });
      this.projects.include(p);
    }
  },

  initThumbnails: function() {
    new Element('ol', {
      id: 'portfolio'
    }).inject(this.container, 'top');

    this.projects.each(function(p) {
      var thumbnailContainer = new Element('li', {
        styles: {top: p.position.y, left: p.position.x},
      }).inject($('portfolio'), 'bottom');

      thumbnailContainer.adopt(new Element('img', {
        src: '/images/tmp/google.png',
        styles: {top: 128} /* hide images to start with */
      }));
    });
   },

   renderThumbnails: function() {
     $$('ol#portfolio li img').each(function(img, index) {
      (function() {
        img.move({
          relativeTo: img.getParent('li'),
          offset: {x: 0, y: -128},
          transition: Fx.Transitions.Bounce.easeOut
        });
      }).delay(index*80);
     });
   },

   computePosition: function(count) {
     var row = Math.ceil(count / this.options.thumbnailColumns);
     var column = count % this.options.thumbnailColumns;
     if (column == 0) column = 3;
     var x = (column - 1) * (this.options.thumbnailWidth+this.options.thumbnailMargin);
     var y = (row - 1) *  (this.options.thumbnailHeight+this.options.thumbnailMargin);
     var position = new Hash();
     position.set('x', x);
     position.set('y', y);
     return position;
   }
});

var FlippingContactForm = new Class({
  Implements: [Options, Events],

  options: {
    dropDelay: 2500,
    thanksDelay: 3500
  },
  senderName: '',
  senderEmail: '',

  initialize: function(container, options) {
    this.setOptions(options);
    this.container = $(container);
    this.form = this.container.getElement('form');

    new Form.Validator.Inline(this.form);
    new Form.Request(this.form, null, {
        requestOptions: {
          useSpinner: false
        },
        onSend: function() {
          this.flipForm()
        }.bind(this),
        onSuccess: function(target, response) {
          var status = JSON.decode(response[0].data.clean(), true);
          if (status == null) {
            this.showErrorMessage()
          }
          else if (status.code == "1") {
            this.showThanks()
          }
          else {
            this.showErrorMessage()
          }
        }.bind(this),
        onFailure: function() {
          alert('failed');
        }.bind(this)
    });
    $$('#send-another').addEvent('click', function(e) {
      e.stop();
      this.resetForm();
    }.bind(this));
  },

  flipForm: function() {
    $('from').set('html', $('name').get('value'));
    this.senderName = $('name').get('value');
    this.senderEmail = $('email').get('value');
    $$('#mail-slot').show();
    this.container.addClass('flip');
    (function() { this.dropForm(); }).delay(this.options.dropDelay, this);
    if (!Modernizr.csstransforms3d) {
      $('form-wrapper').morph({opacity: 0});
      $('envelope').morph({opacity: 1});
    }
  },

  dropForm: function() {
    this.container.setStyle('overflow', 'hidden');
    this.container.getChildren('.inner').move({
      relativeTo: this.container,
      offset: {x: 0, y: 500},
      transition: Fx.Transitions.Quint.easeIn
    });
  },

  showThanks: function() {
    (function() { $('thanks').reveal({duration: 1000}); }).delay(this.options.thanksDelay, this);
  },

  showErrorMessage: function() {
    (function() { $('error').reveal({duration: 1000}); }).delay(this.options.thanksDelay, this);
  },

  resetForm: function() {
    $$('#thanks').hide();
    $$('#mail-slot').hide();
    this.container.setStyle('overflow', 'visible');
    this.container.removeClass('flip');
    this.container.getChildren('.inner').move({
      relativeTo: this.container,
      offset: {x: 0, y: -500},
      transition: Fx.Transitions.Quint.easeOut
    });
    if (!Modernizr.csstransforms3d) {
      $('form-wrapper').morph({opacity: 1});
      $('envelope').morph({opacity: 0});
    }
    $('name').set('value', this.senderName);
    $('email').set('value', this.senderEmail);
    $('message').set('value', '');
    (function() { $('message').focus(); }).delay(500, this);
  }
});

function observeNav() {
  $$('nav ul li a.section').addEvent('click', function(e) {
    e.stop();
    var myFx = new Fx.Scroll(window).toElement(this.get('data-nav-section'));
  });
}

function initPortfolio() {
  var portfolio = new Portfolio($('portfolio-wrapper'), {
    loadAllProjectsURL: '/load_all_projects.php',
    loadProjectURL: '/load__project.php'
  });
}

function initTypography() {
  try {
    Typekit.load({
      active: function() {
        $$('#content').tween('opacity', '1');
        (function() { initPortfolio(); }).delay(1000);
      },
      inactive: function() {
        $$('#content').tween('opacity', '1');
        (function() { initPortfolio(); }).delay(1000);
      }
    })
  } catch(e) {}
}

function initBGScroll() {
  positionBG();
  window.addEvent('scroll', function(event) {
    positionBG();
  });
}

function positionBG() {
  var scroll = window.getScroll();
  $$('img#bg').setStyle('top', '-' + 0.3*scroll.y + 'px')
}

/*
$$('#slide-out-trigger').addEvent('click', function(e) {
  e.stop();
  $('slider1').move({
    position: 'upperLeft',
    edge: 'upperRight'
  })
  $('slider2').move({
    position: 'upperRight',
    edge: 'upperLeft',
    // offset: {x: 100, y: 0}
  })
});

$$('#slide-in-trigger').addEvent('click', function(e) {
  e.stop();
  $('slider1').move({
    relativeTo: $('content'),
    position: 'upperLeft',
    edge: 'upperLeft',
    transition: Fx.Transitions.Back.easeOut
  })
  $('slider2').move({
    relativeTo: $('content'),
    position: 'upperRight',
    edge: 'upperRight',
    transition: Fx.Transitions.Back.easeOut
  })
});
*/
<commit_msg>hide thumbnails on thumbnail click<commit_after>window.addEvent('domready', function() {
  initTypography();
  initBGScroll();
  observeNav();

  var form = new FlippingContactForm($('contact-wrapper'), {});
});

var Project = new Class({
  Implements: [Options, Events],

  options: {
    name: '',
    description: ''
  },

  initialize: function(options) {
    this.setOptions(options);
  }
});

var Portfolio = new Class({
  Implements: [Options, Events],

  options: {
    loadAllProjectsURL: '',
    loadProjectURL: '',
    thumbnailColumns: 3,
    thumbnailWidth: 286,
    thumbnailHeight: 128,
    thumbnailMargin: 20
  },
  projects: [],

  initialize: function(container, options) {
    this.setOptions(options);
    this.container = $(container);
    this.loadAllProjects(this.options.loadAllProjectsURL);
    this.initThumbnails();
    this.showThumbnails();
  },

  loadAllProjects: function(url) {
    for (i=0; i<9; i++) {
      position = this.computePosition(i+1);
      var p = new Hash();
      p.set('project', new Project({name:'Project '+i}));
      p.set('position', {
        x:position.get('x'),
        y:position.get('y')
      });
      this.projects.include(p);
    }
  },

  initThumbnails: function() {
    new Element('ol', {
      id: 'portfolio'
    }).inject(this.container, 'top');

    this.projects.each(function(p) {
      var thumbnailContainer = new Element('li', {
        styles: {top: p.position.y, left: p.position.x},
      }).inject($('portfolio'), 'bottom');

      var link =
        new Element('a', {
          href: '#'
        }).adopt(
          new Element('img', {
            src: '/images/tmp/google.png',
            styles: {top: 128} /* hide images to start with */
          })
        );

      link.addEvent('click', function(e) {
        e.stop();
        this.hideThumbnails();
      }.bind(this));
      thumbnailContainer.adopt(link);
    }.bind(this));
   },

   showThumbnails: function() {
     $$('ol#portfolio li img').each(function(img, index) {
      (function() {
        img.move({
          relativeTo: img.getParent('li'),
          offset: {x: 0, y: -128},
          transition: Fx.Transitions.Bounce.easeOut
        });
      }).delay(index*80);
     });
   },

   hideThumbnails: function() {
     $$('ol#portfolio li img').each(function(img, index) {
      (function() {
        img.move({
          relativeTo: img.getParent('li'),
          offset: {x: 0, y: 128},
          transition: Fx.Transitions.Back.easeInOut,
          duration: 250
        });
      }).delay(index*30);
     });
   },

   computePosition: function(count) {
     var row = Math.ceil(count / this.options.thumbnailColumns);
     var column = count % this.options.thumbnailColumns;
     if (column == 0) column = 3;
     var x = (column - 1) * (this.options.thumbnailWidth+this.options.thumbnailMargin);
     var y = (row - 1) *  (this.options.thumbnailHeight+this.options.thumbnailMargin);
     var position = new Hash();
     position.set('x', x);
     position.set('y', y);
     return position;
   }
});

var FlippingContactForm = new Class({
  Implements: [Options, Events],

  options: {
    dropDelay: 2500,
    thanksDelay: 3500
  },
  senderName: '',
  senderEmail: '',

  initialize: function(container, options) {
    this.setOptions(options);
    this.container = $(container);
    this.form = this.container.getElement('form');

    new Form.Validator.Inline(this.form);
    new Form.Request(this.form, null, {
        requestOptions: {
          useSpinner: false
        },
        onSend: function() {
          this.flipForm()
        }.bind(this),
        onSuccess: function(target, response) {
          var status = JSON.decode(response[0].data.clean(), true);
          if (status == null) {
            this.showErrorMessage()
          }
          else if (status.code == "1") {
            this.showThanks()
          }
          else {
            this.showErrorMessage()
          }
        }.bind(this),
        onFailure: function() {
          alert('failed');
        }.bind(this)
    });
    $$('#send-another').addEvent('click', function(e) {
      e.stop();
      this.resetForm();
    }.bind(this));
  },

  flipForm: function() {
    $('from').set('html', $('name').get('value'));
    this.senderName = $('name').get('value');
    this.senderEmail = $('email').get('value');
    $$('#mail-slot').show();
    this.container.addClass('flip');
    (function() { this.dropForm(); }).delay(this.options.dropDelay, this);
    if (!Modernizr.csstransforms3d) {
      $('form-wrapper').morph({opacity: 0});
      $('envelope').morph({opacity: 1});
    }
  },

  dropForm: function() {
    this.container.setStyle('overflow', 'hidden');
    this.container.getChildren('.inner').move({
      relativeTo: this.container,
      offset: {x: 0, y: 500},
      transition: Fx.Transitions.Quint.easeIn
    });
  },

  showThanks: function() {
    (function() { $('thanks').reveal({duration: 1000}); }).delay(this.options.thanksDelay, this);
  },

  showErrorMessage: function() {
    (function() { $('error').reveal({duration: 1000}); }).delay(this.options.thanksDelay, this);
  },

  resetForm: function() {
    $$('#thanks').hide();
    $$('#mail-slot').hide();
    this.container.setStyle('overflow', 'visible');
    this.container.removeClass('flip');
    this.container.getChildren('.inner').move({
      relativeTo: this.container,
      offset: {x: 0, y: -500},
      transition: Fx.Transitions.Quint.easeOut
    });
    if (!Modernizr.csstransforms3d) {
      $('form-wrapper').morph({opacity: 1});
      $('envelope').morph({opacity: 0});
    }
    $('name').set('value', this.senderName);
    $('email').set('value', this.senderEmail);
    $('message').set('value', '');
    (function() { $('message').focus(); }).delay(500, this);
  }
});

function observeNav() {
  $$('nav ul li a.section').addEvent('click', function(e) {
    e.stop();
    var myFx = new Fx.Scroll(window).toElement(this.get('data-nav-section'));
  });
}

function initPortfolio() {
  var portfolio = new Portfolio($('portfolio-wrapper'), {
    loadAllProjectsURL: '/load_all_projects.php',
    loadProjectURL: '/load__project.php'
  });
}

function initTypography() {
  try {
    Typekit.load({
      active: function() {
        $$('#content').tween('opacity', '1');
        (function() { initPortfolio(); }).delay(1000);
      },
      inactive: function() {
        $$('#content').tween('opacity', '1');
        (function() { initPortfolio(); }).delay(1000);
      }
    })
  } catch(e) {}
}

function initBGScroll() {
  positionBG();
  window.addEvent('scroll', function(event) {
    positionBG();
  });
}

function positionBG() {
  var scroll = window.getScroll();
  $$('img#bg').setStyle('top', '-' + 0.3*scroll.y + 'px')
}

/*
$$('#slide-out-trigger').addEvent('click', function(e) {
  e.stop();
  $('slider1').move({
    position: 'upperLeft',
    edge: 'upperRight'
  })
  $('slider2').move({
    position: 'upperRight',
    edge: 'upperLeft',
    // offset: {x: 100, y: 0}
  })
});

$$('#slide-in-trigger').addEvent('click', function(e) {
  e.stop();
  $('slider1').move({
    relativeTo: $('content'),
    position: 'upperLeft',
    edge: 'upperLeft',
    transition: Fx.Transitions.Back.easeOut
  })
  $('slider2').move({
    relativeTo: $('content'),
    position: 'upperRight',
    edge: 'upperRight',
    transition: Fx.Transitions.Back.easeOut
  })
});
*/
<|endoftext|>


<commit_before>
/**
 * Module dependencies.
 */

var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var grooveshark = require('./grooveshark');

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

//yea sorry global
var playlist = [];

app.post('/add', function(req,res){
    var data = req.body.search.split(", ");
    console.log(data);
	grooveshark.search(data,function(data){
		playlist.push(data);

    });
});

app.post('/vote',function(req,res){
	console.log(req.body.id);
	console.log(req.body.vote);
	for(i=0;i<playlist.length;i++){
		if(playlist[i].SongID == req.body.id){
			if(req.body.vote == 'd'){
				playlist[i].val--;
			}
			if(req.body.vote == 'u'){
				playlist[i].val++;
			}
		}
	}
});

app.get('/playlist',function(req,res){
	res.send(playlist);
});

app.get('/users', user.list);

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});
<commit_msg>fixed multiple entries<commit_after>
/**
 * Module dependencies.
 */

var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var grooveshark = require('./grooveshark');

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

//yea sorry global
var playlist = [];

app.post('/add', function(req,res){
    var data = req.body.search.split(", ");
    console.log(data);
	grooveshark.search(data,function(data){

		var isThere = false;

		for(i=0;i<playlist.length;i++){
			if(playlist[i].SongID == data.SongID){
				playlist[i].val++;
				isThere = true;
			}
		}
		if(!isThere){
			playlist.push(data);
		}

    });
});

app.post('/vote',function(req,res){
	console.log(req.body.id);
	console.log(req.body.vote);
	for(i=0;i<playlist.length;i++){
		if(playlist[i].SongID == req.body.id){
			if(req.body.vote == 'd'){
				playlist[i].val--;
			}
			if(req.body.vote == 'u'){
				playlist[i].val++;
			}
		}
	}
});

app.get('/playlist',function(req,res){
	res.send(playlist);
});

app.get('/users', user.list);

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});
<|endoftext|>


<commit_before>var express         = require('express'),
	bodyParser      = require('body-parser');

var sql             = require('mssql'),
	util            = require('../util');

module.exports      = function (configuration) {
	var router      = express.Router(),
	authenticate    = require('azure-mobile-apps/src/express/middleware/authenticate')(configuration),
	authorize       = require('azure-mobile-apps/src/express/middleware/authorize');

	var completeError = function(err, res) {
		if (err) {
			console.error(err);
			if (res) res.sendStatus(500);
		}
	};

	router.get('/:voucher', (req, res, next) => {
		console.log('in GET /private_invitation/:voucher');
		var voucher = req.params.voucher;
		var body = `
<link rel="stylesheet" type="text/css" href="/tertulias.css">

Tertulias

Welcome to Tertulias platform site.

You arrived at this page because you followed a link with a private invitation from a friend of yours, to join a Tertulia managed by him.

Your voucher number is .

In order to join the Tertulia, press the button bellow (You will be asked to authenticate with your authentication provider).

	<button id='action' onclick="onClickAction('userIdMessagePlaceHolder')">Subscribe</button>

`;
		res.send(body);
		next();
	});
	return router;
};
<commit_msg>wip save<commit_after>var express         = require('express'),
	bodyParser      = require('body-parser');

var sql             = require('mssql'),
	util            = require('../util');

module.exports      = function (configuration) {
	var router      = express.Router(),
	authenticate    = require('azure-mobile-apps/src/express/middleware/authenticate')(configuration),
	authorize       = require('azure-mobile-apps/src/express/middleware/authorize');

	var completeError = function(err, res) {
		if (err) {
			console.error(err);
			if (res) res.sendStatus(500);
		}
	};

	router.get('/:voucher', (req, res, next) => {
		console.log('in GET /private_invitation/:voucher');
		var voucher = req.params.voucher;
		var body = `
<link rel="stylesheet" type="text/css" href="/tertulias.css">

Tertulias

Welcome to Tertulias platform site.

You arrived at this page because you followed a link with a private invitation from a friend of yours, to join a Tertulia managed by him.

Your voucher number is .

In order to join the Tertulia, press the button bellow (You will be asked to authenticate with your authentication provider).

	<button id='action' onclick="onClickAction('userIdMessagePlaceHolder')">Subscribe</button>

`;
		res.send(body);
		next();
	});
	return router;
};
<|endoftext|>


<commit_before>//iTop Designer widget for editing properties line by line
$(function()
{
	// the widget definition, where "itop" is the namespace,
	// "property_field" the widget name
	$.widget( "itop.property_field",
	{
		// default options
		options:
		{
			parent_selector: null,
			field_id: '',
			get_field_value: null,
			equals: null,
			submit_to: 'index.php',
			submit_parameters: {operation: 'async_action'},
			do_apply: null,
			do_cancel: null,
			auto_apply: false
		},

		// the constructor
		_create: function()
		{
			var me = this;

			this.element
				.addClass( "itop-property-field" )
				.bind('apply_changes.itop-property-field', function(){me._do_apply();} );

			this.bModified = false;

			if (this.options.field_id != '')
			{
				// In case there is an hidden input having the same id (somewhere else in the page), the change event does not occur unless the input loses the focus
				// To reduce the impact, let's handle keyup as well
				$('#'+this.options.field_id, this.element).bind('change.itop-property-field keyup.itop-property-field', function() { me._on_change(); });
				this.value = this._get_field_value();
			}
			this.element.find(".prop_apply").bind('click.itop-property-field', function() { me._do_apply(); });
			this.element.find(".prop_cancel").bind('click.itop-property-field', function() { me._do_cancel(); });

			this._refresh();
		},

		// called when created, and later when changing options
		_refresh: function()
		{
			if (this.bModified)
			{
				this.element.addClass("itop-property-field-modified");
				this.element.find(".prop_icon span.ui-icon-circle-check").css({visibility: ''});
				this.element.find(".prop_icon span.ui-icon-circle-close").css({visibility: ''});
			}
			else
			{
				this.element.removeClass("itop-property-field-modified");
				this.element.find(".prop_icon span.ui-icon-circle-check").css({visibility: 'hidden'});
				this.element.find(".prop_icon span.ui-icon-circle-close").css({visibility: 'hidden'});
			}
		},

		// events bound via _bind are removed automatically
		// revert other modifications here
		_destroy: function()
		{
			this.element.removeClass( "itop-property-field" );
			this.element.removeClass("itop-property-field-modified");
		},

		// _setOptions is called with a hash of all options that are changing
		// always refresh when changing options
		_setOptions: function()
		{
			// in 1.9 would use _superApply
			this._superApply(arguments);
			this._refresh();
		},

		// _setOption is called for each individual option that is changing
		_setOption: function( key, value )
		{
			// in 1.9 would use _super
			this._superApply(arguments);
		},
		_on_change: function()
		{
			var new_value = this._get_field_value();
			if (this._equals(new_value, this.value))
			{
				this.bModified = false;
			}
			else
			{
				this.bModified = true;
				if (this.options.auto_apply)
				{
					this._do_apply();
				}
			}
			this._refresh();
		},
		_equals: function( value1, value2 )
		{
			if (this.options.equals === null)
			{
				return value1 == value2;
			}
			else
			{
				return this.options.equals(value1, value2);
			}
		},
		_get_field_value: function()
		{
			if (this.options.get_field_value === null)
			{
				var oField = $('#'+this.options.field_id, this.element);
				if (oField.attr('type') == 'checkbox')
				{
					return (oField.attr('checked') == 'checked');
				}
				else
				{
					return oField.val();
				}
			}
			else
			{
				return this.options.get_field_value();
			}
		},
		_get_committed_value: function()
		{
			return { name: $('#'+this.options.field_id, this.element).attr('name'), value: this.value };
		},
		_do_apply: function()
		{
			if (this.options.parent_selector)
			{
				$(this.options.parent_selector).trigger('mark_as_modified');
			}
			if (this.options.do_apply)
			{
				// specific behavior...
				if (this.options.do_apply())
				{
					this.bModified = false;
					this.previous_value = this.value;
					this.value = this._get_field_value();
					this._refresh();
				}
			}
			else
			{
				// Validate the field
				sFormId = this.element.closest('form').attr('id');
				var oField = $('#'+this.options.field_id, this.element);
				oField.trigger('validate');
				if ( $.inArray(this.options.field_id, oFormValidation[sFormId]) == -1)
				{
					this.bModified = false;
					this.previous_value = this.value;
					this.value = this._get_field_value();
					this._do_submit();
					this._refresh();
				}
			}
		},
		_do_cancel: function()
		{
			if (this.options.do_cancel)
			{
				// specific behavior...
				this.options.do_cancel();
			}
			else
			{
				this.bModified = false;
				var oField = $('#'+this.options.field_id, this.element);
				if (oField.attr('type') == 'checkbox')
				{
					if (this.value)
					{
						oField.attr('checked', true);
					}
					else
					{
						oField.removeAttr('checked');
					}
				}
				else
				{
					oField.val(this.value);
				}
				this._refresh();
				oField.trigger('reverted', {type: 'designer', previous_value: this.value });
				oField.trigger('validate');
			}
		},
		_do_submit: function()
		{
			var oData = {};
			this.element.closest('form').find(':input[type=hidden]').each(function()
			{
				// Hidden form fields
				oData[$(this).attr('name')] = $(this).val();
			});
			this.element.closest('form').find('.itop-property-field').each(function()
			{
				var oWidget = $(this).data('itopProperty_field');
				if (oWidget && oWidget._is_visible())
				{
					var oVal = oWidget._get_committed_value();
					oData[oVal.name] = oVal.value;
				}
			});
			oPostedData = this.options.submit_parameters;
			oPostedData.params = oData;
			oPostedData.params.updated = [ $('#'+this.options.field_id, this.element).attr('name') ]; // only one field updated in this case
			oPostedData.params.previous_values = {};
			oPostedData.params.previous_values[oPostedData.params.updated] = this.previous_value; // pass also the previous value(s)
			$.post(this.options.submit_to, oPostedData, function(data)
			{
				$('#prop_submit_result').html(data);
			});
		},
		_is_visible: function()
		{
			return this.element.is(':visible');
		}
	});
});

var oFormValidation = {};

function ValidateWithPattern(sFieldId, bMandatory, sPattern, sFormId, aForbiddenValues, sExplainForbiddenValues)
{
	var currentVal = $('#'+sFieldId).val();
	var bValid = true;
	var sMessage = null;

	if (bMandatory && (currentVal == ''))
	{
		bValid = false;
	}
	if ((sPattern != '') && (currentVal != ''))
	{
		re = new RegExp(sPattern);
		bValid = re.test(currentVal);
	}
	if (aForbiddenValues)
	{
		for(var i in aForbiddenValues)
		{
			if (aForbiddenValues[i] == currentVal)
			{
				bValid = false;
				sMessage = sExplainForbiddenValues;
				break;
			}
		}
	}

	if (oFormValidation[sFormId] == undefined) oFormValidation[sFormId] = [];
	if (!bValid)
	{
		$('#v_'+sFieldId).addClass('ui-state-error');
		iFieldIdPos = jQuery.inArray(sFieldId, oFormValidation[sFormId]);
		if (iFieldPos == -1)
		{
			oFormValidation[sFormId].push(sFieldId);
		}
		if (sMessage)
		{
			$('#'+sFieldId).attr('title', sMessage).tooltip();
			if ($('#'+sFieldId).is(":focus"))
			{
				$('#'+sFieldId).tooltip('open');
			}
		}
	}
	else
	{
		$('#v_'+sFieldId).removeClass('ui-state-error');
		if ($('#'+sFieldId).data('uiTooltip'))
		{
			$('#'+sFieldId).tooltip('close');
		}
		$('#'+sFieldId).removeAttr('title');
		// Remove the element from the array
		iFieldIdPos = jQuery.inArray(sFieldId, oFormValidation[sFormId]);
		if (iFieldIdPos > -1)
		{
			oFormValidation[sFormId].splice(iFieldIdPos, 1);
		}
	}
}

function ValidateForm(sFormId, bValidateAll)
{
	oFormValidation[sFormId] = [];
	if (bValidateAll)
	{
		$('#'+sFormId+' :input').trigger('validate');
	}
	else
	{
		// Only the visible fields
		$('#'+sFormId+' :input:visible').each(function() {
			$(this).trigger('validate');
		});
	}
	return oFormValidation[sFormId];
}

function ReadFormParams(sFormId)
{
	var oMap = { };
	$('#'+sFormId+' :input').each( function() {
		if ($(this).parent().is(':visible'))
		{
			var sName = $(this).attr('name');
			if (sName && sName != '')
			{
				if (this.type == 'checkbox')
				{
					oMap[sName] = ($(this).attr('checked') == 'checked');
				}
				else
				{
					oMap[sName] = $(this).val();
				}
			}
		}
	});
	return oMap;
}

function SubmitForm(sFormId, onSubmitResult)
{
	var aErrors = ValidateForm(sFormId, false);
	if (aErrors.length == 0)
	{
		var oMap = ReadFormParams(sFormId);
		oMap.module_name = sCurrentModule;
		$('#'+sFormId+' :input').each( function() {
			if ($(this).parent().is(':visible'))
			{
				var sName = $(this).attr('name');
				if (sName && sName != '')
				{
					if (this.type == 'checkbox')
					{
						oMap[sName] = ($(this).attr('checked') == 'checked');
					}
					else
					{
						oMap[sName] = $(this).val();
					}

				}
			}
		});
		$.post(GetAbsoluteUrlAppRoot()+'designer/module.php', oMap, function(data)
				{
					onSubmitResult(data);
				});
	}
	else
	{
		// TODO: better error reporting !!!
		alert('Please fill all the fields before continuing...');
	}
}

function RemoveSubForm(sId, sUrl, oParams)
{
	$.post(sUrl, oParams, function(data) {
		$('body').append(data);
	});
}

function AddSubForm(sId, sUrl, oParams)
{
	var aIndexes = JSON.parse($('#'+sId).val());
	var iLast = aIndexes[aIndexes.length - 1];
	var iNewIdx = 1 + iLast;
	oParams.new_index = iNewIdx;

	$.post(sUrl, oParams, function(data) {
		$('body').append(data);
	});
}

function InitFormSelectorField(sId, sSelector)
{
	$('#'+sId).bind('change reverted init', function() {
		// Mark all the direct children as hidden
		$('tr[data-selector="'+sSelector+'"]').attr('data-state', 'hidden');
		// Mark the selected one as visible
		var sSelectedHierarchy = sSelector+'-'+this.value;
		$('tr[data-path="'+sSelectedHierarchy+'"]').attr('data-state', 'visible');

		// Show all items behind the current one
		$('tr[data-path^="'+sSelector+'"]').show();
		// Hide items behind the current one as soon as it is behind a hidden node (or itself is marked as hidden)
		$('tr[data-path^="'+sSelector+'"][data-state="hidden"]').each(function() {
			$(this).hide();
			var sPath = $(this).attr('data-path');
			$('tr[data-path^="'+sPath+'/"]').hide();
		});
	}).trigger('init'); // initial refresh
}
<commit_msg>Oops, typo in "Prevent the JS validation (on focus) to create multiple entries for the same field, since it breaks the validation."<commit_after>//iTop Designer widget for editing properties line by line
$(function()
{
	// the widget definition, where "itop" is the namespace,
	// "property_field" the widget name
	$.widget( "itop.property_field",
	{
		// default options
		options:
		{
			parent_selector: null,
			field_id: '',
			get_field_value: null,
			equals: null,
			submit_to: 'index.php',
			submit_parameters: {operation: 'async_action'},
			do_apply: null,
			do_cancel: null,
			auto_apply: false
		},

		// the constructor
		_create: function()
		{
			var me = this;

			this.element
				.addClass( "itop-property-field" )
				.bind('apply_changes.itop-property-field', function(){me._do_apply();} );

			this.bModified = false;

			if (this.options.field_id != '')
			{
				// In case there is an hidden input having the same id (somewhere else in the page), the change event does not occur unless the input loses the focus
				// To reduce the impact, let's handle keyup as well
				$('#'+this.options.field_id, this.element).bind('change.itop-property-field keyup.itop-property-field', function() { me._on_change(); });
				this.value = this._get_field_value();
			}
			this.element.find(".prop_apply").bind('click.itop-property-field', function() { me._do_apply(); });
			this.element.find(".prop_cancel").bind('click.itop-property-field', function() { me._do_cancel(); });

			this._refresh();
		},

		// called when created, and later when changing options
		_refresh: function()
		{
			if (this.bModified)
			{
				this.element.addClass("itop-property-field-modified");
				this.element.find(".prop_icon span.ui-icon-circle-check").css({visibility: ''});
				this.element.find(".prop_icon span.ui-icon-circle-close").css({visibility: ''});
			}
			else
			{
				this.element.removeClass("itop-property-field-modified");
				this.element.find(".prop_icon span.ui-icon-circle-check").css({visibility: 'hidden'});
				this.element.find(".prop_icon span.ui-icon-circle-close").css({visibility: 'hidden'});
			}
		},

		// events bound via _bind are removed automatically
		// revert other modifications here
		_destroy: function()
		{
			this.element.removeClass( "itop-property-field" );
			this.element.removeClass("itop-property-field-modified");
		},

		// _setOptions is called with a hash of all options that are changing
		// always refresh when changing options
		_setOptions: function()
		{
			// in 1.9 would use _superApply
			this._superApply(arguments);
			this._refresh();
		},

		// _setOption is called for each individual option that is changing
		_setOption: function( key, value )
		{
			// in 1.9 would use _super
			this._superApply(arguments);
		},
		_on_change: function()
		{
			var new_value = this._get_field_value();
			if (this._equals(new_value, this.value))
			{
				this.bModified = false;
			}
			else
			{
				this.bModified = true;
				if (this.options.auto_apply)
				{
					this._do_apply();
				}
			}
			this._refresh();
		},
		_equals: function( value1, value2 )
		{
			if (this.options.equals === null)
			{
				return value1 == value2;
			}
			else
			{
				return this.options.equals(value1, value2);
			}
		},
		_get_field_value: function()
		{
			if (this.options.get_field_value === null)
			{
				var oField = $('#'+this.options.field_id, this.element);
				if (oField.attr('type') == 'checkbox')
				{
					return (oField.attr('checked') == 'checked');
				}
				else
				{
					return oField.val();
				}
			}
			else
			{
				return this.options.get_field_value();
			}
		},
		_get_committed_value: function()
		{
			return { name: $('#'+this.options.field_id, this.element).attr('name'), value: this.value };
		},
		_do_apply: function()
		{
			if (this.options.parent_selector)
			{
				$(this.options.parent_selector).trigger('mark_as_modified');
			}
			if (this.options.do_apply)
			{
				// specific behavior...
				if (this.options.do_apply())
				{
					this.bModified = false;
					this.previous_value = this.value;
					this.value = this._get_field_value();
					this._refresh();
				}
			}
			else
			{
				// Validate the field
				sFormId = this.element.closest('form').attr('id');
				var oField = $('#'+this.options.field_id, this.element);
				oField.trigger('validate');
				if ( $.inArray(this.options.field_id, oFormValidation[sFormId]) == -1)
				{
					this.bModified = false;
					this.previous_value = this.value;
					this.value = this._get_field_value();
					this._do_submit();
					this._refresh();
				}
			}
		},
		_do_cancel: function()
		{
			if (this.options.do_cancel)
			{
				// specific behavior...
				this.options.do_cancel();
			}
			else
			{
				this.bModified = false;
				var oField = $('#'+this.options.field_id, this.element);
				if (oField.attr('type') == 'checkbox')
				{
					if (this.value)
					{
						oField.attr('checked', true);
					}
					else
					{
						oField.removeAttr('checked');
					}
				}
				else
				{
					oField.val(this.value);
				}
				this._refresh();
				oField.trigger('reverted', {type: 'designer', previous_value: this.value });
				oField.trigger('validate');
			}
		},
		_do_submit: function()
		{
			var oData = {};
			this.element.closest('form').find(':input[type=hidden]').each(function()
			{
				// Hidden form fields
				oData[$(this).attr('name')] = $(this).val();
			});
			this.element.closest('form').find('.itop-property-field').each(function()
			{
				var oWidget = $(this).data('itopProperty_field');
				if (oWidget && oWidget._is_visible())
				{
					var oVal = oWidget._get_committed_value();
					oData[oVal.name] = oVal.value;
				}
			});
			oPostedData = this.options.submit_parameters;
			oPostedData.params = oData;
			oPostedData.params.updated = [ $('#'+this.options.field_id, this.element).attr('name') ]; // only one field updated in this case
			oPostedData.params.previous_values = {};
			oPostedData.params.previous_values[oPostedData.params.updated] = this.previous_value; // pass also the previous value(s)
			$.post(this.options.submit_to, oPostedData, function(data)
			{
				$('#prop_submit_result').html(data);
			});
		},
		_is_visible: function()
		{
			return this.element.is(':visible');
		}
	});
});

var oFormValidation = {};

function ValidateWithPattern(sFieldId, bMandatory, sPattern, sFormId, aForbiddenValues, sExplainForbiddenValues)
{
	var currentVal = $('#'+sFieldId).val();
	var bValid = true;
	var sMessage = null;

	if (bMandatory && (currentVal == ''))
	{
		bValid = false;
	}
	if ((sPattern != '') && (currentVal != ''))
	{
		re = new RegExp(sPattern);
		bValid = re.test(currentVal);
	}
	if (aForbiddenValues)
	{
		for(var i in aForbiddenValues)
		{
			if (aForbiddenValues[i] == currentVal)
			{
				bValid = false;
				sMessage = sExplainForbiddenValues;
				break;
			}
		}
	}

	if (oFormValidation[sFormId] == undefined) oFormValidation[sFormId] = [];
	if (!bValid)
	{
		$('#v_'+sFieldId).addClass('ui-state-error');
		iFieldIdPos = jQuery.inArray(sFieldId, oFormValidation[sFormId]);
		if (iFieldIdPos == -1)
		{
			oFormValidation[sFormId].push(sFieldId);
		}
		if (sMessage)
		{
			$('#'+sFieldId).attr('title', sMessage).tooltip();
			if ($('#'+sFieldId).is(":focus"))
			{
				$('#'+sFieldId).tooltip('open');
			}
		}
	}
	else
	{
		$('#v_'+sFieldId).removeClass('ui-state-error');
		if ($('#'+sFieldId).data('uiTooltip'))
		{
			$('#'+sFieldId).tooltip('close');
		}
		$('#'+sFieldId).removeAttr('title');
		// Remove the element from the array
		iFieldIdPos = jQuery.inArray(sFieldId, oFormValidation[sFormId]);
		if (iFieldIdPos > -1)
		{
			oFormValidation[sFormId].splice(iFieldIdPos, 1);
		}
	}
}

function ValidateForm(sFormId, bValidateAll)
{
	oFormValidation[sFormId] = [];
	if (bValidateAll)
	{
		$('#'+sFormId+' :input').trigger('validate');
	}
	else
	{
		// Only the visible fields
		$('#'+sFormId+' :input:visible').each(function() {
			$(this).trigger('validate');
		});
	}
	return oFormValidation[sFormId];
}

function ReadFormParams(sFormId)
{
	var oMap = { };
	$('#'+sFormId+' :input').each( function() {
		if ($(this).parent().is(':visible'))
		{
			var sName = $(this).attr('name');
			if (sName && sName != '')
			{
				if (this.type == 'checkbox')
				{
					oMap[sName] = ($(this).attr('checked') == 'checked');
				}
				else
				{
					oMap[sName] = $(this).val();
				}
			}
		}
	});
	return oMap;
}

function SubmitForm(sFormId, onSubmitResult)
{
	var aErrors = ValidateForm(sFormId, false);
	if (aErrors.length == 0)
	{
		var oMap = ReadFormParams(sFormId);
		oMap.module_name = sCurrentModule;
		$('#'+sFormId+' :input').each( function() {
			if ($(this).parent().is(':visible'))
			{
				var sName = $(this).attr('name');
				if (sName && sName != '')
				{
					if (this.type == 'checkbox')
					{
						oMap[sName] = ($(this).attr('checked') == 'checked');
					}
					else
					{
						oMap[sName] = $(this).val();
					}

				}
			}
		});
		$.post(GetAbsoluteUrlAppRoot()+'designer/module.php', oMap, function(data)
				{
					onSubmitResult(data);
				});
	}
	else
	{
		// TODO: better error reporting !!!
		alert('Please fill all the fields before continuing...');
	}
}

function RemoveSubForm(sId, sUrl, oParams)
{
	$.post(sUrl, oParams, function(data) {
		$('body').append(data);
	});
}

function AddSubForm(sId, sUrl, oParams)
{
	var aIndexes = JSON.parse($('#'+sId).val());
	var iLast = aIndexes[aIndexes.length - 1];
	var iNewIdx = 1 + iLast;
	oParams.new_index = iNewIdx;

	$.post(sUrl, oParams, function(data) {
		$('body').append(data);
	});
}

function InitFormSelectorField(sId, sSelector)
{
	$('#'+sId).bind('change reverted init', function() {
		// Mark all the direct children as hidden
		$('tr[data-selector="'+sSelector+'"]').attr('data-state', 'hidden');
		// Mark the selected one as visible
		var sSelectedHierarchy = sSelector+'-'+this.value;
		$('tr[data-path="'+sSelectedHierarchy+'"]').attr('data-state', 'visible');

		// Show all items behind the current one
		$('tr[data-path^="'+sSelector+'"]').show();
		// Hide items behind the current one as soon as it is behind a hidden node (or itself is marked as hidden)
		$('tr[data-path^="'+sSelector+'"][data-state="hidden"]').each(function() {
			$(this).hide();
			var sPath = $(this).attr('data-path');
			$('tr[data-path^="'+sPath+'/"]').hide();
		});
	}).trigger('init'); // initial refresh
}
<|endoftext|>


<commit_before>'use strict';

var ApiError = require('../utils/ApiError'),
    winston = require('winston'),
    logger = winston.loggers.get('webapi'),
    JID = require('node-xmpp-core').JID,
    apiutils = require('../utils/utils');

var UserManager = require('../lib/user');

var routes = function (app, storage, settings) {

    logger.info('register room routes');

    var domain = settings.get('domain');
    var usrManager = new UserManager(storage);

    /**
     * Get room
     * restriction: only owner and members can access this information
     */
    app.get('/api/rooms/:owner/:room', function (req, res) {

        // requester, should be member of the room
        var jid = apiutils.getJid(req);

        var username = req.params.owner;
        var roomname = req.params.room;

        logger.debug('Get room: ' +  username + '/' + roomname);

        var ownerjid = new JID(username + '@' + domain);

        var usr = null;
        var r = null;
        usrManager.findUser(jid).then(function (user) {
            usr = user;
            return usrManager.findUser(ownerjid.toString());
        }).then(function(owner){
            return usrManager.getRoom(owner, roomname);
        }).then(function(room) {
            r = room;
            return room.isMember(usr);
        }).then(function() {
            res.json(r);
        }).catch(function(err) {
            console.error(err);
            logger.error(err);
            res.json(404, new ApiError('not found'));
        });
    });

    /**
     * Edit room
     * restriction: only owner and members can access this information
     */
    app.patch('/api/rooms/:owner/:room', function (req, res) {
        res.json(404, new ApiError('not found'));
    });

    /**
     * Delete a room (requires admin access)
     * restriction: only owner can do this
     */
    app.del('/api/rooms/:owner/:room', function (req, res) {
        var username = req.params.owner;
        var roomname = req.params.room;

        logger.debug('Delete room: ' +  username + '/' + roomname);

        // requester, should be member of the room
        var jid = new JID(apiutils.getJid(req));
        var ownerjid = new JID(username + '@' + domain);

        // verify that owner and requestor are the same
        if (!ownerjid.equals(jid)) {
            res.send(404);
            return;
        }

        // since only owner can delete rooms, we try to delete the room directly
        usrManager.findUser(jid.toString()).then(function (user) {
            return usrManager.getRoom(user, roomname);
        }).then(function(room) {
            return usrManager.delRoom(room);
        }).then(function() {
            res.send(204);
        }).catch(function(err) {
            console.error(err);
            logger.error(err);
            res.json(404, new ApiError('not found'));
        });
    });

    /**
     * List members
     * restriction: only owner and members can access this information
     */
    app.get('/api/rooms/:owner/:room/members', function(req, res) {

        // extract parameter
        var username = req.params.owner;
        var roomname = req.params.room;

        logger.debug('Get room: ' +  username + '/' + roomname);

        // requester, should be member of the room
        var jid = new JID(apiutils.getJid(req));
        var ownerjid = new JID(username + '@' + domain);

        var usr = null;
        var r = null;
        usrManager.findUser(jid.toString()).then(function (user) {
            usr = user;
            return usrManager.findUser(ownerjid.toString());
        }).then(function(owner){
            return usrManager.getRoom(owner, roomname);
        }).then(function(room) {
            r = room;
            return room.isMember(usr);
        }).then(function() {
            return r.getMembers();
        }).then(function(members) {
            res.json(apiutils.exportJSON(members));
        }).catch(function(err) {
            console.error(err);
            logger.error(err);
            res.json(404, new ApiError('not found'));
        });
    });

    /**
     * Check if a user is a member
     * restriction: only owner and members can access this information
     */
    app.get('/api/rooms/:owner/:room/members/:user', function(req, res) {

        // extract parameter
        var username = req.params.owner;
        var roomname = req.params.room;
        var membername = req.params.user;

        logger.debug('Get room: ' +  username + '/' + roomname);

        // requester, should be member of the room
        var jid = new JID(apiutils.getJid(req));

        // owner of the room
        var ownerjid = new JID(username + '@' + domain);

        // check if this user is member of the room
        var memberjid = new JID(membername);

        var usr = null;
        var r = null;
        var mem = null;

        // check if the "member" is a known user
        usrManager.findUser(memberjid.toString()).then(function(member){
            mem = member;
            // check if the requestor is a known user
            return usrManager.findUser(jid.toString());
        }).then(function (user) {
            usr = user;
            // check if the owner of the room is a known user
            return usrManager.findUser(ownerjid.toString());
        }).then(function(owner){
            // check if the owner has such room
            return usrManager.getRoom(owner, roomname);
        }).then(function(room) {
            r = room;
            // check if the requestor is member of the room
            return room.isMember(usr);
        }).then(function() {
            // check if the requested member is really a member of the room
            return r.isMember(mem);
        }).then(function() {
            res.send(204);
        }).catch(function(err) {
            console.error(err);
            logger.error(err);
            res.send(404);
        });
    });

    /**
     * Add user as a member
     * restriction: only owners can do this
     */
    app.put('/api/rooms/:owner/:room/members/:user', function(req, res) {
        // extract parameter
        var username = req.params.owner;
        var roomname = req.params.room;
        var membername = req.params.user;

        logger.debug('Add member to room: ' +  username + '/' + roomname);

        // requester, should be member of the room
        var jid = new JID(apiutils.getJid(req));

        // owner of the room
        var ownerjid = new JID(username + '@' + domain);

        // check if this user is member of the room
        var memberjid = new JID(membername);

        // verify that owner and requestor are the same
        if (!ownerjid.equals(jid)) {
            res.send(404);
            return;
        }

        var mem;

        // check if the "member" is a known user
        usrManager.findUser(memberjid.toString()).then(function(member){
            mem = member;
            // check if the requestor is a known user
            return usrManager.findUser(jid.toString());
        }).then(function(owner){
            // check if the owner has such room
            return usrManager.getRoom(owner, roomname);
        }).then(function(room) {
            console.log('add');
            // add member to room
            return usrManager.addMember(room, mem);
        }).then(function() {
            res.send(204);
        }).catch(function(err) {
            console.error(err);
            logger.error(err);
            res.send(404);
        });
    });

    /**
     * Remove user as a member
     * restriction: only owners can do this
     */
    app.del('/api/rooms/:owner/:room/members/:user', function(req, res) {
        // extract parameter
        var username = req.params.owner;
        var roomname = req.params.room;
        var membername = req.params.user;

        logger.debug('Add member to room: ' +  username + '/' + roomname);

        // requester, should be member of the room
        var jid = new JID(apiutils.getJid(req));

        // owner of the room
        var ownerjid = new JID(username + '@' + domain);

        // check if this user is member of the room
        var memberjid = new JID(membername);

        // verify that owner and requestor are the same
        if (!ownerjid.equals(jid)) {
            res.send(404);
            return;
        }

        var mem;

        // check if the "member" is a known user
        usrManager.findUser(memberjid.toString()).then(function(member){
            mem = member;
            // check if the requestor is a known user
            return usrManager.findUser(jid.toString());
        }).then(function(owner){
            // check if the owner has such room
            return usrManager.getRoom(owner, roomname);
        }).then(function(room) {
            // add member to room
            return usrManager.removeMember(room, mem);
        }).then(function() {
            res.send(204);
        }).catch(function(err) {
            console.error(err);
            logger.error(err);
            res.send(404);
        });
    });

    /**
     * List messages for a room
     */
    app.get('/api/rooms/:owner/:room/messages', function(req, res) {
        res.json({});
    });

    /**
     * Get a single message
     */
    app.get('/api/rooms/:owner/:room/messages/:number', function(req, res) {
        res.json({});
    });

    /**
     * Create an message
     */
    app.post('/api/rooms/:owner/:room/messages', function(req, res) {
        res.json({});
    });

    /**
     * Edit an message
     */
    app.patch('/api/rooms/:owner/:room/messages/:number', function(req, res) {
        res.json({});
    });

};

// Expose routes
module.exports = routes;<commit_msg>fix upercase filename in dependency<commit_after>'use strict';

var ApiError = require('../utils/ApiError'),
    winston = require('winston'),
    logger = winston.loggers.get('webapi'),
    JID = require('node-xmpp-core').JID,
    apiutils = require('../utils/utils');

var UserManager = require('../lib/User');

var routes = function (app, storage, settings) {

    logger.info('register room routes');

    var domain = settings.get('domain');
    var usrManager = new UserManager(storage);

    /**
     * Get room
     * restriction: only owner and members can access this information
     */
    app.get('/api/rooms/:owner/:room', function (req, res) {

        // requester, should be member of the room
        var jid = apiutils.getJid(req);

        var username = req.params.owner;
        var roomname = req.params.room;

        logger.debug('Get room: ' +  username + '/' + roomname);

        var ownerjid = new JID(username + '@' + domain);

        var usr = null;
        var r = null;
        usrManager.findUser(jid).then(function (user) {
            usr = user;
            return usrManager.findUser(ownerjid.toString());
        }).then(function(owner){
            return usrManager.getRoom(owner, roomname);
        }).then(function(room) {
            r = room;
            return room.isMember(usr);
        }).then(function() {
            res.json(r);
        }).catch(function(err) {
            console.error(err);
            logger.error(err);
            res.json(404, new ApiError('not found'));
        });
    });

    /**
     * Edit room
     * restriction: only owner and members can access this information
     */
    app.patch('/api/rooms/:owner/:room', function (req, res) {
        res.json(404, new ApiError('not found'));
    });

    /**
     * Delete a room (requires admin access)
     * restriction: only owner can do this
     */
    app.del('/api/rooms/:owner/:room', function (req, res) {
        var username = req.params.owner;
        var roomname = req.params.room;

        logger.debug('Delete room: ' +  username + '/' + roomname);

        // requester, should be member of the room
        var jid = new JID(apiutils.getJid(req));
        var ownerjid = new JID(username + '@' + domain);

        // verify that owner and requestor are the same
        if (!ownerjid.equals(jid)) {
            res.send(404);
            return;
        }

        // since only owner can delete rooms, we try to delete the room directly
        usrManager.findUser(jid.toString()).then(function (user) {
            return usrManager.getRoom(user, roomname);
        }).then(function(room) {
            return usrManager.delRoom(room);
        }).then(function() {
            res.send(204);
        }).catch(function(err) {
            console.error(err);
            logger.error(err);
            res.json(404, new ApiError('not found'));
        });
    });

    /**
     * List members
     * restriction: only owner and members can access this information
     */
    app.get('/api/rooms/:owner/:room/members', function(req, res) {

        // extract parameter
        var username = req.params.owner;
        var roomname = req.params.room;

        logger.debug('Get room: ' +  username + '/' + roomname);

        // requester, should be member of the room
        var jid = new JID(apiutils.getJid(req));
        var ownerjid = new JID(username + '@' + domain);

        var usr = null;
        var r = null;
        usrManager.findUser(jid.toString()).then(function (user) {
            usr = user;
            return usrManager.findUser(ownerjid.toString());
        }).then(function(owner){
            return usrManager.getRoom(owner, roomname);
        }).then(function(room) {
            r = room;
            return room.isMember(usr);
        }).then(function() {
            return r.getMembers();
        }).then(function(members) {
            res.json(apiutils.exportJSON(members));
        }).catch(function(err) {
            console.error(err);
            logger.error(err);
            res.json(404, new ApiError('not found'));
        });
    });

    /**
     * Check if a user is a member
     * restriction: only owner and members can access this information
     */
    app.get('/api/rooms/:owner/:room/members/:user', function(req, res) {

        // extract parameter
        var username = req.params.owner;
        var roomname = req.params.room;
        var membername = req.params.user;

        logger.debug('Get room: ' +  username + '/' + roomname);

        // requester, should be member of the room
        var jid = new JID(apiutils.getJid(req));

        // owner of the room
        var ownerjid = new JID(username + '@' + domain);

        // check if this user is member of the room
        var memberjid = new JID(membername);

        var usr = null;
        var r = null;
        var mem = null;

        // check if the "member" is a known user
        usrManager.findUser(memberjid.toString()).then(function(member){
            mem = member;
            // check if the requestor is a known user
            return usrManager.findUser(jid.toString());
        }).then(function (user) {
            usr = user;
            // check if the owner of the room is a known user
            return usrManager.findUser(ownerjid.toString());
        }).then(function(owner){
            // check if the owner has such room
            return usrManager.getRoom(owner, roomname);
        }).then(function(room) {
            r = room;
            // check if the requestor is member of the room
            return room.isMember(usr);
        }).then(function() {
            // check if the requested member is really a member of the room
            return r.isMember(mem);
        }).then(function() {
            res.send(204);
        }).catch(function(err) {
            console.error(err);
            logger.error(err);
            res.send(404);
        });
    });

    /**
     * Add user as a member
     * restriction: only owners can do this
     */
    app.put('/api/rooms/:owner/:room/members/:user', function(req, res) {
        // extract parameter
        var username = req.params.owner;
        var roomname = req.params.room;
        var membername = req.params.user;

        logger.debug('Add member to room: ' +  username + '/' + roomname);

        // requester, should be member of the room
        var jid = new JID(apiutils.getJid(req));

        // owner of the room
        var ownerjid = new JID(username + '@' + domain);

        // check if this user is member of the room
        var memberjid = new JID(membername);

        // verify that owner and requestor are the same
        if (!ownerjid.equals(jid)) {
            res.send(404);
            return;
        }

        var mem;

        // check if the "member" is a known user
        usrManager.findUser(memberjid.toString()).then(function(member){
            mem = member;
            // check if the requestor is a known user
            return usrManager.findUser(jid.toString());
        }).then(function(owner){
            // check if the owner has such room
            return usrManager.getRoom(owner, roomname);
        }).then(function(room) {
            console.log('add');
            // add member to room
            return usrManager.addMember(room, mem);
        }).then(function() {
            res.send(204);
        }).catch(function(err) {
            console.error(err);
            logger.error(err);
            res.send(404);
        });
    });

    /**
     * Remove user as a member
     * restriction: only owners can do this
     */
    app.del('/api/rooms/:owner/:room/members/:user', function(req, res) {
        // extract parameter
        var username = req.params.owner;
        var roomname = req.params.room;
        var membername = req.params.user;

        logger.debug('Add member to room: ' +  username + '/' + roomname);

        // requester, should be member of the room
        var jid = new JID(apiutils.getJid(req));

        // owner of the room
        var ownerjid = new JID(username + '@' + domain);

        // check if this user is member of the room
        var memberjid = new JID(membername);

        // verify that owner and requestor are the same
        if (!ownerjid.equals(jid)) {
            res.send(404);
            return;
        }

        var mem;

        // check if the "member" is a known user
        usrManager.findUser(memberjid.toString()).then(function(member){
            mem = member;
            // check if the requestor is a known user
            return usrManager.findUser(jid.toString());
        }).then(function(owner){
            // check if the owner has such room
            return usrManager.getRoom(owner, roomname);
        }).then(function(room) {
            // add member to room
            return usrManager.removeMember(room, mem);
        }).then(function() {
            res.send(204);
        }).catch(function(err) {
            console.error(err);
            logger.error(err);
            res.send(404);
        });
    });

    /**
     * List messages for a room
     */
    app.get('/api/rooms/:owner/:room/messages', function(req, res) {
        res.json({});
    });

    /**
     * Get a single message
     */
    app.get('/api/rooms/:owner/:room/messages/:number', function(req, res) {
        res.json({});
    });

    /**
     * Create an message
     */
    app.post('/api/rooms/:owner/:room/messages', function(req, res) {
        res.json({});
    });

    /**
     * Edit an message
     */
    app.patch('/api/rooms/:owner/:room/messages/:number', function(req, res) {
        res.json({});
    });

};

// Expose routes
module.exports = routes;<|endoftext|>