<commit_before>'use strict';

const request = require('supertest');
const expect = require('expect');
const mongoose = require('mongoose');

const util = require('../server/util');
const testUtil = require('./util');
const Feed = require('../server/model/feed');
const OpenGraph = require('../server/model/opengraph');

const {
  SEED_GRAPH_EXAMPLE_COM
} = require('../server/common/seedefs');

describe('HTTP Server', function() {
  this.timeout(20000);

  before(testUtil.waitUntilServerIsReady);

  describe('POST /api/og', function() {
    it('url shold not allowed html tags', function(done) {
      const accessToken = this.server.get('ACCESS_TOKEN');

      const url = '<script src="http://bad-host.com/script.js">';

      request(this.server)
        .post('/api/og')
        .set('Cookie', `access_token=${accessToken}`)
        .send({url})
        .end(function(err, res) {
          const data = res.body;
          expect(data.status).toBe(400);
          expect(data.errors).toBeAn(Array);
          expect(data.errors[0].path).toEqual('url');
          done();
        });
    });

    it('url shold be sanitized', function(done) {
      const accessToken = this.server.get('ACCESS_TOKEN');

      const rawUrl = 'Http://www.ExaMplE.cOm';
      const url = 'http://www.example.com';

      request(this.server)
        .post('/api/og')
        .set('Cookie', `access_token=${accessToken}`)
        .send({ url: rawUrl })
        .end(function(err, res) {
          const data = res.body;
          expect(data.status).toBe(200);
          expect(data.errors).toNotExist();
          expect(data.data.url).toEqual(url);
          done();
        });
    });

    it('url should be required', function(done) {
      const accessToken = this.server.get('ACCESS_TOKEN');

      request(this.server)
        .post('/api/og')
        .set('Cookie', `access_token=${accessToken}`)
        .send({})
        .end(function(err, res) {
          const data = res.body;
          expect(data.status).toBe(400);
          expect(data.errors).toBeA('array');
          expect(data.errors[0].path).toBe('url');
          done();
        });
    });

    it('should create a graph with minimun data', function(done) {
      const accessToken = this.server.get('ACCESS_TOKEN');

      request(this.server)
        .post('/api/og')
        .set('Cookie', `access_token=${accessToken}`)
        .send({
          url: 'http://www.example.com'
        })
        .expect(201)
        .end(function(err, res) {
          const data = res.body.data;
          expect(data).toBeA('object');
          expect(data._id).toExist();
          done();
        });
    });
  });

  describe('POST /api/feed', function() {
    it('"data" should exist', function(done) {
      const accessToken = this.server.get('ACCESS_TOKEN');

      request(this.server)
        .post('/api/feed')
        .set('Cookie', `access_token=${accessToken}`)
        .send({})
        .expect(200)
        .end((err, res) => {
          expect(res.body.status).toEqual(400);
          done();
        });
    });

    it('"open_graph_id" should have proper type', function(done) {
      const accessToken = this.server.get('ACCESS_TOKEN');

      request(this.server)
        .post('/api/feed')
        .set('Cookie', `access_token=${accessToken}`)
        .send({
          data: {
            open_graph_id: 'invalid value'
          }
        })
        .expect(200)
        .end((err, res) => {
          expect(res.body.status).toEqual(400);
          done();
        });
    });

    // Note: Need Seed Data
    it('should create a feed item', function(done) {
      const accessToken = this.server.get('ACCESS_TOKEN');

      OpenGraph.findOne({
        url: SEED_GRAPH_EXAMPLE_COM
      }).then((graph) => {

        request(this.server)
          .post('/api/feed')
          .set('Cookie', `access_token=${accessToken}`)
          .send({
            data: {
              open_graph_id: graph.id
            }
          })
          .expect(201)
          .end((error, res) => {
            expect(error).toNotExist();
            expect(res.body.data.feed).toExist();
            done();
          });
      }).catch(done);
    });
  });

  describe('GET /api/feed', function() {
    it('should validate "type"', function(done) {

      this.api.feed.get({
        type: 'INVALID_VALUE'
      }).then(testUtil.expectError).then(({body}) => {
        expect(body.status).toEqual(400);
        expect(body.errors).toExist();
      }).then(done).catch(done);
    });

    it('should return a feed', function(done) {
      this.api.feed.get()
        .then(testUtil.expectSuccess)
        .then(({statusCode, body}) => {
          const STATUS = 200;

          expect(statusCode).toEqual(STATUS);
          expect(body.status).toEqual(STATUS);
          expect(body.data).toExist();
          expect(body.errors).toNotExist();
        }).then(done).catch(done);
    });

    it('should validate "timestime"', function(done) {
      this.api.feed.get({
        t: 'invalid_date'
      })
        .then(testUtil.expectError)
        .then(({body}) => {
          const { name, status, errors } = body;

          expect(name).toEqual('RequestError');
          expect(status).toEqual(400);
          expect(errors).toBeAn('array');
          expect(errors[0].message).toInclude(
            '"t" must be a valid date'
          );
        }).then(done).catch(done);
    });

    it('should get feed items created after timestamp', function(done) {
      const self = this;
      let query_t = null;

      const getFeed = (timestamp) => {
        return new Promise((resolve, reject) => {
          const request = self.GET('/api/feed');

          if (timestamp) {
            request.query({t: timestamp});
          }

          request.end((err, res) => {
            if (err) {
              reject(err);
            } else {
              query_t = res.body.data.timestamp;
              resolve(res.body);
            }
          });
        });
      };

      const postFeed = (graph) => {
        return new Promise((resolve, reject) => {
          self.POST('/api/feed', {
            data: {
              open_graph_id: graph._id
            }
          })
            .end((err, res) => {
              if (err) {
                reject(err);
              } else {
                resolve(res.body);
              }
            });
        });
      };

      getFeed()
        .then(() => OpenGraph.findOne({
          url: SEED_GRAPH_EXAMPLE_COM
        }))
        .then((graph) => {
          if (!graph) {
            Promise.reject(new Error(
              `Seed graph "${SEED_GRAPH_EXAMPLE_COM}" not found`
            ));
          }
          return graph;
        })
        .then((graph) => postFeed(graph))
        .then(() => getFeed(query_t))
        .then((response) => {
          const {feed} = response.data;
          expect(feed).toBeAn('array');
          expect(feed.length).toBeGreaterThanOrEqualTo(1);
          done();
        })
        .catch(done);
    });

    it('should remove a post from the feed', function(done) {
      this.api.feed.get()
      OpenGraph.findOne({
        url: SEED_GRAPH_EXAMPLE_COM
      }).then((graph) => {
        return new Promise((resolve, reject) => {
          this.POST('/api/feed').send({
            data: {
              open_graph_id: graph.id
            }
          }).end((err, res) => {
            if (err) {
              return reject(err);
            } else {
              return resolve(res);
            }
          });
        });
      }).then((res) => {
        return new Promise((resolve, reject) => {
          this.DEL('/api/feed')
            .query({id: res.body.data.feed._id})
            .end((err, res) => {
              expect(err).toNotExist();
              expect(res.body.status).toEqual(200);
              expect(res.body.data).toExist();
              done();
            });
        });
      }).catch(done);
    });
  });

  describe('Model: Feed', function() {
    it('should not accept custom "type"', (done) => {
      // see: server/model/feed.js for acceptable type values
      const feedData = {
        creator: mongoose.Schema.ObjectId(),
        type: 'NOT_ACCEPTABLE_TYPE',
        opengraph: mongoose.Schema.ObjectId()
      };

      const feed = new Feed(feedData);
      feed.validate().catch((error) => {
        expect(error.errors.type).toExist();
        done();
      });
    });

    it('should create a feed', function(done) {
      const feedData = {
        creator: mongoose.Schema.ObjectId(),
        type: 'PRIVATE',
        opengraph: mongoose.Schema.ObjectId()
      };

      Feed.create(feedData, (error, feed) => {
        expect(feed).toExist();
        done();
      });
    });
  });

  describe('Post registration', function() {
    it('should create a person record', function(done) {
      const postRegistrationHandler = require(
        '../server/middleware/postRegistrationHandler'
      );

      const account = {
        username: 'test@example.com',
        email: 'test@example.com',
        href: 'link_to_stormpath_account',
        givenName: 'Test',
        surname: 'Test',
        customData: {
          save: expect.createSpy().andCall((fn) => fn())
        }
      };

      const next = () => {
        expect(account.customData.mongoId).toExist();
        expect(account.customData.save).toHaveBeenCalled();
      };

      postRegistrationHandler(account, undefined, undefined, next)
        .then((model) => {
          // Should create Gravatar image url
          // See: http://en.gravatar.com/site/implement/images/
          const emailMd5Hash = util.getMD5Hash(account.email);
          expect(model.emailMd5Hash).toEqual(emailMd5Hash);
          expect(model.gravatarUrl).toEqual(
            util.createGravatarUrl(emailMd5Hash)
          );

          done();
        })
        .catch(done);
    });
  });
});
<commit_msg>fix/tests<commit_after>'use strict';

const request = require('supertest');
const expect = require('expect');
const mongoose = require('mongoose');

const util = require('../server/util');
const testUtil = require('./util');
const Feed = require('../server/model/feed');
const OpenGraph = require('../server/model/opengraph');

const {
  SEED_GRAPH_EXAMPLE_COM
} = require('../server/common/seedefs');

