<commit_before>'use strict';

let mongoose = require('mongoose');
let LocalStrategy = require('passport-local').Strategy;
let TwitterStrategy = require('passport-twitter').Strategy;
let FacebookStrategy = require('passport-facebook').Strategy;
let GitHubStrategy = require('passport-github').Strategy;
let GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
let LinkedinStrategy = require('passport-linkedin').Strategy;
let User = mongoose.model('User');
let config = require('clever-core').loadConfig();

module.exports = function(passport) {
  // Serialize the user id to push into the session
  passport.serializeUser(function(user, done) {
    done(null, user.id);
  });

  // Deserialize the user object based on
  // a pre-serialized token which is the user id
  passport.deserializeUser(function(id, done) {
    User.findOne({
      _id: id
    }, '-salt -hashed_password', function(err, user) {
      done(err, user);
    });
  });

  // Use local strategy
  passport.use(new LocalStrategy({
      usernameField: 'email',
      passwordField: 'password'
    },
    function(email, password, done) {
      User.findOne({
        email: email
      }, function(err, user) {
        if (err) {
          return done(err);
        }
        if (!user) {
          return done(null, false, {
            message: 'Unknown user'
          });
        }
        if (!user.authenticate(password)) {
          return done(null, false, {
            message: 'Invalid password'
          });
        }
        return done(null, user);
      });
    }
  ));

  // Use twitter strategy
  passport.use(new TwitterStrategy({
      consumerKey: config.twitter.clientID,
      consumerSecret: config.twitter.clientSecret,
      callbackURL: config.twitter.callbackURL
    },
    function(token, tokenSecret, profile, done) {
      User.findOne({
        'twitter.id_str': profile.id
      }, function(err, user) {
        if (err) {
          return done(err);
        }
        if (user) {
          return done(err, user);
        }
        user = new User({
          name: profile.displayName,
          username: profile.username,
          provider: 'twitter',
          twitter: profile._json,
          roles: ['authenticated']
        });
        user.save(function(err) {
          if (err) {
            console.log(err);
            return done(null, false, {
              message: 'Twitter login failed, email already used by other login strategy'
            });
          } else {
            return done(err, user);
          }
        });
      });
    }
  ));

  // Use facebook strategy
  passport.use(new FacebookStrategy({
      clientID: config.facebook.clientID,
      clientSecret: config.facebook.clientSecret,
      callbackURL: config.facebook.callbackURL
    },
    function(accessToken, refreshToken, profile, done) {
      User.findOne({
        'facebook.id': profile.id
      }, function(err, user) {
        if (err) {
          return done(err);
        }
        if (user) {
          return done(err, user);
        }
        user = new User({
          name: profile.displayName,
          email: profile.emails[0].value,
          username: profile.username || profile.emails[0].value.split('@')[0],
          provider: 'facebook',
          facebook: profile._json,
          roles: ['authenticated']
        });
        user.save(function(err) {
          if (err) {
            console.log(err);
            return done(null, false, {
              message: 'Facebook login failed, email already used by other login strategy'
            });
          } else {
            return done(err, user);
          }
        });
      });
    }
  ));

  // Use github strategy
  passport.use(new GitHubStrategy({
      clientID: config.github.clientID,
      clientSecret: config.github.clientSecret,
      callbackURL: config.github.callbackURL
    },
    function(accessToken, refreshToken, profile, done) {
      User.findOne({
        'github.id': profile.id
      }, function(err, user) {
        if (user) {
          return done(err, user);
        }
        user = new User({
          name: profile.displayName,
          email: profile.emails[0].value,
          username: profile.username,
          provider: 'github',
          github: profile._json,
          roles: ['authenticated']
        });
        user.save(function(err) {
          if (err) {
            console.log(err);
            return done(null, false, {
              message: 'Github login failed, email already used by other login strategy'
            });
          } else {
            return done(err, user);
          }
        });
      });
    }
  ));

  // Use google strategy
  passport.use(new GoogleStrategy({
      clientID: config.google.clientID,
      clientSecret: config.google.clientSecret,
      callbackURL: config.google.callbackURL
    },
    function(accessToken, refreshToken, profile, done) {
      User.findOne({
        'google.id': profile.id
      }, function(err, user) {
        if (user) {
          return done(err, user);
        }
        user = new User({
          name: profile.displayName,
          email: profile.emails[0].value,
          username: profile.emails[0].value,
          provider: 'google',
          google: profile._json,
          roles: ['authenticated']
        });
        user.save(function(err) {
          if (err) {
            console.log(err);
            return done(null, false, {
              message: 'Google login failed, email already used by other login strategy'
            });
          } else {
            return done(err, user);
          }
        });
      });
    }
  ));

  // use linkedin strategy
  passport.use(new LinkedinStrategy({
      consumerKey: config.linkedin.clientID,
      consumerSecret: config.linkedin.clientSecret,
      callbackURL: config.linkedin.callbackURL,
      profileFields: ['id', 'first-name', 'last-name', 'email-address']
    },
    function(accessToken, refreshToken, profile, done) {
      User.findOne({
        'linkedin.id': profile.id
      }, function(err, user) {
        if (user) {
          return done(err, user);
        }
        user = new User({
          name: profile.displayName,
          email: profile.emails[0].value,
          username: profile.emails[0].value,
          provider: 'linkedin',
          roles: ['authenticated']
        });
        user.save(function(err) {
          if (err) {
            console.log(err);
            return done(null, false, {
              message: 'LinkedIn login failed, email already used by other login strategy'
            });
          } else {
            return done(err, user);
          }
        });
      });
    }
  ));
  return passport;
};
<commit_msg>FB Auth Mongo<commit_after>'use strict';

let mongoose = require('mongoose');
let LocalStrategy = require('passport-local').Strategy;
let TwitterStrategy = require('passport-twitter').Strategy;
let FacebookStrategy = require('passport-facebook').Strategy;
let GitHubStrategy = require('passport-github').Strategy;
let GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
let LinkedinStrategy = require('passport-linkedin').Strategy;
let User = mongoose.model('User');
let config = require('clever-core').loadConfig();

module.exports = function(passport) {
  // Serialize the user id to push into the session
  passport.serializeUser(function(user, done) {
    done(null, user.id);
  });

  // Deserialize the user object based on
  // a pre-serialized token which is the user id
  passport.deserializeUser(function(id, done) {
    User.findOne({
      _id: id
    }, '-salt -hashed_password', function(err, user) {
      done(err, user);
    });
  });

  // Use local strategy
  passport.use(new LocalStrategy({
      usernameField: 'email',
      passwordField: 'password'
    },
    function(email, password, done) {
      User.findOne({
        email: email
      }, function(err, user) {
        if (err) {
          return done(err);
        }
        if (!user) {
          return done(null, false, {
            message: 'Unknown user'
          });
        }
        if (!user.authenticate(password)) {
          return done(null, false, {
            message: 'Invalid password'
          });
        }
        return done(null, user);
      });
    }
  ));

  // Use twitter strategy
  passport.use(new TwitterStrategy({
      consumerKey: config.twitter.clientID,
      consumerSecret: config.twitter.clientSecret,
      callbackURL: config.twitter.callbackURL
    },
    function(token, tokenSecret, profile, done) {
      User.findOne({
        'twitter.id_str': profile.id
      }, function(err, user) {
        if (err) {
          return done(err);
        }
        if (user) {
          return done(err, user);
        }
        user = new User({
          firstName: profile.name.givenName,
          lastName: profile.name.familyName,
          provider: 'twitter',
          twitter: profile._json,
          roles: ['authenticated']
        });
        user.save(function(err) {
          if (err) {
            console.log(err);
            return done(null, false, {
              message: 'Twitter login failed, email already used by other login strategy'
            });
          } else {
            return done(err, user);
          }
        });
      });
    }
  ));

  // Use facebook strategy
  passport.use(new FacebookStrategy({
      clientID: config.facebook.clientID,
      clientSecret: config.facebook.clientSecret,
      callbackURL: config.facebook.callbackURL
    },
    function(accessToken, refreshToken, profile, done) {

      console.log(profile)

      User.findOne({
        'facebook.id': profile.id
      }, function(err, user) {
        if (err) {
          return done(err);
        }
        if (user) {
          return done(err, user);
        }
        user = new User({
          firstName: profile.name.givenName,
          lastName: profile.name.familyName,
          email: profile.emails[0].value,
          provider: 'facebook',
          facebook: profile._json,
          roles: ['authenticated']
        });
        user.save(function(err) {
          if (err) {
            console.log(err);
            return done(null, false, {
              message: 'Facebook login failed, email already used by other login strategy'
            });
          } else {
            return done(err, user);
          }
        });
      });
    }
  ));

  // Use github strategy
  passport.use(new GitHubStrategy({
      clientID: config.github.clientID,
      clientSecret: config.github.clientSecret,
      callbackURL: config.github.callbackURL
    },
    function(accessToken, refreshToken, profile, done) {
      User.findOne({
        'github.id': profile.id
      }, function(err, user) {
        if (user) {
          return done(err, user);
        }
        user = new User({
          firstName: profile.name.givenName,
          lastName: profile.name.familyName,
          email: profile.emails[0].value,
          provider: 'github',
          github: profile._json,
          roles: ['authenticated']
        });
        user.save(function(err) {
          if (err) {
            console.log(err);
            return done(null, false, {
              message: 'Github login failed, email already used by other login strategy'
            });
          } else {
            return done(err, user);
          }
        });
      });
    }
  ));

  // Use google strategy
  passport.use(new GoogleStrategy({
      clientID: config.google.clientID,
      clientSecret: config.google.clientSecret,
      callbackURL: config.google.callbackURL
    },
    function(accessToken, refreshToken, profile, done) {
      User.findOne({
        'google.id': profile.id
      }, function(err, user) {
        if (user) {
          return done(err, user);
        }
        user = new User({
          firstName: profile.name.givenName,
          lastName: profile.name.familyName,
          email: profile.emails[0].value,
          provider: 'google',
          google: profile._json,
          roles: ['authenticated']
        });
        user.save(function(err) {
          if (err) {
            console.log(err);
            return done(null, false, {
              message: 'Google login failed, email already used by other login strategy'
            });
          } else {
            return done(err, user);
          }
        });
      });
    }
  ));

  // use linkedin strategy
  passport.use(new LinkedinStrategy({
      consumerKey: config.linkedin.clientID,
      consumerSecret: config.linkedin.clientSecret,
      callbackURL: config.linkedin.callbackURL,
      profileFields: ['id', 'first-name', 'last-name', 'email-address']
    },
    function(accessToken, refreshToken, profile, done) {
      User.findOne({
        'linkedin.id': profile.id
      }, function(err, user) {
        if (user) {
          return done(err, user);
        }
        user = new User({
          firstName: profile.name.givenName,
          lastName: profile.name.familyName,
          email: profile.emails[0].value,
          provider: 'linkedin',
          roles: ['authenticated']
        });
        user.save(function(err) {
          if (err) {
            console.log(err);
            return done(null, false, {
              message: 'LinkedIn login failed, email already used by other login strategy'
            });
          } else {
            return done(err, user);
          }
        });
      });
    }
  ));
  return passport;
};
<|endoftext|>