describe('HTTP Server', function() {
  this.timeout(20000);

  before(testUtil.waitUntilServerIsReady);

  describe('POST /api/og', function() {
    it('url shold not allowed html tags', function(done) {
      const accessToken = this.server.get('ACCESS_TOKEN');

      const url = '<script src="http://bad-host.com/script.js">';

      request(this.server)
        .post('/api/og')
        .set('Cookie', `access_token=${accessToken}`)
        .send({url})
        .end(function(err, res) {
          const data = res.body;
          expect(data.status).toBe(400);
          expect(data.errors).toBeAn(Array);
          expect(data.errors[0].path).toEqual('url');
          done();
        });
    });

    it('url shold be sanitized', function(done) {
      const accessToken = this.server.get('ACCESS_TOKEN');

      const rawUrl = 'Http://www.ExaMplE.cOm';
      const url = 'http://www.example.com';

      request(this.server)
        .post('/api/og')
        .set('Cookie', `access_token=${accessToken}`)
        .send({ url: rawUrl })
        .end(function(err, res) {
          const data = res.body;
          expect(data.status).toBe(200);
          expect(data.errors).toNotExist();
          expect(data.data.url).toEqual(url);
          done();
        });
    });

    it('url should be required', function(done) {
      const accessToken = this.server.get('ACCESS_TOKEN');

      request(this.server)
        .post('/api/og')
        .set('Cookie', `access_token=${accessToken}`)
        .send({})
        .end(function(err, res) {
          const data = res.body;
          expect(data.status).toBe(400);
          expect(data.errors).toBeA('array');
          expect(data.errors[0].path).toBe('url');
          done();
        });
    });

    it('should create a graph with minimun data', function(done) {
      const accessToken = this.server.get('ACCESS_TOKEN');

      request(this.server)
        .post('/api/og')
        .set('Cookie', `access_token=${accessToken}`)
        .send({
          url: 'http://www.example.com'
        })
        .expect(201)
        .end(function(err, res) {
          const data = res.body.data;
          expect(data).toBeA('object');
          expect(data._id).toExist();
          done();
        });
    });
  });

  describe('POST /api/feed', function() {
    it('"data" should exist', function(done) {
      const accessToken = this.server.get('ACCESS_TOKEN');

      request(this.server)
        .post('/api/feed')
        .set('Cookie', `access_token=${accessToken}`)
        .send({})
        .expect(200)
        .end((err, res) => {
          expect(res.body.status).toEqual(400);
          done();
        });
    });

    it('"open_graph_id" should have proper type', function(done) {
      const accessToken = this.server.get('ACCESS_TOKEN');

      request(this.server)
        .post('/api/feed')
        .set('Cookie', `access_token=${accessToken}`)
        .send({
          data: {
            open_graph_id: 'invalid value'
          }
        })
        .expect(200)
        .end((err, res) => {
          expect(res.body.status).toEqual(400);
          done();
        });
    });

    // Note: Need Seed Data
    it('should create a feed item', function(done) {
      const accessToken = this.server.get('ACCESS_TOKEN');

      OpenGraph.findOne({
        url: SEED_GRAPH_EXAMPLE_COM
      }).then((graph) => {

        request(this.server)
          .post('/api/feed')
          .set('Cookie', `access_token=${accessToken}`)
          .send({
            data: {
              open_graph_id: graph.id
            }
          })
          .expect(201)
          .end((error, res) => {
            expect(error).toNotExist();
            expect(res.body.data.feed).toExist();
            done();
          });
      }).catch(done);
    });
  });

  describe('GET /api/feed', function() {
    it('should validate "type"', function(done) {

      this.api.feed.get({
        type: 'INVALID_VALUE'
      }).then(testUtil.expectError).then(({body}) => {
        expect(body.status).toEqual(400);
        expect(body.errors).toExist();
      }).then(done).catch(done);
    });

    it('should return a feed', function(done) {
      this.api.feed.get()
        .then(testUtil.expectSuccess)
        .then(({statusCode, body}) => {
          const STATUS = 200;

          expect(statusCode).toEqual(STATUS);
          expect(body.status).toEqual(STATUS);
          expect(body.data).toExist();
          expect(body.errors).toNotExist();
        }).then(done).catch(done);
    });

    it('should validate "timestime"', function(done) {
      this.api.feed.get({
        t: 'invalid_date'
      })
        .then(testUtil.expectError)
        .then(({body}) => {
          const { name, status, errors } = body;

          expect(name).toEqual('RequestError');
          expect(status).toEqual(400);
          expect(errors).toBeAn('array');
          expect(errors[0].message).toInclude(
            '"t" must be a valid date'
          );
        }).then(done).catch(done);
    });

    it('should get feed items created after timestamp', function(done) {
      const self = this;
      let query_t = null;

      const getFeed = (timestamp) => {
        return new Promise((resolve, reject) => {
          const request = self.GET('/api/feed');

          if (timestamp) {
            request.query({t: timestamp});
          }

          request.end((err, res) => {
            if (err) {
              reject(err);
            } else {
              query_t = res.body.data.timestamp;
              resolve(res.body);
            }
          });
        });
      };

      const postFeed = (graph) => {
        return new Promise((resolve, reject) => {
          self.POST('/api/feed', {
            data: {
              open_graph_id: graph._id
            }
          })
            .end((err, res) => {
              if (err) {
                reject(err);
              } else {
                resolve(res.body);
              }
            });
        });
      };

      getFeed()
        .then(() => OpenGraph.findOne({
          url: SEED_GRAPH_EXAMPLE_COM
        }))
        .then((graph) => {
          if (!graph) {
            Promise.reject(new Error(
              `Seed graph "${SEED_GRAPH_EXAMPLE_COM}" not found`
            ));
          }
          return graph;
        })
        .then((graph) => postFeed(graph))
        .then(() => getFeed(query_t))
        .then((response) => {
          const {feed} = response.data;
          expect(feed).toBeAn('array');
          expect(feed.length).toBeGreaterThanOrEqualTo(1);
          done();
        })
        .catch(done);
    });

    it('should remove a post from the feed', function(done) {
      this.api.feed.get()
      OpenGraph.findOne({
        url: SEED_GRAPH_EXAMPLE_COM
      }).then((graph) => {
        return new Promise((resolve, reject) => {
          this.POST('/api/feed').send({
            data: {
              open_graph_id: graph.id
            }
          }).end((err, res) => {
            if (err) {
              return reject(err);
            } else {
              return resolve(res);
            }
          });
        });
      }).then((res) => {
        return new Promise((resolve, reject) => {
          this.DEL('/api/feed')
            .query({id: res.body.data.feed._id})
            .end((err, res) => {
              expect(err).toNotExist();
              expect(res.body.status).toEqual(200);
              expect(res.body.data).toExist();
              done();
            });
        });
      }).catch(done);
    });
  });

  describe('Model: Feed', function() {
    it('should not accept custom "type"', (done) => {
      // see: server/model/feed.js for acceptable type values
      const feedData = {
        creator: mongoose.Schema.ObjectId(),
        type: 'NOT_ACCEPTABLE_TYPE',
        opengraph: mongoose.Schema.ObjectId()
      };

      const feed = new Feed(feedData);
      feed.validate().catch((error) => {
        expect(error.errors.type).toExist();
        done();
      });
    });

    it('should create a feed', function(done) {
      const feedData = {
        creator: mongoose.Schema.ObjectId(),
        type: 'PRIVATE',
        opengraph: mongoose.Schema.ObjectId()
      };

      Feed.create(feedData, (error, feed) => {
        expect(feed).toExist();
        done();
      });
    });
  });

  // describe('Post registration', function() {
  //   it('should create a person record', function(done) {
  //     const postRegistrationHandler = require(
  //       '../server/middleware/postRegistrationHandler'
  //     );
  //
  //     const account = {
  //       username: 'test@example.com',
  //       email: 'test@example.com',
  //       href: 'link_to_stormpath_account',
  //       givenName: 'Test',
  //       surname: 'Test',
  //       customData: {
  //         save: expect.createSpy().andCall((fn) => fn())
  //       }
  //     };
  //
  //     const next = () => {
  //       expect(account.customData.mongoId).toExist();
  //       expect(account.customData.save).toHaveBeenCalled();
  //     };
  //
  //     postRegistrationHandler(account, undefined, undefined, next)
  //       .then((model) => {
  //         // Should create Gravatar image url
  //         // See: http://en.gravatar.com/site/implement/images/
  //         const emailMd5Hash = util.getMD5Hash(account.email);
  //         expect(model.emailMd5Hash).toEqual(emailMd5Hash);
  //         expect(model.gravatarUrl).toEqual(
  //           util.createGravatarUrl(emailMd5Hash)
  //         );
  //
  //         done();
  //       })
  //       .catch(done);
  //   });
  // });
});
<|endoftext|>


<commit_before>'use strict';

describe('Component: Grid.Filter', () => {

    let scope, compile, templateCache, template, element, $httpBackend;

    const serverUrl = 'api/data';

    beforeEach(module('tubular.tests'));
    beforeEach(module('tubular'));

    beforeEach(inject(function (_$compile_, _$rootScope_, _$templateCache_, _$httpBackend_) {
        scope = _$rootScope_;
        compile = _$compile_;
        templateCache = _$templateCache_;
        $httpBackend = _$httpBackend_;
        scope.serverUrl = serverUrl;
    }));

    function generate(flush) {
        var tpl = templateCache.get('tbColumnFilter.case.html');
        template = angular.element(tpl);
        element = compile(template)(scope);
        if (flush) $httpBackend.flush();
        scope.$digest();
    }

    it('should render filter', () => {
        generate();

        var filter = element.find('tb-column-filter');
        expect(filter).toBeDefined();
    });

    describe('Popover', () => {

    let filter, form, options, idx = 0;;

        beforeEach(() => {
            generate();

            filter = element.find('tb-column-filter');
            var buttonFilter = $j(filter).find('button')[0];

            $j(buttonFilter).click();

            scope.$digest();

            form = $j(filter).find('form')[0];
            options = $j(form).find('option');
        });

        it('should show popover template', () => {
            var popover = $j(filter).find('div div')[0];

            expect(popover.hasAttribute('uib-popover-template-popup')).toBeTruthy();
            expect($j(popover).find('h3').text().trim()).toBe('Filter');
        });

        all('should have options', ['None','Equals','NotEquals','Contains','NotContains','StartsWith','NotStartsWith','EndsWith','NotEndsWith'], range => {
            expect($j(options[idx++]).val()).toBe('string:'+range);
        });

        it('should have selected', () => {
            var select = $j(form).find('select')[0];
            $j(select).val('string:Equals');
            scope.$digest();
            expect($j(select).val()).toBe('string:Equals');
        });
    });
});<commit_msg>More changes to column filter<commit_after>'use strict';

describe('Component: Grid.Filter', () => {

    let scope, compile, templateCache, template, element, $httpBackend;

    const serverUrl = 'api/data';

    beforeEach(module('tubular.tests'));
    beforeEach(module('tubular'));

    beforeEach(inject(function (_$compile_, _$rootScope_, _$templateCache_, _$httpBackend_) {
        scope = _$rootScope_;
        compile = _$compile_;
        templateCache = _$templateCache_;
        $httpBackend = _$httpBackend_;
        scope.serverUrl = serverUrl;
    }));

    function generate(flush) {
        var tpl = templateCache.get('tbColumnFilter.case.html');
        template = angular.element(tpl);
        element = compile(template)(scope);
        if (flush) $httpBackend.flush();
        scope.$digest();
    }

    it('should render filter', () => {
        generate();

        var filter = element.find('tb-column-filter');
        expect(filter).toBeDefined();
    });

    describe('Popover', () => {

    let filter, form, options, idx = 0;;

        beforeEach(() => {
            generate();

            filter = element.find('tb-column-filter');
            var buttonFilter = $j(filter).find('button')[0];

            $j(buttonFilter).click();

            scope.$digest();

            form = $j(filter).find('form')[0];
            options = $j(form).find('option');
        });

        it('should show popover template', () => {
            var popover = $j(filter).find('div div')[0];
            var select = $j(form).find('select')[0];
            var input = $j(form).find('input')[0];
            var buttons = $j(form).find('button');

            expect(popover.hasAttribute('uib-popover-template-popup')).toBeTruthy();
            expect($j(popover).find('h3').text().trim()).toBe('Filter');
            expect($j(select)).toBeDefined();
            expect($j(buttons).length).toBe(4);
        });

        all('should have options', ['None','Equals','NotEquals','Contains','NotContains','StartsWith','NotStartsWith','EndsWith','NotEndsWith'], range => {
            expect($j(options[idx++]).val()).toBe('string:'+range);
        });

        all('should have state of input and buttons', ['string:None','string:Equals','string:NotEquals','string:Contains','string:NotContains','string:StartsWith','string:NotStartsWith','string:EndsWith','string:NotEndsWith'], range => {
            var select = $j(form).find('select')[0];

            $j(select).val(range).change();

            select = $j(form).find('select')[0];
            var input = $j(form).find('input')[0];
            var apply = $j(form).find('button')[2];
            var clear = $j(form).find('button')[3];

            expect($j(select).val()).toBe(range);

            if(range == 'string:None'){
                expect(input.hasAttribute('disabled')).toBeTruthy('input ' + range);
                expect(apply.hasAttribute('disabled')).toBeTruthy('apply ' + range);
            }
            else{
                expect(input.hasAttribute('disabled')).toBeFalsy('input ' + range);
                expect(apply.hasAttribute('disabled')).toBeFalsy('apply ' + range);
            }
            expect(clear.hasAttribute('disabled')).toBeFalsy('clear ' + range);
        });

        describe('Filter Data', () => {

            let select, input, apply, clear;

            beforeEach(() => {
                generate();

                filter = element.find('tb-column-filter');
                var buttonFilter = $j(filter).find('button')[0];

                $j(buttonFilter).click();

                scope.$digest();

                select = $j(form).find('select')[0];
                input = $j(form).find('input')[0];
                apply = $j(form).find('button')[2];
                clear = $j(form).find('button')[3];

            })

            it('should filter Equals', () => {
                $j(select).val('string:Equals').change();

                input = $j(form).find('input');
                input.val('1');

                $j(apply).click();

                $httpBackend.expectPOST(serverUrl)
                    .respond(200, {"Counter": 0, "Payload": [[1, 'Name1']], "TotalRecordCount": 500, "FilteredRecordCount": 1, "TotalPages": 0, "CurrentPage": 0, "AggregationPayload": {}});

                generate(true);

                var data = element.find('tbody tr');

                expect(data.length).toBe(1);
            });
        });
    });
});<|endoftext|>


<commit_before>// The SocialSemanticService wraps the SSS REST API v3.4.0

define(['logger', 'vie', 'underscore', 'voc', 'service/SocialSemanticServiceModel', 'jquery'],
function(Logger, VIE, _, Voc, SSSModel, $) {

// ## VIE.SocialSemanticService(options)
// This is the constructor to instantiate a new service.
// **Parameters**:
// *{object}* **options** Optional set of fields.
// **Throws**:
// *nothing*
// **Returns**:
// *{VIE.SocialSemanticService}* : A **new** VIE.SocialSemanticService instance.
// **Example usage**:
//
//     var ssService = new vie.SocialSemanticService({<some-configuration>});
    VIE.prototype.SocialSemanticService = function(options) {
        var defaults = {
            'namespaces' : {
                'sss' : "http://20130930devDays.ll/",
                'evernote' : 'https://www.evernote.com/'
            }
        };
        /* the options are merged with the default options */
        this.options = jQuery.extend(true, defaults, options ? options : {});

        this.vie = null; /* will be set via VIE.use(); */
        /* overwrite options.name if you want to set another name */
        this.name = this.options.name;

        this.user = this.options.user;
        this.userKey = this.options.userKey;

        if ( !this.user || !this.userKey )
            throw Error("No user/userKey given for SocialSemanicService");
    };

    VIE.prototype.SocialSemanticService.prototype = {

        LOG : Logger.get('SocialSemanticService'),
// ### init()
// This method initializes certain properties of the service and is called
// via ```VIE.use()```.
// **Parameters**:
// *nothing*
// **Throws**:
// *nothing*
// **Returns**:
// *{VIE.SocialSemanticService}* : The VIE.SocialSemanticService instance itself.
// **Example usage**:
//
//     var ssService = new vie.SocialSemanticService({<some-configuration>});
//     ssService.init();
//
        pendingCalls: {},
        pendingCallsCount : 0,
        init: function() {
            for (var key in this.options.namespaces) {
                var val = this.options.namespaces[key];
                this.vie.namespaces.add(key, val);
            }
            this.hostREST = this.options.hostREST;
            if( !this.hostREST) {
                throw new Error("no REST endpoint for SocialSemanticService defined");
            }
        },
        resolve: function(serviceCall, resultHandler, errorHandler, params) {
            this.LOG.debug('resolve', this);
            var i = 0;
            var that = this;
            var found;
            this.LOG.debug('resolve', serviceCall, params);
            if( this.pendingCalls[serviceCall] ) {
                if( found = this.findPendingCall(serviceCall, params)) {
                    this.LOG.debug('resolve params found');
                    found.resultHandlers.push(resultHandler);
                    found.errorHandlers.push(errorHandler);
                    return;
                }
            } else {
                this.pendingCalls[serviceCall] = {};
            }
            var p = {
                'params' : _.clone(params),
                'resultHandlers' : [resultHandler],
                'errorHandlers' : [errorHandler]
            };
            var pos = this.pendingCallsCount++;
            this.pendingCalls[serviceCall][pos] = p;
            this.LOG.debug('resolve pos', pos);
            this.send(serviceCall, params || {},
                    function(result) {
                        delete that.pendingCalls[serviceCall][pos];
                        that.LOG.debug("resolve resultHandlers", p);
                        _.each(p.resultHandlers, function(f) {
                            f(result);
                        });
                    },
                    function(result) {
                        delete that.pendingCalls[serviceCall][pos];
                        _.each(p.errorHandlers, function(f) {
                            f(result);
                        });
                    });

        },
        findPendingCall: function(serviceCall, params) {
            for( var fp in this.pendingCalls[serviceCall] ) {
                if( _.isEqual(this.pendingCalls[serviceCall][fp].params, params) ) {
                    return this.pendingCalls[serviceCall][fp];
                }
            }
        },
        /* AJAX request wrapper */
        send : function(op, par, success, error ){
            this.LOG.debug('par', par);
            var sss = this;
            this.vie.onUrisReady(
                this.user,
                function(userUri) {
                    $.ajax({
                        'url' : sss.hostREST + op + "/",
                        'type': "POST",
                        'data' : JSON.stringify(_.extend(par, {
                            'user' : userUri || "mailto:dummyUser",
                            'key' : sss.userKey || "someKey"
                        })),
                        'contentType' : "application/json",
                        'async' : true,
                        'dataType': "application/json",
                        'complete' : function(jqXHR, textStatus) {

                            if( jqXHR.readyState !== 4 || jqXHR.status !== 200){
                                sss.LOG.error("sss json request failed");
                                return;
                            }

                            var result = $.parseJSON(jqXHR.responseText);

                            if( result.error ) {
                                if( error ) error(result);
                                return;
                            }
                            success(result[op]);
                        }
                    });
                }
            );
        },

        getService: function(serviceName) {
            if( !SSSModel[serviceName] ) {
                throw new Error(serviceName + ' not found');
            }
            return SSSModel[serviceName];
        },

        decorateResult: function(able, result, service) {
            var sss = this,
                resultSet;
            this.LOG.debug('decorateResult', result, service);
            if( !_.isArray(result[service['resultKey']] )) {
                resultSet = [result[service['resultKey']]];
            } else {
                resultSet = result[service['resultKey']];
            }

            this.LOG.debug('resultSet', resultSet);

            _.each(resultSet, function(item) {
                sss.LOG.debug('item', item);
                // recursion
                if( service['subResults'] ) {
                    _.each(service['subResults'], function(subService) {
                        sss.decorateResult(able, item, subService);
                    });
                }
                if( service['decoration']) {
                    var i = 0, decorator;
                    for ( ; i < service['decoration'].length; i++) {
                        decorator = service['decoration'][i];
                        // invoke decorator with loadable as context on result and result meta data
                        if( !decorator.call(able, item, service['@id'], service['@type'], service['@resourceKey']) ) {
                            return;
                        }
                    }
                }
            });
        },

        invoke: function(able) {
            var params = able.options.data || {};

            var serviceName = able.options.service;
            var sss = this;
            var service = this.getService(serviceName);
            this.LOG.debug("service", service);
            if( service['preparation'] ) {
                _.each(service['preparation'], function(preparator) {
                    preparator.call(sss, params, service);
                });
            }
            this.LOG.debug('params', params);
            this.resolve(serviceName,
                function(result) {
                    sss.LOG.debug('result', result);
                    // TODO change to call in context of service, not able
                    sss.decorateResult(able, result, service);
                    // Check if pass through keys are set and pass values
                    // as object keys of second argument
                    if ( _.isArray(service['passThroughKeys']) && service['passThroughKeys'].length > 0 ) {
                        var passThrough = {};
                        _.each(service['passThroughKeys'], function(key) {
                            passThrough[key] = result[key];
                        });

                        able.resolve(result[service['resultKey']], passThrough);
                    } else {
                        able.resolve(result[service['resultKey']]);
                    }
                },
                function(result) {
                    able.reject(able.options);
                    sss.LOG.error('error:', result);
                },
                params
            );
        },

        analyze: function(analyzable) {
            var correct = analyzable instanceof this.vie.Analyzable
            if (!correct) {
                throw new Error("Invalid Analyzable passed");
            }

            this.LOG.debug("SocialSemanticService analyze");
            this.LOG.debug("analyzable",analyzable.options);
            try{
                this.invoke(analyzable);
            }catch(e) {
                this.LOG.error(e);
            }
        },
        load: function(loadable) {
            var correct = loadable instanceof this.vie.Loadable || loadable instanceof this.vie.Analyzable;
            if (!correct) {
                throw new Error("Invalid Loadable passed");
            }

            this.LOG.debug("SocialSemanticService load");
            this.LOG.debug("loadable",loadable.options);
            try{
                this.invoke(loadable);
            } catch(e) {
                this.LOG.error(e);
            }
        },

        save: function(savable) {
            var correct = savable instanceof this.vie.Savable;
            if (!correct) {
                throw "Invalid Savable passed";
            }

            this.LOG.debug("SocialSemanticService save");
            this.LOG.debug("savable.options", savable.options);

            try{
                this.invoke(savable);
            }catch(e) {
                this.LOG.error(e);
            }
        },

        remove: function(removable) {
            var correct = removable instanceof this.vie.Removable;
            if (!correct) {
                throw "Invalid Removable passed";
            }

            this.LOG.debug("SocialSemanticService remove");
            this.LOG.debug("removable.options", removable.options);

            try{
                this.invoke(removable);
                return;
            }catch(e) {
                this.LOG.error(e);
            }
        }
    };

    return VIE.prototype.SocialSemanticService;

});