<commit_before>define(['jquery', 'backbone', 'underscore', 'moxie.conf', 'hbs!places/templates/detail', 'hbs!places/templates/busrti', 'hbs!places/templates/trainrti'],
    function($, Backbone, _, conf, detailTemplate, busRTITemplate, trainRTITemplate){
    var RTI_REFRESH = 15000;    // 15 seconds
    var DetailView = Backbone.View.extend({

        initialize: function() {
            Backbone.trigger('domchange:title', this.model.get('name'));
            Backbone.on('favourited', _.bind(this.favourited, this));
        },
        attributes: {
            'class': 'detail-map'
        },

        serialize: function() {
            var poi = this.model.toJSON();
            return {
                poi: poi,
                multiRTI: poi.RTI.length > 1,
                alternateRTI: this.model.getAlternateRTI(),
                currentRTI: this.model.getCurrentRTI()
            };
        },
        template: detailTemplate,
        manage: true,

        afterRender: function() {
            if (this.model.get('RTI').length > 0) {
                this.refreshID = this.model.renderRTI(this.$('#poi-rti')[0], RTI_REFRESH);
            }
        },

        favourited: function(fav) {
            fav.set('options', {model: this.model.toJSON()});
            fav.set('type', 'poi:'+this.model.get('type'));
            fav.save();
        },

        cleanup: function() {
            Backbone.off('favourited');
            clearInterval(this.refreshID);
        }

    });
    return DetailView;
});
<commit_msg>Cleanup imports<commit_after>define(['jquery', 'backbone', 'underscore', 'moxie.conf', 'hbs!places/templates/detail'],
    function($, Backbone, _, conf, detailTemplate){
    var RTI_REFRESH = 15000;    // 15 seconds
    var DetailView = Backbone.View.extend({

        initialize: function() {
            Backbone.trigger('domchange:title', this.model.get('name'));
            Backbone.on('favourited', _.bind(this.favourited, this));
        },
        attributes: {
            'class': 'detail-map'
        },

        serialize: function() {
            var poi = this.model.toJSON();
            return {
                poi: poi,
                multiRTI: poi.RTI.length > 1,
                alternateRTI: this.model.getAlternateRTI(),
                currentRTI: this.model.getCurrentRTI()
            };
        },
        template: detailTemplate,
        manage: true,

        afterRender: function() {
            if (this.model.get('RTI').length > 0) {
                this.refreshID = this.model.renderRTI(this.$('#poi-rti')[0], RTI_REFRESH);
            }
        },

        favourited: function(fav) {
            fav.set('options', {model: this.model.toJSON()});
            fav.set('type', 'poi:'+this.model.get('type'));
            fav.save();
        },

        cleanup: function() {
            Backbone.off('favourited');
            clearInterval(this.refreshID);
        }

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


<commit_before>define(['jquery', 'backbone', 'underscore', 'leaflet', 'moxie.conf', 'hbs!templates/base', 'hbs!places/templates/detail', 'hbs!places/templates/busrti'],
    function($, Backbone, _, L, MoxieConf, baseTemplate, detailTemplate, busRTITemplate){
    var DetailView = Backbone.View.extend({

        initialize: function() {
            _.bindAll(this);
            L.Icon.Default.imagePath = '/images/maps';
            var wpid = navigator.geolocation.watchPosition(this.handle_geolocation_query, this.geo_error, {maximumAge:60000, timeout:20000});
            if (this.options.poi) {
                this.poi = this.options.poi;
                this.renderPOI();
            } else {
                var headers;
                if (this.user_position) {
                    headers = {'Geo-Position': this.user_position.join(';')};
                }
                var url = MoxieConf.urlFor('places_id') + this.options.poid;
                $.ajax({
                    url: url,
                    dataType: 'json',
                    headers: headers
                }).success(this.getDetail);
            }
        },

        getDetail: function(data) {
            this.poi = new this.model(data);
            this.renderPOI();
        },

        render: function() {
            this.$el.html(baseTemplate());
            this.map = L.map(this.$el.find('#map')[0]).setView([51.75310, -1.2600], 15);
            L.tileLayer('http://{s}.tile.cloudmade.com/b0a15b443b524d1a9739e92fe9dd8459/997/256/{z}/{x}/{y}.png', {
                maxZoom: 18,
                // Detect retina - if true 4* map tiles are downloaded
                detectRetina: true
            }).addTo(this.map);
            this.map.attributionControl.setPrefix('');
            return this;
        },

        invalidateMapSize: function() {
            this.map.invalidateSize();
            return this;
        },

        renderPOI: function() {
            var context = {'poi': this.poi};
            $("#list").html(detailTemplate(context));
            this.latlng = new L.LatLng(this.poi.get('lat'), this.poi.get('lon'));
            var marker = new L.marker(this.latlng, {'title': this.poi.get('name')});
            marker.addTo(this.map);
            if (this.user_position) {
                this.map.fitBounds([
                    this.user_position,
                    this.latlng
                ]);
            } else {
                this.map.panTo(this.latlng);
            }
            if (this.poi.has('hasRti')) {
                var url = MoxieConf.endpoint + this.poi.get('hasRti');
                $.ajax({
                    url: url,
                    dataType: 'json'
                }).success(this.renderRTI);
            }
        },

        renderRTI: function(data) {
            this.$el.find('#poi-rti').html(busRTITemplate(data));
        },

        geo_error: function(error) {
            if (!this.user_position) {
                console.log("No user location");
            }
        },

        handle_geolocation_query: function(position) {
            this.user_position = [position.coords.latitude, position.coords.longitude];
            var you = new L.LatLng(position.coords.latitude, position.coords.longitude);
            L.circle(you, 10, {color: 'red', fillColor: 'red', fillOpacity: 1.0}).addTo(this.map);
            this.map.fitBounds([
                this.user_position,
                this.latlng
            ]);
        }

    });
    return DetailView;
});
<commit_msg>DetailView using the UserLocation module<commit_after>define(['jquery', 'backbone', 'underscore', 'leaflet', 'moxie.conf', 'moxie.position', 'hbs!templates/base', 'hbs!places/templates/detail', 'hbs!places/templates/busrti', 'moxie.backbone'],
    function($, Backbone, _, L, MoxieConf, userPosition, baseTemplate, detailTemplate, busRTITemplate){
    var DetailView = Backbone.View.extend({

        initialize: function() {
            _.bindAll(this);
            L.Icon.Default.imagePath = '/images/maps';
        },

        render: function() {
            console.log("rendering");
            this.$el.html(baseTemplate());
            this.map = L.map(this.$el.find('#map')[0]).setView([51.75310, -1.2600], 15);
            L.tileLayer('http://{s}.tile.cloudmade.com/b0a15b443b524d1a9739e92fe9dd8459/997/256/{z}/{x}/{y}.png', {
                maxZoom: 18,
                // Detect retina - if true 4* map tiles are downloaded
                detectRetina: true
            }).addTo(this.map);
            this.map.attributionControl.setPrefix('');
            userPosition.follow(this.handle_geolocation_query);
            this.requestPOI();
            return this;
        },

        invalidateMapSize: function() {
            this.map.invalidateSize();
            return this;
        },

        requestPOI: function() {
            var url = MoxieConf.urlFor('places_id') + this.options.poid;
            $.ajax({
                url: url,
                dataType: 'json'
            }).success(this.getDetail);
        },

        getDetail: function(data) {
            this.poi = new this.model(data);
            this.renderPOI();
        },

        updateMap: function() {
            if (this.user_position && this.latlng) {
                this.map.fitBounds([
                    this.user_position,
                    this.latlng
                ]);
            } else if (this.user_position) {
                this.map.panTo(this.user_position);
            } else if (this.latlng) {
                this.map.panTo(this.latlng);
            }
        },

        renderPOI: function() {
            var context = {'poi': this.poi};
            this.$el.find("#list").html(detailTemplate(context));
            this.latlng = new L.LatLng(this.poi.get('lat'), this.poi.get('lon'));
            var marker = new L.marker(this.latlng, {'title': this.poi.get('name')});
            marker.addTo(this.map);
            this.updateMap();
            if (this.poi.has('hasRti')) {
                var url = MoxieConf.endpoint + this.poi.get('hasRti');
                $.ajax({
                    url: url,
                    dataType: 'json'
                }).success(this.renderRTI);
            }
        },

        renderRTI: function(data) {
            this.$el.find('#poi-rti').html(busRTITemplate(data));
        },

        geo_error: function(error) {
            if (!this.user_position) {
                console.log("No user location");
            }
        },

        handle_geolocation_query: function(position) {
            console.log("Updated location - Detail");
            this.user_position = [position.coords.latitude, position.coords.longitude];
            var you = new L.LatLng(position.coords.latitude, position.coords.longitude);
            L.circle(you, 10, {color: 'red', fillColor: 'red', fillOpacity: 1.0}).addTo(this.map);
            this.updateMap();
        },

        onClose: function() {
            userPosition.unfollow(this.handle_geolocation_query);
        }

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


<commit_before>const getIndividualClaimDetails = require('../../services/data/get-individual-claim-details')
const getDateFormatted = require('../../views/helpers/date-helper')
const getClaimExpenseDetailFormatted = require('../../views/helpers/claim-expense-helper')
const getDisplayFieldName = require('../../views/helpers/display-field-names')
const ValidationError = require('../../services/errors/validation-error')
const ClaimDecision = require('../../services/domain/claim-decision')
const SubmitClaimResponse = require('../../services/data/submit-claim-response')
const getClaimExpenseResponses = require('../helpers/get-claim-expense-responses')
const prisonerRelationshipsEnum = require('../../constants/prisoner-relationships-enum')

module.exports = function (router) {
  router.get('/claim/:claimId', function (req, res) {
    getIndividualClaimDetails(req.params.claimId)
      .then(function (data) {
        return res.render('./claim/view-claim', {
          title: 'APVS Claim',
          Claim: data.claim,
          Expenses: data.claimExpenses,
          getDateFormatted: getDateFormatted,
          getClaimExpenseDetailFormatted: getClaimExpenseDetailFormatted,
          getDisplayFieldName: getDisplayFieldName,
          prisonerRelationshipsEnum: prisonerRelationshipsEnum
        })
      })
  })

  router.post('/claim/:claimId', function (req, res) {
    try {
      var claimExpenses = getClaimExpenseResponses(req.body)
      var claimDecision = new ClaimDecision(req.body.decision, req.body.reasonRequest, req.body.reasonReject,
        req.body.additionalInfoApprove, req.body.additionalInfoRequest, req.body.additionalInfoReject, req.body.nomisCheck, claimExpenses)

      SubmitClaimResponse(req.params.claimId, claimDecision)
        .then(function () {
          return res.redirect('/')
        })
    } catch (error) {
      if (error instanceof ValidationError) {
        getIndividualClaimDetails(req.params.claimId)
          .then(function (data) {
            // TODO move to route helper and test

            if (data.claim && data.claimExpenses) {
              data.claim.NomisCheck = req.body.nomisCheck

              var claimExpensesById = {}
              claimExpenses.forEach(function (claimExpense) {
                claimExpensesById[claimExpense.claimExpenseId] = claimExpense
              })
              data.claimExpenses.forEach(function (expense) {
                var postedClaimExpenseResponse = claimExpensesById[expense.ClaimExpenseId.toString()]
                expense.Status = postedClaimExpenseResponse.status
                if (expense.Status === 'APPROVED-DIFF-AMOUNT') {
                  expense.ApprovedCost = postedClaimExpenseResponse.approvedCost
                  if (postedClaimExpenseResponse.approvedCost === '') {
                    expense.Error = true
                  }
                }
              })
            }
            return res.status(400).render('./claim/view-claim', {
              title: 'APVS Claim',
              Claim: data.claim,
              Expenses: data.claimExpenses,
              getDateFormatted: getDateFormatted,
              getClaimExpenseDetailFormatted: getClaimExpenseDetailFormatted,
              getDisplayFieldName: getDisplayFieldName,
              prisonerRelationshipsEnum: prisonerRelationshipsEnum,
              claimDecision: req.body,
              errors: error.validationErrors
            })
          })
      } else {
        throw error
      }
    }
  })
}
<commit_msg>Added warning class for invalid line items (#24)<commit_after>const getIndividualClaimDetails = require('../../services/data/get-individual-claim-details')
const getDateFormatted = require('../../views/helpers/date-helper')
const getClaimExpenseDetailFormatted = require('../../views/helpers/claim-expense-helper')
const getDisplayFieldName = require('../../views/helpers/display-field-names')
const ValidationError = require('../../services/errors/validation-error')
const ClaimDecision = require('../../services/domain/claim-decision')
const SubmitClaimResponse = require('../../services/data/submit-claim-response')
const getClaimExpenseResponses = require('../helpers/get-claim-expense-responses')
const prisonerRelationshipsEnum = require('../../constants/prisoner-relationships-enum')
const Validator = require('../../services/validators/common-validator')

module.exports = function (router) {
  router.get('/claim/:claimId', function (req, res) {
    getIndividualClaimDetails(req.params.claimId)
      .then(function (data) {
        return res.render('./claim/view-claim', {
          title: 'APVS Claim',
          Claim: data.claim,
          Expenses: data.claimExpenses,
          getDateFormatted: getDateFormatted,
          getClaimExpenseDetailFormatted: getClaimExpenseDetailFormatted,
          getDisplayFieldName: getDisplayFieldName,
          prisonerRelationshipsEnum: prisonerRelationshipsEnum
        })
      })
  })

  router.post('/claim/:claimId', function (req, res) {
    try {
      var claimExpenses = getClaimExpenseResponses(req.body)
      var claimDecision = new ClaimDecision(req.body.decision, req.body.reasonRequest, req.body.reasonReject,
        req.body.additionalInfoApprove, req.body.additionalInfoRequest, req.body.additionalInfoReject, req.body.nomisCheck, claimExpenses)

      SubmitClaimResponse(req.params.claimId, claimDecision)
        .then(function () {
          return res.redirect('/')
        })
    } catch (error) {
      if (error instanceof ValidationError) {
        getIndividualClaimDetails(req.params.claimId)
          .then(function (data) {
            // TODO move to route helper and test

            if (data.claim && data.claimExpenses) {
              data.claim.NomisCheck = req.body.nomisCheck

              var claimExpensesById = {}
              claimExpenses.forEach(function (claimExpense) {
                claimExpensesById[claimExpense.claimExpenseId] = claimExpense
              })
              data.claimExpenses.forEach(function (expense) {
                var postedClaimExpenseResponse = claimExpensesById[expense.ClaimExpenseId.toString()]
                expense.Status = postedClaimExpenseResponse.status
                if (expense.Status === 'APPROVED-DIFF-AMOUNT') {
                  expense.ApprovedCost = postedClaimExpenseResponse.approvedCost
                  if (!Validator.isCurrency(postedClaimExpenseResponse.approvedCost)) {
                    expense.Error = true
                  }
                }
              })
            }
            return res.status(400).render('./claim/view-claim', {
              title: 'APVS Claim',
              Claim: data.claim,
              Expenses: data.claimExpenses,
              getDateFormatted: getDateFormatted,
              getClaimExpenseDetailFormatted: getClaimExpenseDetailFormatted,
              getDisplayFieldName: getDisplayFieldName,
              prisonerRelationshipsEnum: prisonerRelationshipsEnum,
              claimDecision: req.body,
              errors: error.validationErrors
            })
          })
      } else {
        throw error
      }
    }
  })
}
<|endoftext|>


<commit_before>/*
 *  CoAPBridge.js
 *
 *  David Janes
 *  IOTDB.org
 *  2015-04-10
 *
 *  Copyright [2013-2015] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

var iotdb = require('iotdb');
var _ = iotdb._;
var bunyan = iotdb.bunyan;

var coap = require('coap');

var logger = bunyan.createLogger({
    name: 'homestar-coap',
    module: 'CoAPBridge',
});

/**
 *  See {iotdb.bridge.Bridge#Bridge} for documentation.
 *

 *  @param {object|undefined} native
 *  only used for instances, should be
 */
var CoAPBridge = function (initd, native) {
    var self = this;

    self.initd = _.defaults(initd,
        iotdb.keystore().get("bridges/CoAPBridge/initd"), {
            url: null,
            queue: true,    // if true, queue all requests
            poll: 30
        }
    );
    self.native = native;   // the thing that does the work - keep this name

    if (self.native && self.initd.queue) {
        self._reachable = true;
        self._queue = _.queue("CoAPBridge:" + url.parse(self.initd.url).host);
    }
};

CoAPBridge.prototype = new iotdb.Bridge();

CoAPBridge.prototype.name = function () {
    return "CoAPBridge";
};

/* --- lifecycle --- */

/**
 *  See {iotdb.bridge.Bridge#XXX} for documentation.
 */
CoAPBridge.prototype.discover = function () {
    var self = this;

    logger.info({
        method: "discover"
    }, "called");

    if (!self.initd.url) {
        logger.error({
            method: "discover",
            cause: "all CoAP Bridges must be explicitly set up with an IRI",
        }, "no 'url' parameter - cannot do discovery");
        return;
    }

    self.discovered(new CoAPBridge(self.initd, {}));
};

/**
 *  See {iotdb.bridge.Bridge#XXX} for documentation.
 */
CoAPBridge.prototype.connect = function (connectd) {
    var self = this;
    if (!self.native) {
        return;
    }

    self._validate_connect(connectd);

    self._setup_polling();
    self.pull();
};

CoAPBridge.prototype._setup_polling = function () {
    var self = this;
    if (!self.initd.poll) {
        return;
    }

    var timer = setInterval(function () {
        if (!self.native) {
            clearInterval(timer);
            return;
        }

        self.pull();
    }, self.initd.poll * 1000);
};

CoAPBridge.prototype._forget = function () {
    var self = this;
    if (!self.native) {
        return;
    }

    logger.info({
        method: "_forget"
    }, "called");

    self.native = null;
    self.pulled();
};

/**
 *  See {iotdb.bridge.Bridge#XXX} for documentation.
 */
CoAPBridge.prototype.disconnect = function () {
    var self = this;
    if (!self.native || !self.native) {
        return;
    }

    self._forget();
};

/* --- data --- */

/**
 *  See {iotdb.bridge.Bridge#XXX} for documentation.
 */
CoAPBridge.prototype.push = function (pushd) {
    var self = this;
    if (!self.native) {
        return;
    }

    logger.info({
        method: "push",
        putd: putd
    }, "push");

    if (self.queue) {
        var qitem = {
            // if you set "id", new pushes will unqueue old pushes with the same id
            // id: self.number,
            run: function () {
                self._pushd(pushd);
                self.queue.finished(qitem);
            }
        };
        self.queue.add(qitem);
    } else {
        self._pushd(pushd);
    }
};

/**
 *  Do the work of sending data
 */
CoAPBridge.prototype._push = function (pushd) {
};

/**
 *  See {iotdb.bridge.Bridge#XXX} for documentation.
 */
CoAPBridge.prototype.pull = function () {
    var self = this;
    if (!self.native) {
        return;
    }
};

/* --- state --- */

/**
 *  See {iotdb.bridge.Bridge#XXX} for documentation.
 */
CoAPBridge.prototype.meta = function () {
    var self = this;
    if (!self.native) {
        return;
    }

    return {
        "iot:thing": _.id.thing_urn.unique("CoAP", self.initd.url),
        "schema:name": self.native.name || "CoAP",
    };
};

/**
 *  See {iotdb.bridge.Bridge#XXX} for documentation.
 */
CoAPBridge.prototype.reachable = function () {
    return (this.native !== null) && this._reachable;
};

/**
 *  See {iotdb.bridge.Bridge#XXX} for documentation.
 */
CoAPBridge.prototype.configure = function (app) {};

/*
 *  API
 */
exports.Bridge = CoAPBridge;
<commit_msg>validate push<commit_after>/*
 *  CoAPBridge.js
 *
 *  David Janes
 *  IOTDB.org
 *  2015-04-10
 *
 *  Copyright [2013-2015] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

var iotdb = require('iotdb');
var _ = iotdb._;
var bunyan = iotdb.bunyan;

var coap = require('coap');

var logger = bunyan.createLogger({
    name: 'homestar-coap',
    module: 'CoAPBridge',
});

/**
 *  See {iotdb.bridge.Bridge#Bridge} for documentation.
 *

 *  @param {object|undefined} native
 *  only used for instances, should be
 */
var CoAPBridge = function (initd, native) {
    var self = this;

    self.initd = _.defaults(initd,
        iotdb.keystore().get("bridges/CoAPBridge/initd"), {
            url: null,
            queue: true,    // if true, queue all requests
            poll: 30
        }
    );
    self.native = native;   // the thing that does the work - keep this name

    if (self.native && self.initd.queue) {
        self._reachable = true;
        self._queue = _.queue("CoAPBridge:" + url.parse(self.initd.url).host);
    }
};

CoAPBridge.prototype = new iotdb.Bridge();

CoAPBridge.prototype.name = function () {
    return "CoAPBridge";
};

/* --- lifecycle --- */

/**
 *  See {iotdb.bridge.Bridge#XXX} for documentation.
 */
CoAPBridge.prototype.discover = function () {
    var self = this;

    logger.info({
        method: "discover"
    }, "called");

    if (!self.initd.url) {
        logger.error({
            method: "discover",
            cause: "all CoAP Bridges must be explicitly set up with an IRI",
        }, "no 'url' parameter - cannot do discovery");
        return;
    }

    self.discovered(new CoAPBridge(self.initd, {}));
};

/**
 *  See {iotdb.bridge.Bridge#XXX} for documentation.
 */
CoAPBridge.prototype.connect = function (connectd) {
    var self = this;
    if (!self.native) {
        return;
    }

    self._validate_connect(connectd);

    self._setup_polling();
    self.pull();
};

CoAPBridge.prototype._setup_polling = function () {
    var self = this;
    if (!self.initd.poll) {
        return;
    }

    var timer = setInterval(function () {
        if (!self.native) {
            clearInterval(timer);
            return;
        }

        self.pull();
    }, self.initd.poll * 1000);
};

CoAPBridge.prototype._forget = function () {
    var self = this;
    if (!self.native) {
        return;
    }

    logger.info({
        method: "_forget"
    }, "called");

    self.native = null;
    self.pulled();
};

/**
 *  See {iotdb.bridge.Bridge#XXX} for documentation.
 */
CoAPBridge.prototype.disconnect = function () {
    var self = this;
    if (!self.native || !self.native) {
        return;
    }

    self._forget();
};

/* --- data --- */

/**
 *  See {iotdb.bridge.Bridge#XXX} for documentation.
 */
CoAPBridge.prototype.push = function (pushd) {
    var self = this;
    if (!self.native) {
        return;
    }

    self._validate_push(pushd);

    logger.info({
        method: "push",
        putd: putd
    }, "push");

    if (self.queue) {
        var qitem = {
            // if you set "id", new pushes will unqueue old pushes with the same id
            // id: self.number,
            run: function () {
                self._pushd(pushd);
                self.queue.finished(qitem);
            }
        };
        self.queue.add(qitem);
    } else {
        self._pushd(pushd);
    }
};

/**
 *  Do the work of sending data
 */
CoAPBridge.prototype._push = function (pushd) {
};

/**
 *  See {iotdb.bridge.Bridge#XXX} for documentation.
 */
CoAPBridge.prototype.pull = function () {
    var self = this;
    if (!self.native) {
        return;
    }
};

/* --- state --- */

/**
 *  See {iotdb.bridge.Bridge#XXX} for documentation.
 */
CoAPBridge.prototype.meta = function () {
    var self = this;
    if (!self.native) {
        return;
    }

    return {
        "iot:thing": _.id.thing_urn.unique("CoAP", self.initd.url),
        "schema:name": self.native.name || "CoAP",
    };
};

/**
 *  See {iotdb.bridge.Bridge#XXX} for documentation.
 */
CoAPBridge.prototype.reachable = function () {
    return (this.native !== null) && this._reachable;
};

/**
 *  See {iotdb.bridge.Bridge#XXX} for documentation.
 */
CoAPBridge.prototype.configure = function (app) {};

/*
 *  API
 */
exports.Bridge = CoAPBridge;
<|endoftext|>


<commit_before>'use strict';

// A single cluster supervisor instance oversees a collection of worker
// supervisors and load balancers.
// The worker supervisors ensure that workers remain up.
// The load balancers distribute connections to workers that are listening on a
// shared port.

var debuglog = require('debuglog');
var os = require('os');
var events = require('events');
var util = require('util');
var WorkerSupervisor = require('./worker-supervisor');
var LoadBalancer = require('./round-robin-load-balancer');

var logger = debuglog('clustermon');
var TERM_SIGNALS = ['SIGINT', 'SIGTERM', 'SIGQUIT'];

function ClusterSupervisor(spec) {
    if (!(this instanceof ClusterSupervisor)) {
        return new ClusterSupervisor(spec);
    }
    if (typeof spec !== 'object' || spec === null) {
        throw new Error('ClusterSupervisor requires a spec argument');
    }

    this.respawnWorkerCount = spec.respawnWorkerCount !== undefined ?
        spec.respawnWorkerCount :
        -1;
    this.initMaster = spec.initMaster; // Post-initialization hook, receives this, but no arguments
    this.numCPUs = spec.numCPUs || os.cpus().length;
    this.logicalIds = spec.logicalIds || [];
    this.exec = spec.exec; // Worker module path TODO rename modulePath
    this.args = spec.args || []; // Worker arguments TODO rename argv or something
    this.logger = spec.logger || {
        error: logger,
        warn: logger,
        info: logger,
        debug: logger
    };
    // The period between when a server errors out and stops and when we
    // attempt to restart it:
    this.serverRestartDelay = spec.serverRestartDelay;
    this.spec = spec;

    this.workers = [];
    this.loadBalancers = {}; // port to LoadBalancer

    if (!spec.exec) throw new Error('missing exec');
    if (Array.isArray(spec.logicalIds) && spec.logicalIds.length !== this.numCPUs) {
        throw new Error('mismatching logicalIds length and numCPUs');
    }

    // Event handlers bound to this instance
    this.handleWorkerListenRequest = this.handleWorkerListenRequest.bind(this);
    this.handleWorkerCloseRequest = this.handleWorkerCloseRequest.bind(this);
    this.handleWorkerBounce = this.handleWorkerBounce.bind(this);
    this.handleWorkerStandby = this.handleWorkerStandby.bind(this);
    this.handleLoadBalancerStandby = this.handleLoadBalancerStandby.bind(this);
}

util.inherits(ClusterSupervisor, events.EventEmitter);

ClusterSupervisor.prototype.defaultWorkerForceStopDelay = 5000;
ClusterSupervisor.prototype.LoadBalancer = LoadBalancer;
ClusterSupervisor.prototype.WorkerSupervisor = WorkerSupervisor;

// ## Commands

// The start command spins up all the workers and the workers in turn spin up
// any needed load balancers.
ClusterSupervisor.prototype.start = function start () {
    this._initMaster();
};

// The stop command shuts down all workers and load balancers.
// The given callback will be informed when all systems return to a standby
// state.
ClusterSupervisor.prototype.stop = function (callback) {
    this.forEachWorker(function (worker) {
        worker.stop();
    });
    this.forEachLoadBalancer(function (loadBalancer) {
        loadBalancer.stop();
    }, this);
    if (callback) {
        this.once('standby', callback);
        // This will emit standby immediately if the cluster is already fully
        // stopped.
        this.checkForFullStop();
    }
};

// ## Inspecting the cluster

// Produces a snap shot of a data structure describing the state of the entire
// cluster, including all open ports and all workers.
ClusterSupervisor.prototype.inspect = function () {
    return {
        workers: this.workers.map(function (worker) {
            return worker.inspect();
        }),
        loadBalancers: Object.keys(this.loadBalancers).map(function (port) {
            return this.loadBalancers[port].inspect();
        }, this)
    };
};

ClusterSupervisor.prototype.countWorkers = function () {
    return this.workers.length;
};

ClusterSupervisor.prototype.countActiveWorkers = function () {
    return this.inspect().workers.filter(function (worker) {
        return worker.state !== 'standby';
    }).length;
};

ClusterSupervisor.prototype.countActiveLoadBalancers = function () {
    return this.inspect().loadBalancers.filter(function (loadBalancer) {
        return loadBalancer.state !== 'standby';
    }).length;
};

ClusterSupervisor.prototype.countRunningWorkers = function () {
    return this.inspect().workers.filter(function (worker) {
        return worker.state === 'running';
    }).length;
};

ClusterSupervisor.prototype.countRunningLoadBalancers = function () {
    return this.inspect().loadBalancers.filter(function (loadBalancer) {
        return loadBalancer.state === 'running';
    }).length;
};

ClusterSupervisor.prototype.forEachWorker = function (callback, thisp) {
    this.workers.forEach(function (worker, index) {
        callback.call(thisp, worker, index, this);
    }, this);
};

ClusterSupervisor.prototype.forEachLoadBalancer = function (callback, thisp) {
    Object.keys(this.loadBalancers).forEach(function (port) {
        var loadBalancer = this.loadBalancers[port];
        callback.call(thisp, loadBalancer, port, this);
    }, this);
};

// ## Internals

// Thus ends the public interface of the ClusterSupervisor and begins its
// internals.

ClusterSupervisor.prototype._initMaster = function _initMaster () {
    var self = this;

    this.logger.info('initing master', {
        title: process.title,
        numCPUs: this.numCPUs
    });

    for(var i = 0; i < this.numCPUs; i++) {
        var logicalId;
        logicalId = this.logicalIds[i] || i;
        this._spawnWorker(logicalId);
    }

    TERM_SIGNALS.forEach(function (signal) {
        process.on(signal, function () {
            this.logger.info('cluster master received signal...killing workers', {
                signal: signal
            });
            self.stop(function () {
                process.exit();
            });
        }.bind(this));
    }.bind(this));

    if (this.initMaster) this.initMaster();
};

ClusterSupervisor.prototype._spawnWorker = function (logicalId) {
    var spec = this.spec;
    var worker = this.WorkerSupervisor({
        id: logicalId,
        logger: this.logger,
        // Fork spec:
        workerPath: spec.exec, // TODO rename exec to workerPath
        cwd: spec.cwd,
        encoding: spec.encoding,
        execPath: spec.execPath,
        execArgv: spec.execArgv,
        silent: spec.silent,
        // Supervisor spec:
        pulse: spec.pulse,
        restartDelay: spec.workerRestartDelay,
        forceStopDelay: spec.workerForceStopDelay ||
            this.defaultWorkerForceStopDelay,
        createEnvironment: spec.createEnvironment,
        isHealthy: spec.isHealthy,
        unhealthyTimeout: spec.unhealthyTimeout
    });
    worker.on('listen', this.handleWorkerListenRequest);
    worker.on('close', this.handleWorkerCloseRequest);
    worker.on('bounce', this.handleWorkerBounce);
    worker.on('standby', this.handleWorkerStandby);
    worker.start();
    this.workers.push(worker);
};

ClusterSupervisor.prototype.handleWorkerListenRequest = function (port, address, backlog, workerSupervisor) {
    var loadBalancer = this.loadBalancers[port];
    if (!loadBalancer) {
        loadBalancer = this._createLoadBalancer(port, address, backlog);
        this.loadBalancers[port] = loadBalancer;
    } else {
        // Verify that all workers are listening with the same parameters for a
        // given port or pipename.
        if (loadBalancer.requestedAddress !== address) {
            workerSupervisor.sendError(
                port,
                new Error(
                    'Can\'t listen on cluster-shared port ' +
                    'with alternate address: expected ' +
                    loadBalancer.requestedAddress + ' got ' + address
                )
            );
            return;
        } else if (loadBalancer.requestedBacklog !== backlog) {
            workerSupervisor.sendError(
                port,
                new Error(
                    'Can\'t listen on cluster-shared port ' +
                    'with alternate backlog: expected ' +
                    loadBalancer.requestedBacklog + ' got ' + backlog
                )
            );
            return;
        }
    }
    loadBalancer.addWorkerSupervisor(workerSupervisor);
    workerSupervisor.addLoadBalancer(loadBalancer);
};

ClusterSupervisor.prototype.handleWorkerCloseRequest = function (port, workerSupervisor) {
    var loadBalancer = this.loadBalancers[port];
    loadBalancer.removeWorkerSupervisor(workerSupervisor);
    workerSupervisor.removeLoadBalancer(loadBalancer);
};

// Called when a worker emits a 'bounce' message, indicating that a worker
// returned a connection because the server closed before it could receive the
// connection.
ClusterSupervisor.prototype.handleWorkerBounce = function (port, connection) {
    var loadBalancer = this.loadBalancers[port];
    loadBalancer.handleConnection(connection);
};

ClusterSupervisor.prototype._createLoadBalancer = function (port, address, backlog) {
    var loadBalancer = this.LoadBalancer({
        logger: this.logger,
        port: port,
        address: address,
        backlog: backlog,
        restartDelay: this.serverRestartDelay
    });
    loadBalancer.on('standby', this.handleLoadBalancerStandby);
    return loadBalancer;
};

// Called when a worker emits 'standby' indicating that it has stopped
ClusterSupervisor.prototype.handleWorkerStandby = function (workerSupervisor) {
    workerSupervisor.forEachLoadBalancer(function (loadBalancer) {
        loadBalancer.removeWorkerSupervisor(workerSupervisor);
        workerSupervisor.removeLoadBalancer(loadBalancer);
    });
    this.checkForFullStop();
};

// Called when a load balancer emits 'standby' indicating that it has stopped
ClusterSupervisor.prototype.handleLoadBalancerStandby = function (loadBalancer) {
    loadBalancer.forEachWorkerSupervisor(function (workerSupervisor) {
        workerSupervisor.removeLoadBalancer(loadBalancer);
        loadBalancer.removeWorkerSupervisor(workerSupervisor);
    });
    this.checkForFullStop();
};

// Called when either a worker or load balancer enters stand-by mode. When both
// populations are entirely on standby, the cluster is at standby.
ClusterSupervisor.prototype.checkForFullStop = function () {
    var activeWorkerCount = this.countActiveWorkers();
    var activeLoadBalancerCount = this.countActiveLoadBalancers();
    if (activeWorkerCount === 0 && activeLoadBalancerCount === 0) {
        this.logger.debug('cluster now standing by', {});
        this.emit('standby');
    }
};

module.exports = ClusterSupervisor;

<commit_msg>Lazy load debuglog<commit_after>'use strict';

// A single cluster supervisor instance oversees a collection of worker
// supervisors and load balancers.
// The worker supervisors ensure that workers remain up.
// The load balancers distribute connections to workers that are listening on a
// shared port.

var os = require('os');
var events = require('events');
var util = require('util');
var WorkerSupervisor = require('./worker-supervisor');
var LoadBalancer = require('./round-robin-load-balancer');

var logger; // lazy = debuglog('clustermon');
var TERM_SIGNALS = ['SIGINT', 'SIGTERM', 'SIGQUIT'];

function ClusterSupervisor(spec) {
    if (!(this instanceof ClusterSupervisor)) {
        return new ClusterSupervisor(spec);
    }
    if (typeof spec !== 'object' || spec === null) {
        throw new Error('ClusterSupervisor requires a spec argument');
    }

    this.respawnWorkerCount = spec.respawnWorkerCount !== undefined ?
        spec.respawnWorkerCount :
        -1;
    this.initMaster = spec.initMaster; // Post-initialization hook, receives this, but no arguments

    this.logicalIds = this.configureLogicalIds(spec);

    this.exec = spec.exec; // Worker module path TODO rename modulePath
    this.args = spec.args || []; // Worker arguments TODO rename argv or something

    if (!spec.logger) {
        if (!logger) {
            logger = require('debuglog')('clustermon');
        }
        spec.logger = {
            error: logger,
            warn: logger,
            info: logger,
            debug: logger
        };
    }
    this.logger = spec.logger;

    // The period between when a server errors out and stops and when we
    // attempt to restart it:
    this.serverRestartDelay = spec.serverRestartDelay;
    this.spec = spec;

    this.workers = [];
    this.loadBalancers = {}; // port to LoadBalancer

    if (!spec.exec) throw new Error('missing exec');
    if (Array.isArray(spec.logicalIds) && spec.logicalIds.length !== this.numCPUs) {
        throw new Error('mismatching logicalIds length and numCPUs');
    }

    // Event handlers bound to this instance
    this.handleWorkerListenRequest = this.handleWorkerListenRequest.bind(this);
    this.handleWorkerCloseRequest = this.handleWorkerCloseRequest.bind(this);
    this.handleWorkerBounce = this.handleWorkerBounce.bind(this);
    this.handleWorkerStandby = this.handleWorkerStandby.bind(this);
    this.handleLoadBalancerStandby = this.handleLoadBalancerStandby.bind(this);
}

util.inherits(ClusterSupervisor, events.EventEmitter);

ClusterSupervisor.prototype.defaultWorkerForceStopDelay = 5000;
ClusterSupervisor.prototype.LoadBalancer = LoadBalancer;
ClusterSupervisor.prototype.WorkerSupervisor = WorkerSupervisor;

// ## Commands

// The start command spins up all the workers and the workers in turn spin up
// any needed load balancers.
ClusterSupervisor.prototype.start = function start () {
    this._initMaster();
};

// The stop command shuts down all workers and load balancers.
// The given callback will be informed when all systems return to a standby
// state.
ClusterSupervisor.prototype.stop = function (callback) {
    this.forEachWorker(function (worker) {
        worker.stop();
    });
    this.forEachLoadBalancer(function (loadBalancer) {
        loadBalancer.stop();
    }, this);
    if (callback) {
        this.once('standby', callback);
        // This will emit standby immediately if the cluster is already fully
        // stopped.
        this.checkForFullStop();
    }
};

// ## Inspecting the cluster

// Produces a snap shot of a data structure describing the state of the entire
// cluster, including all open ports and all workers.
ClusterSupervisor.prototype.inspect = function () {
    return {
        workers: this.workers.map(function (worker) {
            return worker.inspect();
        }),
        loadBalancers: Object.keys(this.loadBalancers).map(function (port) {
            return this.loadBalancers[port].inspect();
        }, this)
    };
};

ClusterSupervisor.prototype.countWorkers = function () {
    return this.workers.length;
};

ClusterSupervisor.prototype.countActiveWorkers = function () {
    return this.inspect().workers.filter(function (worker) {
        return worker.state !== 'standby';
    }).length;
};

ClusterSupervisor.prototype.countActiveLoadBalancers = function () {
    return this.inspect().loadBalancers.filter(function (loadBalancer) {
        return loadBalancer.state !== 'standby';
    }).length;
};

ClusterSupervisor.prototype.countRunningWorkers = function () {
    return this.inspect().workers.filter(function (worker) {
        return worker.state === 'running';
    }).length;
};

ClusterSupervisor.prototype.countRunningLoadBalancers = function () {
    return this.inspect().loadBalancers.filter(function (loadBalancer) {
        return loadBalancer.state === 'running';
    }).length;
};

ClusterSupervisor.prototype.forEachWorker = function (callback, thisp) {
    this.workers.forEach(function (worker, index) {
        callback.call(thisp, worker, index, this);
    }, this);
};

ClusterSupervisor.prototype.forEachLoadBalancer = function (callback, thisp) {
    Object.keys(this.loadBalancers).forEach(function (port) {
        var loadBalancer = this.loadBalancers[port];
        callback.call(thisp, loadBalancer, port, this);
    }, this);
};

// ## Internals

// Thus ends the public interface of the ClusterSupervisor and begins its
// internals.

ClusterSupervisor.prototype._initMaster = function _initMaster () {
    var self = this;

    this.logger.info('initing master', {
        title: process.title,
        numCPUs: this.numCPUs
    });

    for(var i = 0; i < this.numCPUs; i++) {
        var logicalId;
        logicalId = this.logicalIds[i] || i;
        this._spawnWorker(logicalId);
    }

    TERM_SIGNALS.forEach(function (signal) {
        process.on(signal, function () {
            this.logger.info('cluster master received signal...killing workers', {
                signal: signal
            });
            self.stop(function () {
                process.exit();
            });
        }.bind(this));
    }.bind(this));

    if (this.initMaster) this.initMaster();
};

ClusterSupervisor.prototype._spawnWorker = function (logicalId) {
    var spec = this.spec;
    var worker = this.WorkerSupervisor({
        id: logicalId,
        logger: this.logger,
        // Fork spec:
        workerPath: spec.exec, // TODO rename exec to workerPath
        cwd: spec.cwd,
        encoding: spec.encoding,
        execPath: spec.execPath,
        execArgv: spec.execArgv,
        silent: spec.silent,
        // Supervisor spec:
        pulse: spec.pulse,
        restartDelay: spec.workerRestartDelay,
        forceStopDelay: spec.workerForceStopDelay ||
            this.defaultWorkerForceStopDelay,
        createEnvironment: spec.createEnvironment,
        isHealthy: spec.isHealthy,
        unhealthyTimeout: spec.unhealthyTimeout
    });
    worker.on('listen', this.handleWorkerListenRequest);
    worker.on('close', this.handleWorkerCloseRequest);
    worker.on('bounce', this.handleWorkerBounce);
    worker.on('standby', this.handleWorkerStandby);
    worker.start();
    this.workers.push(worker);
};

ClusterSupervisor.prototype.handleWorkerListenRequest = function (port, address, backlog, workerSupervisor) {
    var loadBalancer = this.loadBalancers[port];
    if (!loadBalancer) {
        loadBalancer = this._createLoadBalancer(port, address, backlog);
        this.loadBalancers[port] = loadBalancer;
    } else {
        // Verify that all workers are listening with the same parameters for a
        // given port or pipename.
        if (loadBalancer.requestedAddress !== address) {
            workerSupervisor.sendError(
                port,
                new Error(
                    'Can\'t listen on cluster-shared port ' +
                    'with alternate address: expected ' +
                    loadBalancer.requestedAddress + ' got ' + address
                )
            );
            return;
        } else if (loadBalancer.requestedBacklog !== backlog) {
            workerSupervisor.sendError(
                port,
                new Error(
                    'Can\'t listen on cluster-shared port ' +
                    'with alternate backlog: expected ' +
                    loadBalancer.requestedBacklog + ' got ' + backlog
                )
            );
            return;
        }
    }
    loadBalancer.addWorkerSupervisor(workerSupervisor);
    workerSupervisor.addLoadBalancer(loadBalancer);
};

ClusterSupervisor.prototype.handleWorkerCloseRequest = function (port, workerSupervisor) {
    var loadBalancer = this.loadBalancers[port];
    loadBalancer.removeWorkerSupervisor(workerSupervisor);
    workerSupervisor.removeLoadBalancer(loadBalancer);
};

// Called when a worker emits a 'bounce' message, indicating that a worker
// returned a connection because the server closed before it could receive the
// connection.
ClusterSupervisor.prototype.handleWorkerBounce = function (port, connection) {
    var loadBalancer = this.loadBalancers[port];
    loadBalancer.handleConnection(connection);
};

ClusterSupervisor.prototype._createLoadBalancer = function (port, address, backlog) {
    var loadBalancer = this.LoadBalancer({
        logger: this.logger,
        port: port,
        address: address,
        backlog: backlog,
        restartDelay: this.serverRestartDelay
    });
    loadBalancer.on('standby', this.handleLoadBalancerStandby);
    return loadBalancer;
};

// Called when a worker emits 'standby' indicating that it has stopped
ClusterSupervisor.prototype.handleWorkerStandby = function (workerSupervisor) {
    workerSupervisor.forEachLoadBalancer(function (loadBalancer) {
        loadBalancer.removeWorkerSupervisor(workerSupervisor);
        workerSupervisor.removeLoadBalancer(loadBalancer);
    });
    this.checkForFullStop();
};

// Called when a load balancer emits 'standby' indicating that it has stopped
ClusterSupervisor.prototype.handleLoadBalancerStandby = function (loadBalancer) {
    loadBalancer.forEachWorkerSupervisor(function (workerSupervisor) {
        workerSupervisor.removeLoadBalancer(loadBalancer);
        loadBalancer.removeWorkerSupervisor(workerSupervisor);
    });
    this.checkForFullStop();
};

// Called when either a worker or load balancer enters stand-by mode. When both
// populations are entirely on standby, the cluster is at standby.
ClusterSupervisor.prototype.checkForFullStop = function () {
    var activeWorkerCount = this.countActiveWorkers();
    var activeLoadBalancerCount = this.countActiveLoadBalancers();
    if (activeWorkerCount === 0 && activeLoadBalancerCount === 0) {
        this.logger.debug('cluster now standing by', {});
        this.emit('standby');
    }
};

module.exports = ClusterSupervisor;

<|endoftext|>


<commit_before>/* eslint-disable import/prefer-default-export */

/**
 * Initializer for state/resetter
 */

export const initialState = ({ type }) => ({
  program: null,
  supplier: null,
  period: null,
  orderType: null,
  name: '',
  currentKey: 'program',
  isProgramBased: true,
  isModalOpen: false,
  steps: STEPS[type].true,
});

/**
 * Action constants for ByProgramReducer
 */
const actions = {
  SELECT_PROGRAM: 'selectProgram',
  SELECT_SUPPLIER: 'selectSupplier',
  SELECT_ORDER_TYPE: 'selectOrderType',
  SELECT_PERIOD: 'selectPeriod',
  SET_TOGGLE: 'setToggle',
  SET_MODAL_OPEN: 'setModalOpen',
  SET_MODAL_CLOSED: 'setModalClosed',
  SET_STORE_TAGS: 'setStoreTags',
  SET_STEPS: 'setSteps',
  SET_NAME: 'setName',
};

const STEPS = {
  requisition: {
    true: ['program', 'supplier', 'orderType', 'period'],
    false: ['supplier'],
  },
  stocktake: {
    true: ['program', 'name'],
    false: ['name'],
  },
};

/**
 * Action Creators for ByProgramReducer
 */
export const setSteps = value => ({
  type: actions.SET_STEPS,
  value,
});

export const selectProgram = value => ({
  type: actions.SELECT_PROGRAM,
  value,
});

export const selectSupplier = value => ({
  type: actions.SELECT_SUPPLIER,
  value,
});

export const selectOrderType = value => ({
  type: actions.SELECT_ORDER_TYPE,
  value,
});

export const selectPeriod = value => ({
  type: actions.SELECT_PERIOD,
  value,
});

export const setName = value => ({
  type: actions.SET_NAME,
  value,
});

export const setModalOpen = value => ({
  type: actions.SET_MODAL_OPEN,
  value,
});

export const setModalClosed = () => ({
  type: actions.SET_MODAL_CLOSED,
});

export const setToggle = value => ({
  type: actions.SET_TOGGLE,
  value,
});

export const setStoreTags = value => ({
  type: actions.SET_STORE_TAGS,
  value,
});

/**
 * Reducer to handle the state management of
 * ByProgramModal
 */
export const byProgramReducer = (state, action) => {
  const { type, value } = action;
  //   console.log(action);
  switch (type) {
    case actions.SELECT_PROGRAM:
      return {
        ...state,
        program: value,
        supplier: null,
        orderType: null,
        period: null,
        name: '',
        isModalOpen: false,
        complete: false,
      };
    case actions.SELECT_SUPPLIER:
      return {
        ...state,
        supplier: value,
        orderType: null,
        period: null,
        name: '',
        isModalOpen: false,
        complete: false,
      };
    case actions.SELECT_ORDER_TYPE:
      return {
        ...state,
        orderType: value,
        period: null,
        name: '',
        isModalOpen: false,
        complete: false,
      };
    case actions.SELECT_PERIOD:
      return {
        ...state,
        period: value,
        name: '',
        isModalOpen: false,
        complete: true,
      };
    case actions.SET_NAME:
      return {
        ...state,
        isModalOpen: false,
        complete: true,
        name: value,
      };
    case actions.SET_MODAL_DATA:
      return {
        ...state,
        modalData: value,
      };
    case actions.SET_TOGGLE: {
      const { isProgramBased } = state;
      const steps = STEPS[value][!isProgramBased];
      return {
        ...state,
        program: null,
        supplier: null,
        orderType: null,
        period: null,
        name: '',
        isProgramBased: !isProgramBased,
        steps,
        complete: false,
        currentKey: null,
      };
    }
    case actions.SET_MODAL_OPEN: {
      const { selection, key: currentKey } = value;
      return {
        ...state,
        isModalOpen: true,
        currentKey,
        modalData: selection,
      };
    }
    case actions.SET_MODAL_CLOSED:
      return {
        ...state,
        isModalOpen: false,
        currentKey: null,
      };
    case actions.SET_STORE_TAGS:
      return {
        ...state,
        storeTags: value,
      };
    default:
      return state;
  }
};
<commit_msg>Add removal of console log<commit_after>/* eslint-disable import/prefer-default-export */

/**
 * Initializer for state/resetter
 */

export const initialState = ({ type }) => ({
  program: null,
  supplier: null,
  period: null,
  orderType: null,
  name: '',
  currentKey: 'program',
  isProgramBased: true,
  isModalOpen: false,
  steps: STEPS[type].true,
});

/**
 * Action constants for ByProgramReducer
 */
const actions = {
  SELECT_PROGRAM: 'selectProgram',
  SELECT_SUPPLIER: 'selectSupplier',
  SELECT_ORDER_TYPE: 'selectOrderType',
  SELECT_PERIOD: 'selectPeriod',
  SET_TOGGLE: 'setToggle',
  SET_MODAL_OPEN: 'setModalOpen',
  SET_MODAL_CLOSED: 'setModalClosed',
  SET_STORE_TAGS: 'setStoreTags',
  SET_STEPS: 'setSteps',
  SET_NAME: 'setName',
};

const STEPS = {
  requisition: {
    true: ['program', 'supplier', 'orderType', 'period'],
    false: ['supplier'],
  },
  stocktake: {
    true: ['program', 'name'],
    false: ['name'],
  },
};

/**
 * Action Creators for ByProgramReducer
 */
export const setSteps = value => ({
  type: actions.SET_STEPS,
  value,
});

export const selectProgram = value => ({
  type: actions.SELECT_PROGRAM,
  value,
});

export const selectSupplier = value => ({
  type: actions.SELECT_SUPPLIER,
  value,
});

export const selectOrderType = value => ({
  type: actions.SELECT_ORDER_TYPE,
  value,
});

export const selectPeriod = value => ({
  type: actions.SELECT_PERIOD,
  value,
});

export const setName = value => ({
  type: actions.SET_NAME,
  value,
});

export const setModalOpen = value => ({
  type: actions.SET_MODAL_OPEN,
  value,
});

export const setModalClosed = () => ({
  type: actions.SET_MODAL_CLOSED,
});

export const setToggle = value => ({
  type: actions.SET_TOGGLE,
  value,
});

export const setStoreTags = value => ({
  type: actions.SET_STORE_TAGS,
  value,
});

/**
 * Reducer to handle the state management of
 * ByProgramModal
 */
export const byProgramReducer = (state, action) => {
  const { type, value } = action;
  switch (type) {
    case actions.SELECT_PROGRAM:
      return {
        ...state,
        program: value,
        supplier: null,
        orderType: null,
        period: null,
        name: '',
        isModalOpen: false,
        complete: false,
      };
    case actions.SELECT_SUPPLIER:
      return {
        ...state,
        supplier: value,
        orderType: null,
        period: null,
        name: '',
        isModalOpen: false,
        complete: false,
      };
    case actions.SELECT_ORDER_TYPE:
      return {
        ...state,
        orderType: value,
        period: null,
        name: '',
        isModalOpen: false,
        complete: false,
      };
    case actions.SELECT_PERIOD:
      return {
        ...state,
        period: value,
        name: '',
        isModalOpen: false,
        complete: true,
      };
    case actions.SET_NAME:
      return {
        ...state,
        isModalOpen: false,
        complete: true,
        name: value,
      };
    case actions.SET_MODAL_DATA:
      return {
        ...state,
        modalData: value,
      };
    case actions.SET_TOGGLE: {
      const { isProgramBased } = state;
      const steps = STEPS[value][!isProgramBased];
      return {
        ...state,
        program: null,
        supplier: null,
        orderType: null,
        period: null,
        name: '',
        isProgramBased: !isProgramBased,
        steps,
        complete: false,
        currentKey: null,
      };
    }
    case actions.SET_MODAL_OPEN: {
      const { selection, key: currentKey } = value;
      return {
        ...state,
        isModalOpen: true,
        currentKey,
        modalData: selection,
      };
    }
    case actions.SET_MODAL_CLOSED:
      return {
        ...state,
        isModalOpen: false,
        currentKey: null,
      };
    case actions.SET_STORE_TAGS:
      return {
        ...state,
        storeTags: value,
      };
    default:
      return state;
  }
};
<|endoftext|>


<commit_before>import utils from 'heyui/utils/utils';
import locale from 'heyui/locale';

const Default = {
  type: 'dialog',
  title: '',
  content: '',
  style: null,
  class: null,
  buttons: [],
  hasMask: false,
  closeOnMask: true,
  hasCloseIcon: false,
  timeout: 0,
  width: false,
  global: false,
  noPadding: false
};

const TYPE = {
  MODAL: 'h-modal',
  MESSAGE: 'h-message',
  NOTICE: 'h-notice'
};

const notifyCls = 'h-notify';
const notifyHasCloseCls = 'h-notify-has-close';
const notifyContentCls = 'h-notify-content';
const notifyContainerCls = 'h-notify-container';
const notifyBodyCls = 'h-notify-body';
const notifyCloseCls = 'h-notify-close';
const notifyMaskCls = 'h-notify-mask';
const notifyShowCls = 'h-notify-show';
const closeIcon = 'h-icon-close';

class Notify {
  constructor(orignalparam) {
    const that = this;
    this.mouseOver = false;
    this.closeTimeout = false;
    let param = this.param = utils.extend({}, Default, orignalparam, true);
    let html = '';
    if (param.hasMask) {
      html += `<div class="${notifyMaskCls}"></div>`;
    }
    if (param.type === TYPE.MODAL && param.hasMask) {
      html += `<div class="${notifyBodyCls}">`;
    }
    html += `<div class="${notifyContainerCls}">`;
    if (param.hasCloseIcon) html += `<span class="${notifyCloseCls} ${closeIcon}"></span>`;
    if (param.title) html += `<header class="${param.type}-header">${param.title}</header>`;
    html += `<div class="${notifyContentCls}"></div>`;
    param.hasFooter = utils.isArray(param.buttons) && param.buttons.length > 0 && !param.component;
    if (param.hasFooter) {
      let footeHtml = '';
      for (const b of param.buttons) {
        let name = '';
        let attr = '';
        let color = '';
        if (b == 'cancel') {
          name = b.name || locale.t('h.common.cancel');
          attr = b;
        } else if (b == 'ok') {
          name = b.name || locale.t('h.common.confirm');
          attr = 'ok';
          color = 'primary';
        } else if (utils.isObject(b)) {
          attr = b.type;
          name = b.name;
          color = b.color;
        }
        if (color) color = `h-btn-${color}`;
        footeHtml += `<button class="h-btn ${color}" attr="${attr}" >${name}</button>`;
      }
      html += `<footer class="${param.type}-footer">${footeHtml}</footer>`;
    }
    if (param.type === TYPE.MODAL) {
      html += `</div>`;
    }

    html += '
';
    let $body = document.createElement(`div`);
    utils.addClass($body, notifyCls);
    if (param.hasMask) {
      utils.addClass($body, 'h-notify-has-mask');
    } else {
      utils.addClass($body, 'h-notify-no-mask');
    }
    if (param.class) {
      utils.addClass($body, param.class);
    }
    if (param.className) {
      utils.addClass($body, param.className);
    }
    $body.innerHTML = html;
    let $content = this.$content = $body.querySelector(`.${notifyContentCls}`);
    let $container = this.$container = $body.querySelector(`.${notifyContainerCls}`);
    this.$body = $body;

    let content = param.content;
    if (content.nodeType === 1) {
      $content.appendChild(content);
    } else if (utils.isFunction(content)) {
      const contentText = content.call(this);
      $content.innerHTML = contentText;
    } else {
      $content.innerHTML = content;
    }

    if (param.component != undefined && param.Vue) {
      this.vue = new param.Vue({
        el: $content,
        i18n: param.$i18n,
        router: param.$router,
        render(createElement) {
          let keys = Object.keys(param.events || {});
          let events = {
            event: this.trigger,
            close: this.close
          };
          for (let key of keys) {
            if (events[key]) {
              continue;
            }
            events[key] = (...data) => {
              this.trigger(key, ...data);
            };
          }
          return createElement(
            'div', {}, [createElement('plugin', {
              props: this.propsData,
              on: events
            })]
          );
        },
        data() {
          return {
            propsData: utils.extend({}, param.component.datas, {
              // **删除**delete**
              param: param.component.data,
              params: param.component.data
            }),
            modal: that
          };
        },
        mounted() {
        },
        methods: {
          trigger(name, ...data) {
            that.trigger(name, ...data);
          },
          close() {
            that.close();
          }
        },
        components: {
          plugin: param.component.vue
        }
      });
    }

    if (param.hasCloseIcon) {
      utils.addClass($body, notifyHasCloseCls);
    }

    if (param.type) {
      utils.addClass($body, param.type);
    }

    if (param.height) {
      $content.style.height = `${param.height}px`;
    }
    if (param.maxheight) {
      $content.style.maxHeight = `${param.maxheight}px`;
    }
    if (param.style) {
      utils.addClass($body, param.style);
    }
    if (param.width) {
      $container.style.width = `${param.width}px`;
    }

    let parentDom = param.parent || document.body;
    if (param.type == 'h-notice' && parentDom.hasChildNodes()) {
      parentDom.insertBefore($body, parentDom.firstChild);
    } else {
      parentDom.appendChild($body);
    }
    // fix: button在focus状态，enter或者空格键都会再次触发
    let focusClicked = document.querySelector(':focus');
    if (focusClicked && param.type === TYPE.MODAL) {
      focusClicked.blur();
    }
    if (param.hasCloseIcon) {
      $body.querySelector(`.${notifyCloseCls}`).onclick = function () {
        that.close();
      };
    }
    if (param.hasFooter) {
      let buttons = $body.querySelectorAll(`.${notifyContainerCls}>footer>button`);
      for (let button of buttons) {
        button.onclick = function (event) {
          let attr = event.target.getAttribute('attr');
          if (attr) {
            if (attr == 'cancel') {
              that.close();
            }
            that.trigger(attr);
          }
        };
      }
    }

    window.setTimeout(() => {
      utils.addClass($body, notifyShowCls);
      if (param.hasMask) {
        let body = document.documentElement;
        let scrollWidth = window.innerWidth - body.clientWidth;
        body.style.overflow = 'hidden';
        body.style.paddingRight = `${scrollWidth}px`;
      }
    }, 20);

    if (param.events && utils.isFunction(param.events.$init)) {
      param.events.$init.call(null, that, $content);
    }
    if (param.timeout) {
      $body.addEventListener('mouseover', () => {
        this.mouseOver = true;
      });
      $body.addEventListener('mouseleave', () => {
        this.mouseOver = false;
        if (this.closeTimeout) {
          that.close();
        }
      });

      window.setTimeout(() => {
        this.closeTimeout = true;
        if (!this.mouseOver) {
          that.close();
        }
      }, param.timeout);
    }
    if (param.closeOnMask && param.hasMask) {
      $body.querySelector(`.${notifyMaskCls}`).onclick = () => {
        this.close();
      };
      let modalBody = $body.querySelector(`.${notifyBodyCls}`);
      if (modalBody) {
        modalBody.onclick = (event) => {
          if (event.target == modalBody) {
            this.close();
          }
        };
      }
    }
    this.PopstateEvent = () => {
      this.close();
    };

    window.addEventListener('popstate', this.PopstateEvent);
  }

  trigger(event, ...data) {
    let param = this.param;
    if (param.events && utils.isFunction(param.events[event])) {
      param.events[event].call(null, this, ...data);
    }
  }

  close() {
    let that = this;
    const $body = this.$body;
    if (this.vm) {
      that.vm.$destroy();
    }

    let body = document.documentElement;
    body.style.overflow = '';
    body.style.paddingRight = '';

    this.trigger('$close');

    window.removeEventListener('popstate', this.PopstateEvent);

    utils.removeClass($body, notifyShowCls);

    $body.addEventListener('transitionend', (event) => {
      if (event.target == this.$container) {
        utils.removeDom($body);
      }
    });
    setTimeout(() => {
      utils.removeDom($body);
    }, 400);
  }
}

export default function (param) {
  return new Notify(param);
}
<commit_msg>chore: update var name<commit_after>import utils from 'heyui/utils/utils';
import locale from 'heyui/locale';

const Default = {
  type: 'dialog',
  title: '',
  content: '',
  style: null,
  class: null,
  buttons: [],
  hasMask: false,
  closeOnMask: true,
  hasCloseIcon: false,
  timeout: 0,
  width: false,
  global: false,
  noPadding: false
};

const TYPE = {
  MODAL: 'h-modal',
  MESSAGE: 'h-message',
  NOTICE: 'h-notice'
};

const notifyCls = 'h-notify';
const notifyHasCloseCls = 'h-notify-has-close';
const notifyContentCls = 'h-notify-content';
const notifyContainerCls = 'h-notify-container';
const notifyBodyCls = 'h-notify-body';
const notifyCloseCls = 'h-notify-close';
const notifyMaskCls = 'h-notify-mask';
const notifyShowCls = 'h-notify-show';
const closeIcon = 'h-icon-close';

class Notify {
  constructor(orignalparam) {
    const that = this;
    this.mouseOver = false;
    this.closeTimeout = false;
    let param = this.param = utils.extend({}, Default, orignalparam, true);
    let html = '';
    if (param.hasMask) {
      html += `<div class="${notifyMaskCls}"></div>`;
    }
    if (param.type === TYPE.MODAL && param.hasMask) {
      html += `<div class="${notifyBodyCls}">`;
    }
    html += `<div class="${notifyContainerCls}">`;
    if (param.hasCloseIcon) html += `<span class="${notifyCloseCls} ${closeIcon}"></span>`;
    if (param.title) html += `<header class="${param.type}-header">${param.title}</header>`;
    html += `<div class="${notifyContentCls}"></div>`;
    param.hasFooter = utils.isArray(param.buttons) && param.buttons.length > 0 && !param.component;
    if (param.hasFooter) {
      let footeHtml = '';
      for (const b of param.buttons) {
        let name = '';
        let attr = '';
        let color = '';
        if (b == 'cancel') {
          name = b.name || locale.t('h.common.cancel');
          attr = b;
        } else if (b == 'ok') {
          name = b.name || locale.t('h.common.confirm');
          attr = 'ok';
          color = 'primary';
        } else if (utils.isObject(b)) {
          attr = b.type;
          name = b.name;
          color = b.color;
        }
        if (color) color = `h-btn-${color}`;
        footeHtml += `<button class="h-btn ${color}" attr="${attr}" >${name}</button>`;
      }
      html += `<footer class="${param.type}-footer">${footeHtml}</footer>`;
    }
    if (param.type === TYPE.MODAL) {
      html += `</div>`;
    }

    html += '
';
    let $body = document.createElement(`div`);
    utils.addClass($body, notifyCls);
    if (param.hasMask) {
      utils.addClass($body, 'h-notify-has-mask');
    } else {
      utils.addClass($body, 'h-notify-no-mask');
    }
    if (param.class) {
      utils.addClass($body, param.class);
    }
    if (param.className) {
      utils.addClass($body, param.className);
    }
    $body.innerHTML = html;
    let $content = this.$content = $body.querySelector(`.${notifyContentCls}`);
    let $container = this.$container = $body.querySelector(`.${notifyContainerCls}`);
    this.$body = $body;

    let content = param.content;
    if (content.nodeType === 1) {
      $content.appendChild(content);
    } else if (utils.isFunction(content)) {
      const contentText = content.call(this);
      $content.innerHTML = contentText;
    } else {
      $content.innerHTML = content;
    }

    if (param.component != undefined && param.Vue) {
      this.vue = new param.Vue({
        el: $content,
        i18n: param.$i18n,
        router: param.$router,
        render(createElement) {
          let keys = Object.keys(param.events || {});
          let events = {
            event: this.trigger,
            close: this.close
          };
          for (let key of keys) {
            if (events[key]) {
              continue;
            }
            events[key] = (...data) => {
              this.trigger(key, ...data);
            };
          }
          return createElement(
            'div', {}, [createElement('plugin', {
              props: this.propsData,
              on: events
            })]
          );
        },
        data() {
          return {
            propsData: utils.extend({}, param.component.datas, {
              // **删除**delete**
              param: param.component.data,
              params: param.component.data
            }),
            modal: that
          };
        },
        mounted() {
        },
        methods: {
          trigger(name, ...data) {
            that.trigger(name, ...data);
          },
          close() {
            that.close();
          }
        },
        components: {
          plugin: param.component.vue
        }
      });
    }

    if (param.hasCloseIcon) {
      utils.addClass($body, notifyHasCloseCls);
    }

    if (param.type) {
      utils.addClass($body, param.type);
    }

    if (param.height) {
      $content.style.height = `${param.height}px`;
    }
    if (param.maxheight) {
      $content.style.maxHeight = `${param.maxheight}px`;
    }
    if (param.style) {
      utils.addClass($body, param.style);
    }
    if (param.width) {
      $container.style.width = `${param.width}px`;
    }

    let parentDom = param.parent || document.body;
    if (param.type == 'h-notice' && parentDom.hasChildNodes()) {
      parentDom.insertBefore($body, parentDom.firstChild);
    } else {
      parentDom.appendChild($body);
    }
    // fix: button在focus状态，enter或者空格键都会再次触发
    let focusClicked = document.querySelector(':focus');
    if (focusClicked && param.type === TYPE.MODAL) {
      focusClicked.blur();
    }
    if (param.hasCloseIcon) {
      $body.querySelector(`.${notifyCloseCls}`).onclick = function () {
        that.close();
      };
    }
    if (param.hasFooter) {
      let buttons = $body.querySelectorAll(`.${notifyContainerCls}>footer>button`);
      for (let button of buttons) {
        button.onclick = function (event) {
          let attr = event.target.getAttribute('attr');
          if (attr) {
            if (attr == 'cancel') {
              that.close();
            }
            that.trigger(attr);
          }
        };
      }
    }

    window.setTimeout(() => {
      utils.addClass($body, notifyShowCls);
      if (param.hasMask) {
        let body = document.documentElement;
        let scrollWidth = window.innerWidth - body.clientWidth;
        body.style.overflow = 'hidden';
        body.style.paddingRight = `${scrollWidth}px`;
      }
    }, 20);

    if (param.events && utils.isFunction(param.events.$init)) {
      param.events.$init.call(null, that, $content);
    }
    if (param.timeout) {
      $body.addEventListener('mouseover', () => {
        this.mouseOver = true;
      });
      $body.addEventListener('mouseleave', () => {
        this.mouseOver = false;
        if (this.closeTimeout) {
          that.close();
        }
      });

      window.setTimeout(() => {
        this.closeTimeout = true;
        if (!this.mouseOver) {
          that.close();
        }
      }, param.timeout);
    }
    if (param.closeOnMask && param.hasMask) {
      $body.querySelector(`.${notifyMaskCls}`).onclick = () => {
        this.close();
      };
      let modalBody = $body.querySelector(`.${notifyBodyCls}`);
      if (modalBody) {
        modalBody.onclick = (event) => {
          if (event.target == modalBody) {
            this.close();
          }
        };
      }
    }
    this.popstateEvent = () => {
      this.close();
    };

    window.addEventListener('popstate', this.popstateEvent);
  }

  trigger(event, ...data) {
    let param = this.param;
    if (param.events && utils.isFunction(param.events[event])) {
      param.events[event].call(null, this, ...data);
    }
  }

  close() {
    let that = this;
    const $body = this.$body;
    if (this.vm) {
      that.vm.$destroy();
    }

    let body = document.documentElement;
    body.style.overflow = '';
    body.style.paddingRight = '';

    this.trigger('$close');

    window.removeEventListener('popstate', this.popstateEvent);

    utils.removeClass($body, notifyShowCls);

    $body.addEventListener('transitionend', (event) => {
      if (event.target == this.$container) {
        utils.removeDom($body);
      }
    });
    setTimeout(() => {
      utils.removeDom($body);
    }, 400);
  }
}

export default function (param) {
  return new Notify(param);
}
<|endoftext|>


<commit_before>var AV = require('leanengine');
var http = require('http');
var cheerio = require('cheerio');
var https = require("https");

function sendGank(content) {
    var data = JSON.stringify(content);
    var options = {
        hostname: 'hook.bearychat.com',
        port: 443,
        path:"/=bw88X/incoming/659242f9646cf54b6f62acd6dee9fbfc",
        method: "POST",
        headers: {
            'Content-Type': 'application/json',
            'Content-Length': Buffer.byteLength(data)
        }
    };
    var req = http.request(options, function(res){
        console.log("STATUS" + res.statusCode);
    });
    req.write(data);
    req.end();

}

AV.Cloud.define('hello', function(req, res){
    console.log(req);
    res.success('Hello world in cloud function');
});

AV.Cloud.define("todayGank", function(request, response) {
        date = new Date();
        var year = date.getFullYear();
        var month = date.getMonth() + 1;
        var day = date.getDate();
        url = "http://gank.io/api/day/" +year+ "/" + month + "/" + day;
    http.get(url, function(res) {
        if (res.statusCode !== 200) {
            sendGank({"text": "发生了错误"});
            return;
        }
        res.setEncoding("utf8");
        var rawData = '';
        res.on('data', function(chunk){
            rawData += chunk;
        });
        res.on('end', function() {
            parseData = JSON.parse(rawData);
            if (parseData.category.length == 0) {
                sendGank({"text":":joy: 今天休息没干货"});
                return;
            }
            datas = parseData.results;
            var text = "今日干货 " +year + "年" + month + "月" + day + "日";
            arr = new Array();
            for(key in datas) {
                if (key != "休息视频" && key != "福利") {
                    attachmentItem = {'title': key, 'text': '', 'color':"#409fff"};
                    itemData  = datas[key];
                    for(items in itemData) {
                        attachmentItem.text = attachmentItem.text + itemData[items].desc + " By:" + itemData[items].who + "\n" + itemData[items].url + "\n";
                    }
                    arr.push(attachmentItem);
                }

            }
            sendGank({"text": text, "attachments": arr});
        });

    });
});

//var baseUrl = "http://www.meizitu.com/a/";
//AV.Cloud.define("meiziSpider", function(request, response) {
//    var query = new AV.Query("meiziIndex");
//    query.equalTo("name", "meizitucom");
//    query.first().then(function(obj) {
//       var sInd = obj.get("lastIndex");
//        var index = parseInt(sInd);
//        index += 1;
//        console.log("index:" + index);
//        requestMeizitu(index);
//
//    }, function(error) {
//        requestMeizitu(1);
//    });
//});

function requestMeizitu(index) {
    var mUrl = baseUrl + index + ".html";
    http.get(mUrl, function(res) {

        var html = "";
        response.on('data', function(data) {
            html += data;
        });

        response.on('end', function() {
            console.log("html:" + html);
            parsehtml(index, html);
            var query = new AV.Query("meiziIndex");
            query.equalTo("name", "meizitucom");
            query.first().then(function(obj) {
                var index = parseInt(obj.get("lastIndex"));
                index += 1;
                obj.set("lastIndex", inde);
                obj.save();

            }, function(error) {
                var obj = new MeiziIndex();
                obj.set("name", "meizitucom");
                obj.set("lastIndex", 1);
                obj.save();
            });
        });
    });
}

function parsehtml(oid, htmlContent) {
    var $ = cheerio.load(htmlContent);
    var mzObj = new Meizitu();
    var titleName = $("div.metaRight h2 a").text();
    mzObj.set("title", titleName);
    var tags = $("div.metaRight p").text();
    tags = tags.replace("Tags:", "");
    var tagArray = tags.split(" , ");
    mzObj.set("tags", tagArray);
    var imageLinks = [];
    mzObj.set("mzId", oid);
    $("div.postConttent p img").each(function(index, element) {
        var imgUrl = $(element).attr("src");
        imageLinks.push(imgUrl);
    });
    mzObj.set("imgs", imageLinks);
    var otherText = $("div.postContent p").text();
    mzObj.set("text", otherText);
    mzObj.save();
}

var DoubanMusic = AV.Object.extend("DoubanMusic");
var Meizitu = AV.Object.extend("meizitu");
var MeiziIndex = AV.Object.extend("meiziIndex");

module.exports = AV.Cloud;
<commit_msg>云函数增加返回值<commit_after>var AV = require('leanengine');
var http = require('http');
var cheerio = require('cheerio');
var https = require("https");

function sendGank(content) {
    var data = JSON.stringify(content);
    var options = {
        hostname: 'hook.bearychat.com',
        port: 443,
        path:"/=bw88X/incoming/659242f9646cf54b6f62acd6dee9fbfc",
        method: "POST",
        headers: {
            'Content-Type': 'application/json',
            'Content-Length': Buffer.byteLength(data)
        }
    };
    var req = http.request(options, function(res){
        console.log("STATUS" + res.statusCode);
    });
    req.write(data);
    req.end();

}

AV.Cloud.define('hello', function(req, res){
    console.log(req);
    res.success('Hello world in cloud function');
});

AV.Cloud.define("todayGank", function(request, response) {
        date = new Date();
        var year = date.getFullYear();
        var month = date.getMonth() + 1;
        var day = date.getDate();
        url = "http://gank.io/api/day/" +year+ "/" + month + "/" + day;
    http.get(url, function(res) {
        if (res.statusCode !== 200) {
            sendGank({"text": "发生了错误"});
            return response.success();
        }
        res.setEncoding("utf8");
        var rawData = '';
        res.on('data', function(chunk){
            rawData += chunk;
        });
        res.on('end', function() {
            parseData = JSON.parse(rawData);
            if (parseData.category.length == 0) {
                sendGank({"text":":joy: 今天休息没干货"});
                return response.success();
            }
            datas = parseData.results;
            var text = "今日干货 " +year + "年" + month + "月" + day + "日";
            arr = new Array();
            for(key in datas) {
                if (key != "休息视频" && key != "福利") {
                    attachmentItem = {'title': key, 'text': '', 'color':"#409fff"};
                    itemData  = datas[key];
                    for(items in itemData) {
                        attachmentItem.text = attachmentItem.text + itemData[items].desc + " By:" + itemData[items].who + "\n" + itemData[items].url + "\n";
                    }
                    arr.push(attachmentItem);
                }

            }
            sendGank({"text": text, "attachments": arr});
            return response.success();
        });

    });
});

//var baseUrl = "http://www.meizitu.com/a/";
//AV.Cloud.define("meiziSpider", function(request, response) {
//    var query = new AV.Query("meiziIndex");
//    query.equalTo("name", "meizitucom");
//    query.first().then(function(obj) {
//       var sInd = obj.get("lastIndex");
//        var index = parseInt(sInd);
//        index += 1;
//        console.log("index:" + index);
//        requestMeizitu(index);
//
//    }, function(error) {
//        requestMeizitu(1);
//    });
//});

function requestMeizitu(index) {
    var mUrl = baseUrl + index + ".html";
    http.get(mUrl, function(res) {

        var html = "";
        response.on('data', function(data) {
            html += data;
        });

        response.on('end', function() {
            console.log("html:" + html);
            parsehtml(index, html);
            var query = new AV.Query("meiziIndex");
            query.equalTo("name", "meizitucom");
            query.first().then(function(obj) {
                var index = parseInt(obj.get("lastIndex"));
                index += 1;
                obj.set("lastIndex", inde);
                obj.save();

            }, function(error) {
                var obj = new MeiziIndex();
                obj.set("name", "meizitucom");
                obj.set("lastIndex", 1);
                obj.save();
            });
        });
    });
}

function parsehtml(oid, htmlContent) {
    var $ = cheerio.load(htmlContent);
    var mzObj = new Meizitu();
    var titleName = $("div.metaRight h2 a").text();
    mzObj.set("title", titleName);
    var tags = $("div.metaRight p").text();
    tags = tags.replace("Tags:", "");
    var tagArray = tags.split(" , ");
    mzObj.set("tags", tagArray);
    var imageLinks = [];
    mzObj.set("mzId", oid);
    $("div.postConttent p img").each(function(index, element) {
        var imgUrl = $(element).attr("src");
        imageLinks.push(imgUrl);
    });
    mzObj.set("imgs", imageLinks);
    var otherText = $("div.postContent p").text();
    mzObj.set("text", otherText);
    mzObj.save();
}

var DoubanMusic = AV.Object.extend("DoubanMusic");
var Meizitu = AV.Object.extend("meizitu");
var MeiziIndex = AV.Object.extend("meiziIndex");

module.exports = AV.Cloud;
<|endoftext|>