<commit_msg>LL-998 #comment Added the code to force logout.<commit_after>// The SocialSemanticService wraps the SSS REST API v3.4.0

define(['logger', 'vie', 'underscore', 'voc', 'service/SocialSemanticServiceModel', 'jquery', 'UserAuth'],
function(Logger, VIE, _, Voc, SSSModel, $, UserAuth) {

// ## VIE.SocialSemanticService(options)
// This is the constructor to instantiate a new service.
// **Parameters**:
// *{object}* **options** Optional set of fields.
// **Throws**:
// *nothing*
// **Returns**:
// *{VIE.SocialSemanticService}* : A **new** VIE.SocialSemanticService instance.
// **Example usage**:
//
//     var ssService = new vie.SocialSemanticService({<some-configuration>});
    VIE.prototype.SocialSemanticService = function(options) {
        var defaults = {
            'namespaces' : {
                'sss' : "http://20130930devDays.ll/",
                'evernote' : 'https://www.evernote.com/'
            }
        };
        /* the options are merged with the default options */
        this.options = jQuery.extend(true, defaults, options ? options : {});

        this.vie = null; /* will be set via VIE.use(); */
        /* overwrite options.name if you want to set another name */
        this.name = this.options.name;

        this.user = this.options.user;
        this.userKey = this.options.userKey;

        if ( !this.user || !this.userKey )
            throw Error("No user/userKey given for SocialSemanicService");
    };

    VIE.prototype.SocialSemanticService.prototype = {

        LOG : Logger.get('SocialSemanticService'),
// ### init()
// This method initializes certain properties of the service and is called
// via ```VIE.use()```.
// **Parameters**:
// *nothing*
// **Throws**:
// *nothing*
// **Returns**:
// *{VIE.SocialSemanticService}* : The VIE.SocialSemanticService instance itself.
// **Example usage**:
//
//     var ssService = new vie.SocialSemanticService({<some-configuration>});
//     ssService.init();
//
        pendingCalls: {},
        pendingCallsCount : 0,
        init: function() {
            for (var key in this.options.namespaces) {
                var val = this.options.namespaces[key];
                this.vie.namespaces.add(key, val);
            }
            this.hostREST = this.options.hostREST;
            if( !this.hostREST) {
                throw new Error("no REST endpoint for SocialSemanticService defined");
            }
        },
        resolve: function(serviceCall, resultHandler, errorHandler, params) {
            this.LOG.debug('resolve', this);
            var i = 0;
            var that = this;
            var found;
            this.LOG.debug('resolve', serviceCall, params);
            if( this.pendingCalls[serviceCall] ) {
                if( found = this.findPendingCall(serviceCall, params)) {
                    this.LOG.debug('resolve params found');
                    found.resultHandlers.push(resultHandler);
                    found.errorHandlers.push(errorHandler);
                    return;
                }
            } else {
                this.pendingCalls[serviceCall] = {};
            }
            var p = {
                'params' : _.clone(params),
                'resultHandlers' : [resultHandler],
                'errorHandlers' : [errorHandler]
            };
            var pos = this.pendingCallsCount++;
            this.pendingCalls[serviceCall][pos] = p;
            this.LOG.debug('resolve pos', pos);
            this.send(serviceCall, params || {},
                    function(result) {
                        delete that.pendingCalls[serviceCall][pos];
                        that.LOG.debug("resolve resultHandlers", p);
                        _.each(p.resultHandlers, function(f) {
                            f(result);
                        });
                    },
                    function(result) {
                        delete that.pendingCalls[serviceCall][pos];
                        _.each(p.errorHandlers, function(f) {
                            f(result);
                        });
                    });

        },
        findPendingCall: function(serviceCall, params) {
            for( var fp in this.pendingCalls[serviceCall] ) {
                if( _.isEqual(this.pendingCalls[serviceCall][fp].params, params) ) {
                    return this.pendingCalls[serviceCall][fp];
                }
            }
        },
        /* AJAX request wrapper */
        send : function(op, par, success, error ){
            this.LOG.debug('par', par);
            var sss = this;
            this.vie.onUrisReady(
                this.user,
                function(userUri) {
                    $.ajax({
                        'url' : sss.hostREST + op + "/",
                        'type': "POST",
                        'data' : JSON.stringify(_.extend(par, {
                            'user' : userUri || "mailto:dummyUser",
                            'key' : sss.userKey || "someKey"
                        })),
                        'contentType' : "application/json",
                        'async' : true,
                        'dataType': "application/json",
                        'complete' : function(jqXHR, textStatus) {

                            if( jqXHR.readyState !== 4 || jqXHR.status !== 200){
                                sss.LOG.error("sss json request failed");
                                return;
                            }

                            var result = $.parseJSON(jqXHR.responseText);

                            if( result.error ) {
                                if( error ) error(result);

                                // This could trigger a logout
                                sss.checkErrorAndAct(error);

                                return;
                            }
                            success(result[op]);
                        }
                    });
                }
            );
        },

        getService: function(serviceName) {
            if( !SSSModel[serviceName] ) {
                throw new Error(serviceName + ' not found');
            }
            return SSSModel[serviceName];
        },

        decorateResult: function(able, result, service) {
            var sss = this,
                resultSet;
            this.LOG.debug('decorateResult', result, service);
            if( !_.isArray(result[service['resultKey']] )) {
                resultSet = [result[service['resultKey']]];
            } else {
                resultSet = result[service['resultKey']];
            }

            this.LOG.debug('resultSet', resultSet);

            _.each(resultSet, function(item) {
                sss.LOG.debug('item', item);
                // recursion
                if( service['subResults'] ) {
                    _.each(service['subResults'], function(subService) {
                        sss.decorateResult(able, item, subService);
                    });
                }
                if( service['decoration']) {
                    var i = 0, decorator;
                    for ( ; i < service['decoration'].length; i++) {
                        decorator = service['decoration'][i];
                        // invoke decorator with loadable as context on result and result meta data
                        if( !decorator.call(able, item, service['@id'], service['@type'], service['@resourceKey']) ) {
                            return;
                        }
                    }
                }
            });
        },

        invoke: function(able) {
            var params = able.options.data || {};

            var serviceName = able.options.service;
            var sss = this;
            var service = this.getService(serviceName);
            this.LOG.debug("service", service);
            if( service['preparation'] ) {
                _.each(service['preparation'], function(preparator) {
                    preparator.call(sss, params, service);
                });
            }
            this.LOG.debug('params', params);
            this.resolve(serviceName,
                function(result) {
                    sss.LOG.debug('result', result);
                    // TODO change to call in context of service, not able
                    sss.decorateResult(able, result, service);
                    // Check if pass through keys are set and pass values
                    // as object keys of second argument
                    if ( _.isArray(service['passThroughKeys']) && service['passThroughKeys'].length > 0 ) {
                        var passThrough = {};
                        _.each(service['passThroughKeys'], function(key) {
                            passThrough[key] = result[key];
                        });

                        able.resolve(result[service['resultKey']], passThrough);
                    } else {
                        able.resolve(result[service['resultKey']]);
                    }
                },
                function(result) {
                    able.reject(able.options);
                    sss.LOG.error('error:', result);
                },
                params
            );
        },

        analyze: function(analyzable) {
            var correct = analyzable instanceof this.vie.Analyzable
            if (!correct) {
                throw new Error("Invalid Analyzable passed");
            }

            this.LOG.debug("SocialSemanticService analyze");
            this.LOG.debug("analyzable",analyzable.options);
            try{
                this.invoke(analyzable);
            }catch(e) {
                this.LOG.error(e);
            }
        },
        load: function(loadable) {
            var correct = loadable instanceof this.vie.Loadable || loadable instanceof this.vie.Analyzable;
            if (!correct) {
                throw new Error("Invalid Loadable passed");
            }

            this.LOG.debug("SocialSemanticService load");
            this.LOG.debug("loadable",loadable.options);
            try{
                this.invoke(loadable);
            } catch(e) {
                this.LOG.error(e);
            }
        },

        save: function(savable) {
            var correct = savable instanceof this.vie.Savable;
            if (!correct) {
                throw "Invalid Savable passed";
            }

            this.LOG.debug("SocialSemanticService save");
            this.LOG.debug("savable.options", savable.options);

            try{
                this.invoke(savable);
            }catch(e) {
                this.LOG.error(e);
            }
        },

        remove: function(removable) {
            var correct = removable instanceof this.vie.Removable;
            if (!correct) {
                throw "Invalid Removable passed";
            }

            this.LOG.debug("SocialSemanticService remove");
            this.LOG.debug("removable.options", removable.options);

            try{
                this.invoke(removable);
                return;
            }catch(e) {
                this.LOG.error(e);
            }
        },

        checkErrorAndAct: function(error) {
            if ( error && error.id === 'authOIDCUserInfoRequestFailed' ) {
                if ( UserAuth.logout() ) {
                    document.location.reload();
                }
            }
        }
    };

    return VIE.prototype.SocialSemanticService;

});

<|endoftext|>


<commit_before>'use strict';

var express = require('express');
var router = express.Router();

var moment = require("moment");
var later = require("later");
var botgram = require("botgram");

var bot = botgram(process.env.TELEGRAM_TOKEN);

const ConfigState = {
	NONE: 0,
	DATE: 1,
	DATE_CONFIRMATION: 2,
	PILL_TYPE: 3,
	ALARM_TIME: 4,
	COMPLETED: 5
};

var timers = {};

// todo: check if context is unique per user. Set 2 timers at the same time using different users
bot.context({ isAsking: ConfigState.NONE });

bot.command("start", function (msg, reply, next) {
	console.log("Start from: ", msg.from.id);

	// todo: localize strings in english
	reply.text("Ciao! Sono Bibot.");

	askStepDate(msg, reply);
});

bot.text(function (msg, reply, next) {
	console.log("Received a text message:", msg.text);

	switch (msg.context.isAsking) {
		case ConfigState.DATE:
			stepDate(msg, reply);
			break;

		case ConfigState.DATE_CONFIRMATION:
			stepDateConfirmation(msg, reply);
			break;

		case ConfigState.PILL_TYPE:
			stepPillType(msg, reply);
			break;

		case ConfigState.ALARM_TIME:
			stepAlarmTime(msg, reply);
			break;
	}
});

function askStepDate(msg, reply) {
	let today = moment().format("YYYY-MM-DD");
	msg.context.isAsking = ConfigState.DATE;
	reply.text("In che giorno hai iniziato a prendere la pillola? Ad esempio: " + today);
}

function stepDate(msg, reply) {
	let dateRaw = msg.text;
	let date = moment(dateRaw, "YYYY-MM-DD");

	if (!date.isValid()) {
		reply.text("La data è errata. Puoi reinserirla?");
		return;
	}

	msg.context.isAsking = ConfigState.DATE_CONFIRMATION;
	msg.context.stepDate = date;
	let formatted = date.locale("IT").format("dddd, D MMMM YYYY");
	// todo: give options to be selected, instead of this
	reply.text("Confermi questa data? (S/N) \n" + formatted);
}

function stepDateConfirmation(msg, reply) {
	let answerText = msg.text.toLowerCase();

	if (answerText == "n" || answerText == "no") {
		reply.text("Va bene, ricominciamo.");
		askStepDate(msg, reply);
		return;
	}

	if (answerText != "s" && answerText != "si") {
		reply.text("Lo prendo come un no.");
		askStepDate(msg, reply);
		return;
	}

	askStepPillType(msg, reply);
}

function askStepPillType(msg, reply) {
	msg.context.isAsking = ConfigState.PILL_TYPE;
	msg.context.stepDateConfirmation = true;
	reply.text("Prendi una pillola da 21 o da 28 giorni? (21/28)");
}

function stepPillType(msg, reply) {
	let pillType = msg.text;

	if (pillType != "21" && pillType != "28") {
		reply.text("Scusa, non ho capito.");
		askStepPillType(msg, reply);
		return;
	}

	msg.context.stepPillType = pillType;

	askStepAlarmTime(msg, reply);
}

function askStepAlarmTime(msg, reply) {
	msg.context.isAsking = ConfigState.ALARM_TIME;
	reply.text("A che ora vuoi che ti avvisi? Ad esempio: 20:00");
}

function stepAlarmTime(msg, reply) {
	let timeRaw = msg.text;
	let time = moment(timeRaw, ['h:m a', 'H:m']);

	if (!time.isValid()) {
		reply.text("Non riesco a capire l'orario. Puoi scriverlo di nuovo?");
		return;
	}

	msg.context.isAsking = ConfigState.COMPLETED;
	msg.context.stepAlarmTime = time;

	setScheduling(msg, reply);
}

function setScheduling(msg, reply) {
	let startingDateMoment = msg.context.stepDate;
	// todo: if date is older than now, add 3 weeks
	let startingDate = startingDateMoment.utc();
	let startingDayOfYear = startingDate.format("DDD");

	let timeMoment = msg.context.stepAlarmTime;
	let time = timeMoment.utc().format("HH:mm");

	let pillType = msg.context.stepPillType;

	// let sched;
	// if (pillType == "28") {
	// 	sched = later.parse.recur().after(startingDayOfYear).dayOfYear().on(time).time();
	// }
	// else if (pillType == "21") {
	// 	// todo: this works only when starting date is after today
	// 	// check better if this really works
	// 	sched = later.parse.recur().after(startingDayOfYear).dayOfYear().on(time).time().except().every(4).weekOfYear();
	// }
	// else {
	// 	reply.text("Ho avuto dei problemi mentre impostavo il timer. Puoi ripetere ripartendo da /start?");
	// 	return;
	// }

	// // todo: 100 is too much...
	// var occurrences = later.schedule(sched).next(100);
	// var schedText = "";
	// for (var i = 0; i < 100; i++) {
	// 	schedText += occurrences[i] + '\n';
	// }

	// reply.text("Ti avviserò questi giorni: \n" + schedText);

	// // todo: ask for confirmation

	let sched = later.parse.recur().after(startingDayOfYear).dayOfYear().on(time).time();

	let timer = later.setInterval(function () {
		pillWarning(reply, startingDate, pillType);
	}, sched);

	let id = msg.chat.id;

	let oldTimer = timers[id];
	if (oldTimer) oldTimer.clear();

	timers[id] = timer;
}

function pillWarning(reply, startingDate, pillType) {
	if (pillType == "21") {
		let today = moment(new Date()).utc();

		let pastDays = startingDate.diff(today, 'days');
		// fixme: this number will get bigger and bigger
		pastDays = Math.abs(pastDays);

		let pillDay = (pastDays % 28) + 1; // this is a number between 1 and 28

		if (pillDay > 21) {
			return;
		}
	}

	// todo: insert plenty of strings and pick one randomly.
	reply.text("Ehi, prendi la pillola!");

	// todo: ask this again untill it gets an answer
}

bot.command("stop", function (msg, reply, next) {
	console.log("Stopped from: ", msg.from.id);
	msg.context.isAsking = ConfigState.NONE;

	let id = msg.chat.id;

	let oldTimer = timers[id];
	if (!oldTimer) {
		reply.text("Non hai nessun allarme da fermare!");
		return;
	}

	oldTimer.clear();
	reply.text("Ho fermato l'allarme. Puoi ripetere la configurazione con /start.");
	reply.text("Ciao, a presto!");
});

/* GET home page. */
router.get('/', function (req, res, next) {
	res.render('index', { title: 'Bibot' });
});

module.exports = router;
<commit_msg>Confimation message<commit_after>'use strict';

var express = require('express');
var router = express.Router();

var moment = require("moment");
var later = require("later");
var botgram = require("botgram");

var bot = botgram(process.env.TELEGRAM_TOKEN);

const ConfigState = {
	NONE: 0,
	DATE: 1,
	DATE_CONFIRMATION: 2,
	PILL_TYPE: 3,
	ALARM_TIME: 4,
	COMPLETED: 5
};

var timers = {};

// todo: check if context is unique per user. Set 2 timers at the same time using different users
bot.context({ isAsking: ConfigState.NONE });

bot.command("start", function (msg, reply, next) {
	console.log("Start from: ", msg.from.id);

	// todo: localize strings in english
	reply.text("Ciao! Sono Bibot.");

	askStepDate(msg, reply);
});

bot.text(function (msg, reply, next) {
	console.log("Received a text message:", msg.text);

	switch (msg.context.isAsking) {
		case ConfigState.DATE:
			stepDate(msg, reply);
			break;

		case ConfigState.DATE_CONFIRMATION:
			stepDateConfirmation(msg, reply);
			break;

		case ConfigState.PILL_TYPE:
			stepPillType(msg, reply);
			break;

		case ConfigState.ALARM_TIME:
			stepAlarmTime(msg, reply);
			break;
	}
});

function askStepDate(msg, reply) {
	let today = moment().format("YYYY-MM-DD");
	msg.context.isAsking = ConfigState.DATE;
	reply.text("In che giorno hai iniziato a prendere la pillola? Ad esempio: " + today);
}

function stepDate(msg, reply) {
	let dateRaw = msg.text;
	let date = moment(dateRaw, "YYYY-MM-DD");

	if (!date.isValid()) {
		reply.text("La data è errata. Puoi reinserirla?");
		return;
	}

	msg.context.isAsking = ConfigState.DATE_CONFIRMATION;
	msg.context.stepDate = date;
	let formatted = date.locale("IT").format("dddd, D MMMM YYYY");
	// todo: give options to be selected, instead of this
	reply.text("Confermi questa data? (S/N) \n" + formatted);
}

function stepDateConfirmation(msg, reply) {
	let answerText = msg.text.toLowerCase();

	if (answerText == "n" || answerText == "no") {
		reply.text("Va bene, ricominciamo.");
		askStepDate(msg, reply);
		return;
	}

	if (answerText != "s" && answerText != "si") {
		reply.text("Lo prendo come un no.");
		askStepDate(msg, reply);
		return;
	}

	askStepPillType(msg, reply);
}

function askStepPillType(msg, reply) {
	msg.context.isAsking = ConfigState.PILL_TYPE;
	msg.context.stepDateConfirmation = true;
	reply.text("Prendi una pillola da 21 o da 28 giorni? (21/28)");
}

function stepPillType(msg, reply) {
	let pillType = msg.text;

	if (pillType != "21" && pillType != "28") {
		reply.text("Scusa, non ho capito.");
		askStepPillType(msg, reply);
		return;
	}

	msg.context.stepPillType = pillType;

	askStepAlarmTime(msg, reply);
}

function askStepAlarmTime(msg, reply) {
	msg.context.isAsking = ConfigState.ALARM_TIME;
	reply.text("A che ora vuoi che ti avvisi? Ad esempio: 20:00");
}

function stepAlarmTime(msg, reply) {
	let timeRaw = msg.text;
	let time = moment(timeRaw, ['h:m a', 'H:m']);

	if (!time.isValid()) {
		reply.text("Non riesco a capire l'orario. Puoi scriverlo di nuovo?");
		return;
	}

	msg.context.isAsking = ConfigState.COMPLETED;
	msg.context.stepAlarmTime = time;

	setScheduling(msg, reply);
}

function setScheduling(msg, reply) {
	let startingDateMoment = msg.context.stepDate;
	// todo: if date is older than now, add 3 weeks
	let startingDate = startingDateMoment.utc();
	let startingDayOfYear = startingDate.format("DDD");

	let timeMoment = msg.context.stepAlarmTime;
	let time = timeMoment.utc().format("HH:mm");

	let pillType = msg.context.stepPillType;

	// let sched;
	// if (pillType == "28") {
	// 	sched = later.parse.recur().after(startingDayOfYear).dayOfYear().on(time).time();
	// }
	// else if (pillType == "21") {
	// 	// todo: this works only when starting date is after today
	// 	// check better if this really works
	// 	sched = later.parse.recur().after(startingDayOfYear).dayOfYear().on(time).time().except().every(4).weekOfYear();
	// }
	// else {
	// 	reply.text("Ho avuto dei problemi mentre impostavo il timer. Puoi ripetere ripartendo da /start?");
	// 	return;
	// }

	// // todo: 100 is too much...
	// var occurrences = later.schedule(sched).next(100);
	// var schedText = "";
	// for (var i = 0; i < 100; i++) {
	// 	schedText += occurrences[i] + '\n';
	// }

	// reply.text("Ti avviserò questi giorni: \n" + schedText);

	// // todo: ask for confirmation

	let sched = later.parse.recur().after(startingDayOfYear).dayOfYear().on(time).time();

	let timer = later.setInterval(function () {
		pillWarning(reply, startingDate, pillType);
	}, sched);

	let id = msg.chat.id;

	let oldTimer = timers[id];
	if (oldTimer) oldTimer.clear();

	timers[id] = timer;

	reply.text("Promemoria settato!");
}

function pillWarning(reply, startingDate, pillType) {
	if (pillType == "21") {
		let today = moment(new Date()).utc();

		let pastDays = startingDate.diff(today, 'days');
		// fixme: this number will get bigger and bigger
		pastDays = Math.abs(pastDays);

		let pillDay = (pastDays % 28) + 1; // this is a number between 1 and 28

		if (pillDay > 21) {
			return;
		}
	}

	// todo: insert plenty of strings and pick one randomly.
	reply.text("Ehi, prendi la pillola!");

	// todo: ask this again untill it gets an answer
}

bot.command("stop", function (msg, reply, next) {
	console.log("Stopped from: ", msg.from.id);
	msg.context.isAsking = ConfigState.NONE;

	let id = msg.chat.id;

	let oldTimer = timers[id];
	if (!oldTimer) {
		reply.text("Non hai nessun allarme da fermare!");
		return;
	}

	oldTimer.clear();
	reply.text("Ho fermato l'allarme. Puoi ripetere la configurazione con /start.");
	reply.text("Ciao, a presto!");
});

/* GET home page. */
router.get('/', function (req, res, next) {
	res.render('index', { title: 'Bibot' });
});

module.exports = router;
<|endoftext|>


<commit_before>(function() {
  'use strict';
  var gulp = require('gulp');
  var order = require('gulp-order');
  var concat = require('gulp-concat');
  var plumber = require('gulp-plumber');
  var sourcemaps = require('gulp-sourcemaps');
  var babel = require('gulp-babel');
  var connect = require('gulp-connect');
  // var uglify = require('uglify');

  gulp.task('bundle', bundle);
  // gulp.task('vendor', vendor);
  // gulp.task('css', css);
  gulp.task('start-web-server', startWebServer);
  gulp.task('watch', watch);
  gulp.task('default', ['bundle', 'start-web-server', 'watch']); //'vendor', 'css'

  ////////////////////

  var jsFiles = [
    'app/**/*.js',
    '!app/bower_components/**/*',
    '!app/content/bundle.js'
  ];
  // var vendorJSFiles = [
  //   'app/bower_components/jquery/dist/jquery.min.js',
  //   'app/bower_components/bootstrap/dist/js/bootstrap.min.js',
  //   'app/bower_components/angular-loader/angular-loader.min.js',
  //   'app/bower_components/angular/angular.js',
  //   'app/bower_components/angular-ui-router/release/angular-ui-router.js',
  //   'app/bower_components/angular-flash-alert/dist/angular-flash.js',
  //   'app/bower_components/textAngular/dist/textAngular-rangy.min.js',
  //   'app/bower_components/textAngular/dist/textAngular-sanitize.min.js',
  //   'app/bower_components/textAngular/dist/textAngular.min.js'
  // ];
  // var vendorCSSFiles = [
  //   <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Merriweather:400,300,300italic|Oxygen:400,300,700">
  //   'content/bower_components/font-awesome/css/font-awesome.css',
  //   'content/bower_components/bootstrap/dist/css/bootstrap.css',
  //   'content/bower_components/textAngular/dist/textAngular.css'
  // ];

  function bundle() {
    return gulp.src(jsFiles)
      .pipe(order([
        'app/app.module.js',              // put the main module first
        'app/**/*.module.js',             // followed by all other modules
        'app/**/*.js'                     // and all other JS files
      ], { base: './' }))
      .pipe(plumber())                    // restart gulp on error
      .pipe(sourcemaps.init())            // let sourcemaps watch this pipeline
      .pipe(babel({
        presets: ['es2015']
      }))                                 // transpile into ES5 for browsers
      .pipe(concat('bundle.js'))          // concatenate all JS files
      .pipe(sourcemaps.write('.'))        // emit the .map file for debugging
      .pipe(gulp.dest('app/content'));
  }

  // function vendor() {
  //   return gulp.src(vendorJSFiles)
  //     .pipe(order([
  //       'app/app.module.js',              // put the main module first
  //       'app/**/*.module.js',             // followed by all other modules
  //       'app/**/*.js'                     // and all other JS files
  //     ], { base: './' }))
  //     .pipe(plumber())                    // restart gulp on error
  //     .pipe(sourcemaps.init())            // let sourcemaps watch this pipeline
  //     .pipe(babel({
  //       presets: ['es2015']
  //     }))                                 // transpile into ES5 for browsers
  //     .pipe(concat('bundle.js'))
  //     .pipe(uglify())          // concatenate all JS files
  //     .pipe(sourcemaps.write('.'))        // emit the .map file for debugging
  //     .pipe(gulp.dest('app/content'));
  // }
  {/*function css(){
    return gulp.src(vendorCssFiles)
  }*/}

  function startWebServer() {
    connect.server({
      root: 'app',
      port: 8000
    });
  }

  function watch() {
    gulp.watch(['app/**/*', 'gulpfile.js'], ['bundle']); //'!app/content/bundle.*' ['vendor', 'css']
  }
})();
<commit_msg>Add heroku port display<commit_after>(function() {
  'use strict';
  var gulp = require('gulp');
  var order = require('gulp-order');
  var concat = require('gulp-concat');
  var plumber = require('gulp-plumber');
  var sourcemaps = require('gulp-sourcemaps');
  var babel = require('gulp-babel');
  var connect = require('gulp-connect');
  // var uglify = require('uglify');

  gulp.task('bundle', bundle);
  // gulp.task('vendor', vendor);
  // gulp.task('css', css);
  gulp.task('start-web-server', startWebServer);
  gulp.task('watch', watch);
  gulp.task('default', ['bundle', 'start-web-server', 'watch']); //'vendor', 'css'

  ////////////////////

  var jsFiles = [
    'app/**/*.js',
    '!app/bower_components/**/*',
    '!app/content/bundle.js'
  ];
  // var vendorJSFiles = [
  //   'app/bower_components/jquery/dist/jquery.min.js',
  //   'app/bower_components/bootstrap/dist/js/bootstrap.min.js',
  //   'app/bower_components/angular-loader/angular-loader.min.js',
  //   'app/bower_components/angular/angular.js',
  //   'app/bower_components/angular-ui-router/release/angular-ui-router.js',
  //   'app/bower_components/angular-flash-alert/dist/angular-flash.js',
  //   'app/bower_components/textAngular/dist/textAngular-rangy.min.js',
  //   'app/bower_components/textAngular/dist/textAngular-sanitize.min.js',
  //   'app/bower_components/textAngular/dist/textAngular.min.js'
  // ];
  // var vendorCSSFiles = [
  //   <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Merriweather:400,300,300italic|Oxygen:400,300,700">
  //   'content/bower_components/font-awesome/css/font-awesome.css',
  //   'content/bower_components/bootstrap/dist/css/bootstrap.css',
  //   'content/bower_components/textAngular/dist/textAngular.css'
  // ];

  function bundle() {
    return gulp.src(jsFiles)
      .pipe(order([
        'app/app.module.js',              // put the main module first
        'app/**/*.module.js',             // followed by all other modules
        'app/**/*.js'                     // and all other JS files
      ], { base: './' }))
      .pipe(plumber())                    // restart gulp on error
      .pipe(sourcemaps.init())            // let sourcemaps watch this pipeline
      .pipe(babel({
        presets: ['es2015']
      }))                                 // transpile into ES5 for browsers
      .pipe(concat('bundle.js'))          // concatenate all JS files
      .pipe(sourcemaps.write('.'))        // emit the .map file for debugging
      .pipe(gulp.dest('app/content'));
  }

  // function vendor() {
  //   return gulp.src(vendorJSFiles)
  //     .pipe(order([
  //       'app/app.module.js',              // put the main module first
  //       'app/**/*.module.js',             // followed by all other modules
  //       'app/**/*.js'                     // and all other JS files
  //     ], { base: './' }))
  //     .pipe(plumber())                    // restart gulp on error
  //     .pipe(sourcemaps.init())            // let sourcemaps watch this pipeline
  //     .pipe(babel({
  //       presets: ['es2015']
  //     }))                                 // transpile into ES5 for browsers
  //     .pipe(concat('bundle.js'))
  //     .pipe(uglify())          // concatenate all JS files
  //     .pipe(sourcemaps.write('.'))        // emit the .map file for debugging
  //     .pipe(gulp.dest('app/content'));
  // }
  {/*function css(){
    return gulp.src(vendorCssFiles)
  }*/}

  function startWebServer() {
    connect.server({
      root: 'app',
      port: prcess.env.PORT||8000
    });
  }

  function watch() {
    gulp.watch(['app/**/*', 'gulpfile.js'], ['bundle']); //'!app/content/bundle.*' ['vendor', 'css']
  }
})();
<|endoftext|>


<commit_before>import { module, test } from 'qunit';
import Satellite from 'smoke-and-mirrors/models/satellite';

const RELATIVE_UNIT = 100;
var App = {};

module('Unit | Model | Satellite', {

  beforeEach(assert) {
    App.planetADiv = document.createElement('div');
    App.planetADiv.style.width = RELATIVE_UNIT;
    App.planetADiv.style.height = RELATIVE_UNIT;
    App.planetADiv.style.position = "absolute";
    App.planetADiv.style.top = (RELATIVE_UNIT + 1) + "px";
    App.planetADiv.style.left = (RELATIVE_UNIT + 1) + "px";
    document.body.appendChild(App.planetADiv);
  },

  afterEach(assert) {
    App.planetADiv.parentNode.removeChild(App.planetADiv);
    App = {};
  }

});

test('Satellite should build correctly', function(assert) {

  let component = { element: App.planetADiv };
  let satellite = new Satellite(component);

  assert.equal(satellite.component, component, 'component set');
  assert.equal(satellite.element, component.element, 'element set');

});

test('resize returns adjustment', function(assert) {

  assert.expect(3);

  let component = { element: App.planetADiv };
  let satellite = new Satellite(component);

  let noChangeResult = satellite.resize();

  assert.equal(noChangeResult, null, 'nothing has changed');

  component.element.style.width = (RELATIVE_UNIT / 2) + "px";
  component.element.style.height = (RELATIVE_UNIT / 2) + "px";

  let result = satellite.resize();

  // Need assertions to test if heightDidChange() and widthDidChange() are called

  assert.equal(result.dX, -(RELATIVE_UNIT / 2), 'width is adjusted -50px');
  assert.equal(result.dY, -(RELATIVE_UNIT / 2), 'height is not adjusted');

});

test('shift adjusts the positions', function(assert) {

  assert.expect(2);

  let component = { element: App.planetADiv };
  let satellite = new Satellite(component);

  satellite.shift(RELATIVE_UNIT, RELATIVE_UNIT);

  assert.equal(satellite.geography.top, 1, "element is now 1px from top");
  assert.equal(satellite.geography.left, 1, "element is now 1px from left");

});

test('destroy is destructive', function(assert) {

  let component = { element: App.planetADiv };
  let satellite = new Satellite(component);
  satellite.destroy();

  assert.notOk(satellite.geography, 'geography destroyed and set to null');
  assert.notOk(satellite.component, 'component set to null');
  assert.notOk(satellite.element, 'element is set to null');

});
<commit_msg>Add test for register and unregister satellite<commit_after>import { module, test } from 'qunit';
import Satellite from 'smoke-and-mirrors/models/satellite';

const RELATIVE_UNIT = 100;
var App = {};

module('Unit | Model | Satellite', {

  beforeEach(assert) {
    App.planetADiv = document.createElement('div');
    App.planetADiv.style.width = RELATIVE_UNIT;
    App.planetADiv.style.height = RELATIVE_UNIT;
    App.planetADiv.style.position = "absolute";
    App.planetADiv.style.top = (RELATIVE_UNIT + 1) + "px";
    App.planetADiv.style.left = (RELATIVE_UNIT + 1) + "px";
    document.body.appendChild(App.planetADiv);
  },

  afterEach(assert) {
    App.planetADiv.parentNode.removeChild(App.planetADiv);
    App = {};
  }

});

test('Satellite should build correctly', function(assert) {

  assert.expect(4);

  let component = { element: App.planetADiv,
                    registerSatellite() {
                      assert.ok(true, 'The Component registerSatellite hook is called');
                    },
                    unregisterSatellite() {
                      assert.ok(true, 'The Component unregisterSatellite hook is called');
                    }
                  };
  let satellite = new Satellite(component);

  assert.equal(satellite.component, component, 'component set');
  assert.equal(satellite.element, component.element, 'element set');

});

test('resize returns adjustment', function(assert) {

  assert.expect(3);

  let component = { element: App.planetADiv };
  let satellite = new Satellite(component);

  let noChangeResult = satellite.resize();

  assert.equal(noChangeResult, null, 'nothing has changed');

  component.element.style.width = (RELATIVE_UNIT / 2) + "px";
  component.element.style.height = (RELATIVE_UNIT / 2) + "px";

  let result = satellite.resize();

  // Need assertions to test if heightDidChange() and widthDidChange() are called

  assert.equal(result.dX, -(RELATIVE_UNIT / 2), 'width is adjusted -50px');
  assert.equal(result.dY, -(RELATIVE_UNIT / 2), 'height is not adjusted');

});

test('shift adjusts the positions', function(assert) {

  assert.expect(2);

  let component = { element: App.planetADiv };
  let satellite = new Satellite(component);

  satellite.shift(RELATIVE_UNIT, RELATIVE_UNIT);

  assert.equal(satellite.geography.top, 1, "element is now 1px from top");
  assert.equal(satellite.geography.left, 1, "element is now 1px from left");

});

test('destroy is destructive', function(assert) {

  let component = { element: App.planetADiv };
  let satellite = new Satellite(component);
  satellite.destroy();

  assert.notOk(satellite.geography, 'geography destroyed and set to null');
  assert.notOk(satellite.component, 'component set to null');
  assert.notOk(satellite.element, 'element is set to null');

});
<|endoftext|>


<commit_before>/**
 * MenuButton.js
 *
 * Released under LGPL License.
 * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
 *
 * License: http://www.tinymce.com/license
 * Contributing: http://www.tinymce.com/contributing
 */

/**
 * Creates a new menu button.
 *
 * @-x-less MenuButton.less
 * @class tinymce.ui.MenuButton
 * @extends tinymce.ui.Button
 */
define("tinymce/ui/MenuButton", [
	"tinymce/ui/Button",
	"tinymce/ui/Factory",
	"tinymce/ui/MenuBar"
], function(Button, Factory, MenuBar) {
	"use strict";

	// TODO: Maybe add as some global function
	function isChildOf(node, parent) {
		while (node) {
			if (parent === node) {
				return true;
			}

			node = node.parentNode;
		}

		return false;
	}

	var MenuButton = Button.extend({
		/**
		 * Constructs a instance with the specified settings.
		 *
		 * @constructor
		 * @param {Object} settings Name/value object with settings.
		 */
		init: function(settings) {
			var self = this;

			self._renderOpen = true;

			self._super(settings);
			settings = self.settings;

			self.classes.add('menubtn');

			if (settings.fixedWidth) {
				self.classes.add('fixed-width');
			}

			self.aria('haspopup', true);

			self.state.set('menu', settings.menu || self.render());
		},

		/**
		 * Shows the menu for the button.
		 *
		 * @method showMenu
		 */
		showMenu: function() {
			var self = this, menu;

			if (self.menu && self.menu.visible()) {
				return self.hideMenu();
			}

			if (!self.menu) {
				menu = self.state.get('menu') || [];

				// Is menu array then auto constuct menu control
				if (menu.length) {
					menu = {
						type: 'menu',
						items: menu
					};
				} else {
					menu.type = menu.type || 'menu';
				}

				if (!menu.renderTo) {
					self.menu = Factory.create(menu).parent(self).renderTo();
				} else {
					self.menu = menu.parent(self).show().renderTo();
				}

				self.fire('createmenu');
				self.menu.reflow();
				self.menu.on('cancel', function(e) {
					if (e.control.parent() === self.menu) {
						e.stopPropagation();
						self.focus();
						self.hideMenu();
					}
				});

				// Move focus to button when a menu item is selected/clicked
				self.menu.on('select', function() {
					self.focus();
				});

				self.menu.on('show hide', function(e) {
					if (e.control == self.menu) {
						self.activeMenu(e.type == 'show');
					}

					self.aria('expanded', e.type == 'show');
				}).fire('show');
			}

			self.menu.show();
			self.menu.layoutRect({w: self.layoutRect().w});
			self.menu.moveRel(self.getEl(), self.isRtl() ? ['br-tr', 'tr-br'] : ['bl-tl', 'tl-bl']);
		},

		/**
		 * Hides the menu for the button.
		 *
		 * @method hideMenu
		 */
		hideMenu: function() {
			var self = this;

			if (self.menu) {
				self.menu.items().each(function(item) {
					if (item.hideMenu) {
						item.hideMenu();
					}
				});

				self.menu.hide();
			}
		},

		/**
		 * Sets the active menu state.
		 *
		 * @private
		 */
		activeMenu: function(state) {
			this.classes.toggle('active', state);
		},

		/**
		 * Renders the control as a HTML string.
		 *
		 * @method renderHtml
		 * @return {String} HTML representing the control.
		 */
		renderHtml: function() {
			var self = this, id = self._id, prefix = self.classPrefix;
			var icon = self.settings.icon, image, text = self.state.get('text');

			image = self.settings.image;
			if (image) {
				icon = 'none';

				// Support for [high dpi, low dpi] image sources
				if (typeof image != "string") {
					image = window.getSelection ? image[0] : image[1];
				}

				image = ' style="background-image: url(\'' + image + '\')"';
			} else {
				image = '';
			}

			icon = self.settings.icon ? prefix + 'ico ' + prefix + 'i-' + icon : '';

			self.aria('role', self.parent() instanceof MenuBar ? 'menuitem' : 'button');

			return (
				'
' +
					'<button id="' + id + '-open" role="presentation" type="button" tabindex="-1">' +
						(icon ? '' : '') +
						(text ? (icon ? '\u00a0' : '') + self.encode(text) : '') +
						' ' +
					'</button>' +
				'
'
			);
		},

		/**
		 * Gets invoked after the control has been rendered.
		 *
		 * @method postRender
		 */
		postRender: function() {
			var self = this;

			self.on('click', function(e) {
				if (e.control === self && isChildOf(e.target, self.getEl())) {
					self.showMenu();

					if (e.aria) {
						self.menu.items()[0].focus();
					}
				}
			});

			self.on('mouseenter', function(e) {
				var overCtrl = e.control, parent = self.parent(), hasVisibleSiblingMenu;

				if (overCtrl && parent && overCtrl instanceof MenuButton && overCtrl.parent() == parent) {
					parent.items().filter('MenuButton').each(function(ctrl) {
						if (ctrl.hideMenu && ctrl != overCtrl) {
							if (ctrl.menu && ctrl.menu.visible()) {
								hasVisibleSiblingMenu = true;
							}

							ctrl.hideMenu();
						}
					});

					if (hasVisibleSiblingMenu) {
						overCtrl.focus(); // Fix for: #5887
						overCtrl.showMenu();
					}
				}
			});

			return self._super();
		},

		bindStates: function() {
			var self = this;

			self.state.on('change:menu', function() {
				if (self.menu) {
					self.menu.remove();
				}

				self.menu = null;
			});

			return self._super();
		},

		/**
		 * Removes the control and it's menus.
		 *
		 * @method remove
		 */
		remove: function() {
			this._super();

			if (this.menu) {
				this.menu.remove();
			}
		}
	});

	return MenuButton;
});<commit_msg>Fix fixed width menu button display<commit_after>/**
 * MenuButton.js
 *
 * Released under LGPL License.
 * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
 *
 * License: http://www.tinymce.com/license
 * Contributing: http://www.tinymce.com/contributing
 */

/**
 * Creates a new menu button.
 *
 * @-x-less MenuButton.less
 * @class tinymce.ui.MenuButton
 * @extends tinymce.ui.Button
 */
define("tinymce/ui/MenuButton", [
	"tinymce/ui/Button",
	"tinymce/ui/Factory",
	"tinymce/ui/MenuBar"
], function(Button, Factory, MenuBar) {
	"use strict";

	// TODO: Maybe add as some global function
	function isChildOf(node, parent) {
		while (node) {
			if (parent === node) {
				return true;
			}

			node = node.parentNode;
		}

		return false;
	}

	var MenuButton = Button.extend({
		/**
		 * Constructs a instance with the specified settings.
		 *
		 * @constructor
		 * @param {Object} settings Name/value object with settings.
		 */
		init: function(settings) {
			var self = this;

			self._renderOpen = true;

			self._super(settings);
			settings = self.settings;

			self.classes.add('menubtn');

			if (settings.fixedWidth) {
				self.classes.add('fixed-width');
			}

			self.aria('haspopup', true);

			self.state.set('menu', settings.menu || self.render());
		},

		/**
		 * Shows the menu for the button.
		 *
		 * @method showMenu
		 */
		showMenu: function() {
			var self = this, menu;

			if (self.menu && self.menu.visible()) {
				return self.hideMenu();
			}

			if (!self.menu) {
				menu = self.state.get('menu') || [];

				// Is menu array then auto constuct menu control
				if (menu.length) {
					menu = {
						type: 'menu',
						items: menu
					};
				} else {
					menu.type = menu.type || 'menu';
				}

				if (!menu.renderTo) {
					self.menu = Factory.create(menu).parent(self).renderTo();
				} else {
					self.menu = menu.parent(self).show().renderTo();
				}

				self.fire('createmenu');
				self.menu.reflow();
				self.menu.on('cancel', function(e) {
					if (e.control.parent() === self.menu) {
						e.stopPropagation();
						self.focus();
						self.hideMenu();
					}
				});

				// Move focus to button when a menu item is selected/clicked
				self.menu.on('select', function() {
					self.focus();
				});

				self.menu.on('show hide', function(e) {
					if (e.control == self.menu) {
						self.activeMenu(e.type == 'show');
					}

					self.aria('expanded', e.type == 'show');
				}).fire('show');
			}

			self.menu.show();
			self.menu.layoutRect({w: self.layoutRect().w});
			self.menu.moveRel(self.getEl(), self.isRtl() ? ['br-tr', 'tr-br'] : ['bl-tl', 'tl-bl']);
		},

		/**
		 * Hides the menu for the button.
		 *
		 * @method hideMenu
		 */
		hideMenu: function() {
			var self = this;

			if (self.menu) {
				self.menu.items().each(function(item) {
					if (item.hideMenu) {
						item.hideMenu();
					}
				});

				self.menu.hide();
			}
		},

		/**
		 * Sets the active menu state.
		 *
		 * @private
		 */
		activeMenu: function(state) {
			this.classes.toggle('active', state);
		},

		/**
		 * Renders the control as a HTML string.
		 *
		 * @method renderHtml
		 * @return {String} HTML representing the control.
		 */
		renderHtml: function() {
			var self = this, id = self._id, prefix = self.classPrefix;
			var icon = self.settings.icon, image, text = self.state.get('text');

			image = self.settings.image;
			if (image) {
				icon = 'none';

				// Support for [high dpi, low dpi] image sources
				if (typeof image != "string") {
					image = window.getSelection ? image[0] : image[1];
				}

				image = ' style="background-image: url(\'' + image + '\')"';
			} else {
				image = '';
			}

			icon = self.settings.icon ? prefix + 'ico ' + prefix + 'i-' + icon : '';

			self.aria('role', self.parent() instanceof MenuBar ? 'menuitem' : 'button');

			return (
				'
' +
					'<button id="' + id + '-open" role="presentation" type="button" tabindex="-1">' +
						(icon ? '' : '') +
						(self.settings.fixedWidth ? '' : '') +
						(text ? (icon ? '\u00a0' : '') + self.encode(text) : '') +
						(self.settings.fixedWidth ? '' : '') +
						' ' +
					'</button>' +
				'
'
			);
		},

		/**
		 * Gets invoked after the control has been rendered.
		 *
		 * @method postRender
		 */
		postRender: function() {
			var self = this;

			self.on('click', function(e) {
				if (e.control === self && isChildOf(e.target, self.getEl())) {
					self.showMenu();

					if (e.aria) {
						self.menu.items()[0].focus();
					}
				}
			});

			self.on('mouseenter', function(e) {
				var overCtrl = e.control, parent = self.parent(), hasVisibleSiblingMenu;

				if (overCtrl && parent && overCtrl instanceof MenuButton && overCtrl.parent() == parent) {
					parent.items().filter('MenuButton').each(function(ctrl) {
						if (ctrl.hideMenu && ctrl != overCtrl) {
							if (ctrl.menu && ctrl.menu.visible()) {
								hasVisibleSiblingMenu = true;
							}

							ctrl.hideMenu();
						}
					});

					if (hasVisibleSiblingMenu) {
						overCtrl.focus(); // Fix for: #5887
						overCtrl.showMenu();
					}
				}
			});

			return self._super();
		},

		bindStates: function() {
			var self = this;

			self.state.on('change:menu', function() {
				if (self.menu) {
					self.menu.remove();
				}

				self.menu = null;
			});

			return self._super();
		},

		/**
		 * Removes the control and it's menus.
		 *
		 * @method remove
		 */
		remove: function() {
			this._super();

			if (this.menu) {
				this.menu.remove();
			}
		}
	});

	return MenuButton;
});<|endoftext|>


<commit_before>var express  = require('express');
var router   = express.Router();
var multer   = require('multer');
var crypto   = require('crypto');
var mime     = require('mime');
var User     = require('../models/user');
var passport = require('passport');

/*// Config multer for upload pictures.
var uploading = multer({
    limits: { fileSize: 10000000, files: 1},
    storage: multer.diskStorage({
        destination: function(req, file, cb) {
            cb(null, './public/img/user_pictures');
        },
        filename: function (req, file, cb) {
            crypto.pseudoRandomBytes(16, function (err, raw) {
                cb(null, raw.toString('hex') + Date.now() + '.' + mime.extension(file.mimetype));
            });
        }
    })
});*/

router.get('/', function(req, res){
    res.render('home');
});

// Show register template.
router.get('/register', function(req, res) {
    res.render('register');
});

// New - Register a user
router.post('/register', function(req, res, next) {
    var newUser = new User({
        username: req.body.username,
        name: req.body.name,
        age: req.body.age,
        email: req.body.email,
        picture: req.body.picture
    });
    User.register(newUser, req.body.password, function(err, user){
        if (err) {
            console.log('Error: ' + err);
            return res.render('register');
        }
        passport.authenticate('local')(req, res, function() {
            res.redirect('/campgrounds');
        });

    });
});

router.get('/login', function(req, res) {
    res.render('login');
});

router.post('/login', passport.authenticate('local', {
    'successRedirect': "/campgrounds",
    'failureRedirect': "/login"
}));

router.get('/logout', function(req, res) {
    req.logout();
    res.redirect('/campgrounds  ');
});

// Middleware.
function isLoggedIn(req, res, next) {
    if (req.isAuthenticated()) {
        return next();
    }
    res.redirect("/login");
}

module.exports = router;
<commit_msg>Delete isLoggedIn middleware<commit_after>var express  = require('express');
var router   = express.Router();
var multer   = require('multer');
var crypto   = require('crypto');
var mime     = require('mime');
var User     = require('../models/user');
var passport = require('passport');

/*// Config multer for upload pictures.
var uploading = multer({
    limits: { fileSize: 10000000, files: 1},
    storage: multer.diskStorage({
        destination: function(req, file, cb) {
            cb(null, './public/img/user_pictures');
        },
        filename: function (req, file, cb) {
            crypto.pseudoRandomBytes(16, function (err, raw) {
                cb(null, raw.toString('hex') + Date.now() + '.' + mime.extension(file.mimetype));
            });
        }
    })
});*/

router.get('/', function(req, res){
    res.render('home');
});

// Show register template.
router.get('/register', function(req, res) {
    res.render('register');
});

// New - Register a user
router.post('/register', function(req, res, next) {
    var newUser = new User({
        username: req.body.username,
        name: req.body.name,
        age: req.body.age,
        email: req.body.email,
        picture: req.body.picture
    });
    User.register(newUser, req.body.password, function(err, user){
        if (err) {
            console.log('Error: ' + err);
            return res.render('register');
        }
        passport.authenticate('local')(req, res, function() {
            res.redirect('/campgrounds');
        });

    });
});

router.get('/login', function(req, res) {
    res.render('login');
});

router.post('/login', passport.authenticate('local', {
    'successRedirect': "/campgrounds",
    'failureRedirect': "/login"
}));

router.get('/logout', function(req, res) {
    req.logout();
    res.redirect('/campgrounds  ');
});

module.exports = router;
<|endoftext|>


<commit_before>"use strict";
require('reflect-metadata');
var Parameter_1 = require('../parameters/Parameter');
var KeyFactory_1 = require('./KeyFactory');
var IOC_METADATA_KEY = 'ioc:metadata';
var RegistrationMetadata = (function () {
    function RegistrationMetadata(factory) {
        this.factory = factory;
        this.initializers = [];
        this.key = KeyFactory_1.default.create(factory);
        this.findDependencies();
    }
    RegistrationMetadata.findOrCreate = function (factory) {
        var existingMetadata = Reflect.getMetadata(IOC_METADATA_KEY, factory);
        if (existingMetadata != null) {
            return existingMetadata;
        }
        var metadata = new RegistrationMetadata(factory);
        Reflect.defineMetadata(IOC_METADATA_KEY, metadata, factory);
        return metadata;
    };
    RegistrationMetadata.prototype.initializeRegistration = function (registration) {
        this.initializers.forEach(function (init) { return init(registration); });
    };
    RegistrationMetadata.prototype.addInitialization = function (initializer) {
        this.initializers.push(initializer);
    };
    RegistrationMetadata.prototype.findDependencies = function () {
        var paramTypes = Reflect.getMetadata('design:paramtypes', this.factory);
        if (paramTypes != null) {
            this.addInitialization(function (registration) {
                registration.parameters = paramTypes.map(function (t) { return new Parameter_1.default(t); });
            });
        }
    };
    return RegistrationMetadata;
}());
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = RegistrationMetadata;
<commit_msg>Fixed a bug where sub types may register properties on super types.<commit_after>"use strict";
require('reflect-metadata');
var Parameter_1 = require('../parameters/Parameter');
var KeyFactory_1 = require('./KeyFactory');
var IOC_METADATA_KEY = 'ioc:metadata';
var RegistrationMetadata = (function () {
    function RegistrationMetadata(factory) {
        this.factory = factory;
        this.initializers = [];
        this.key = KeyFactory_1.default.create(factory);
        this.findDependencies();
    }
    RegistrationMetadata.findOrCreate = function (factory) {
        var existingMetadata = Reflect.getOwnMetadata(IOC_METADATA_KEY, factory);
        if (existingMetadata != null) {
            return existingMetadata;
        }
        var metadata = new RegistrationMetadata(factory);
        Reflect.defineMetadata(IOC_METADATA_KEY, metadata, factory);
        return metadata;
    };
    RegistrationMetadata.prototype.initializeRegistration = function (registration) {
        this.initializers.forEach(function (init) { return init(registration); });
    };
    RegistrationMetadata.prototype.addInitialization = function (initializer) {
        this.initializers.push(initializer);
    };
    RegistrationMetadata.prototype.findDependencies = function () {
        var paramTypes = Reflect.getMetadata('design:paramtypes', this.factory);
        if (paramTypes != null) {
            this.addInitialization(function (registration) {
                registration.parameters = paramTypes.map(function (t) { return new Parameter_1.default(t); });
            });
        }
    };
    return RegistrationMetadata;
}());
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = RegistrationMetadata;
<|endoftext|>