<commit_before>var os = require('os');
var path = require('path');
var moment = require('moment');
var chalk = require('chalk');
var nunjucks = require('nunjucks');
var express = require('express');
var bodyParser = require('body-parser');
var morgan = require('morgan');
var builder = require('./builder');
var watcher = require('./watcher');
var settings = require('./settings');
var utils = require('./utils');
var Builder = builder.Builder;
var Watcher = watcher.Watcher;

function createApp(builder, logAll) {
  // Express application
  var app = express();

  // Attach watcher
  app.watcher = watcher || null;

  // Middleware
  app.use(bodyParser.urlencoded({extended: false}));
  app.use(morgan(function (tokens, req, res) {
    var status = res.statusCode;
    var color;
    if (status === 404) { color = 33; }       // yellow
    else if (status === 304) { color = 36; }  // cyan
    else if (status >= 500) { color = 95; }   // magenta
    else if (status >= 400) { color = 91; }   // red
    else if (status >= 300) { color = 32; }   // green
    else { color = 90; }                      // dark gray (gray = 37)
    return ('\u001b[' + color + 'm' +
      ('[' + moment().format('DD/MMM/YYYY HH:mm:ss') + '] ') +
      (tokens.method(req, res, 'undefined') || '-') + ' ' +
      (tokens.url(req, res, 'undefined') || '-') + ' ' +
      (tokens.status(req, res, 'undefined') || '-') + ' ' +
      (tokens.res(req, res, 'content-length') || '-') + '\u001b[0m');
  }, {
    skip: function (req, res) {
      if (utils.startsWith(req.url, '/log')) {
        return true;
      }
      return !logAll && (
        utils.startsWith(req.url, '/images') || utils.startsWith(req.url, '/scripts') ||
        utils.startsWith(req.url, '/styles') || utils.startsWith(req.url, '/vendor'));
    }
  }));
  app.use(express.static(path.join(__dirname, 'public')));

  // Configure extensions
  nunjucks.configure(path.join(__dirname, 'views'));

  // Routes
  app.get('/', function(req, res) {
    builder.ready(function(err) {
      // TODO: Get values from project settings
      res.type('html');
      res.end(nunjucks.render('index.html', {
        gessoScript: '/gesso-bundle.js',
        gessoProjectName: builder.projectName,
        gessoBuildError: err ? (err.message || String(err)) + os.EOL : null,
        canvasId: settings.CANVAS_ID,
        canvasWidth: settings.CANVAS_WIDTH,
        canvasHeight: settings.CANVAS_HEIGHT
      }));
    });
  });

  app.get('/gesso-bundle.js', function(req, res) {
    res.type('js');
    builder.ready(function(err, output) {
      res.end(output || '');
    });
  });

  app.post('/log', function(req, res) {
    if (!req.body || typeof req.body.message === 'undefined') {
      res.status(400);
      res.end('No "message" form field specified.');
      return;
    }

    var level = req.body.level || 'log';
    var messages = req.body.message.split('\n');
    for (var index = 0; index < messages.length; index++) {
      var message = '[' + moment().format('DD/MMM/YYYY HH:mm:ss') + '] Client: ' + messages[index];
      if (level === 'error') {
        message = chalk.bold.red(message);
      } else if (level === 'warn') {
        message = chalk.bold.yellow(message);
      } else if (level === 'info') {
        message = chalk.bold.cyan(message);
      } else {
        message = chalk.white(message);
      }
      console.log(message);
    }
    res.end('');
  });

  return app;
}

function serve(options) {
  options = options || {};

  // Create builder and watcher
  var builder = new Builder(options.packagePath);
  var watcher = new Watcher(builder);

  // Create the app
  var app = createApp(builder, options.logAll);

  // Run first build
  builder.build();

  // Run the server
  var port = options.port || settings.PORT;
  var host = options.host || settings.HOST;
  app.listen(port, host, function() {
    console.log(' * Listening on http://%s:%d/', host, port);

    // Start watching
    watcher.watch();
  });

  return app;
}

module.exports = {
  createApp: createApp,
  serve: serve
};
<commit_msg>Serve assets.<commit_after>var os = require('os');
var path = require('path');
var moment = require('moment');
var chalk = require('chalk');
var nunjucks = require('nunjucks');
var express = require('express');
var bodyParser = require('body-parser');
var morgan = require('morgan');
var builder = require('./builder');
var watcher = require('./watcher');
var settings = require('./settings');
var utils = require('./utils');
var Builder = builder.Builder;
var Watcher = watcher.Watcher;

function createApp(builder, logAll) {
  // Express application
  var app = express();
  app.use('/assets', express.static(path.join(builder.path, 'assets')));

  // Attach watcher
  app.watcher = watcher || null;

  // Middleware
  app.use(bodyParser.urlencoded({extended: false}));
  app.use(morgan(function (tokens, req, res) {
    var status = res.statusCode;
    var color;
    if (status === 404) { color = 33; }       // yellow
    else if (status === 304) { color = 36; }  // cyan
    else if (status >= 500) { color = 95; }   // magenta
    else if (status >= 400) { color = 91; }   // red
    else if (status >= 300) { color = 32; }   // green
    else { color = 90; }                      // dark gray (gray = 37)
    return ('\u001b[' + color + 'm' +
      ('[' + moment().format('DD/MMM/YYYY HH:mm:ss') + '] ') +
      (tokens.method(req, res, 'undefined') || '-') + ' ' +
      (tokens.url(req, res, 'undefined') || '-') + ' ' +
      (tokens.status(req, res, 'undefined') || '-') + ' ' +
      (tokens.res(req, res, 'content-length') || '-') + '\u001b[0m');
  }, {
    skip: function (req, res) {
      if (utils.startsWith(req.url, '/log')) {
        return true;
      }
      return !logAll && (
        utils.startsWith(req.url, '/images') || utils.startsWith(req.url, '/scripts') ||
        utils.startsWith(req.url, '/styles') || utils.startsWith(req.url, '/vendor'));
    }
  }));
  app.use(express.static(path.join(__dirname, 'public')));

  // Configure extensions
  nunjucks.configure(path.join(__dirname, 'views'));

  // Routes
  app.get('/', function(req, res) {
    builder.ready(function(err) {
      // TODO: Get values from project settings
      res.type('html');
      res.end(nunjucks.render('index.html', {
        gessoScript: '/gesso-bundle.js',
        gessoProjectName: builder.projectName,
        gessoBuildError: err ? (err.message || String(err)) + os.EOL : null,
        canvasId: settings.CANVAS_ID,
        canvasWidth: settings.CANVAS_WIDTH,
        canvasHeight: settings.CANVAS_HEIGHT
      }));
    });
  });

  app.get('/gesso-bundle.js', function(req, res) {
    res.type('js');
    builder.ready(function(err, output) {
      res.end(output || '');
    });
  });

  app.post('/log', function(req, res) {
    if (!req.body || typeof req.body.message === 'undefined') {
      res.status(400);
      res.end('No "message" form field specified.');
      return;
    }

    var level = req.body.level || 'log';
    var messages = req.body.message.split('\n');
    for (var index = 0; index < messages.length; index++) {
      var message = '[' + moment().format('DD/MMM/YYYY HH:mm:ss') + '] Client: ' + messages[index];
      if (level === 'error') {
        message = chalk.bold.red(message);
      } else if (level === 'warn') {
        message = chalk.bold.yellow(message);
      } else if (level === 'info') {
        message = chalk.bold.cyan(message);
      } else {
        message = chalk.white(message);
      }
      console.log(message);
    }
    res.end('');
  });

  return app;
}

function serve(options) {
  options = options || {};

  // Create builder and watcher
  var builder = new Builder(options.packagePath);
  var watcher = new Watcher(builder);

  // Create the app
  var app = createApp(builder, options.logAll);

  // Run first build
  builder.build();

  // Run the server
  var port = options.port || settings.PORT;
  var host = options.host || settings.HOST;
  app.listen(port, host, function() {
    console.log(' * Listening on http://%s:%d/', host, port);

    // Start watching
    watcher.watch();
  });

  return app;
}

module.exports = {
  createApp: createApp,
  serve: serve
};
<|endoftext|>


<commit_before>
/**
 * @ngdoc controller
 * @name Umbraco.MainController
 * @function
 *
 * @description
 * The main application controller
 *
 */
function MainController($scope, $rootScope, $location, $routeParams, $timeout, $http, $log, appState, treeService, notificationsService, userService, navigationService, historyService, legacyJsLoader, updateChecker) {

    var legacyTreeJsLoaded = false;

    //the null is important because we do an explicit bool check on this in the view
    //the avatar is by default the umbraco logo
    $scope.authenticated = null;
    $scope.avatar = "assets/img/application/logo.png";
    $scope.touchDevice = appState.getGlobalState("touchDevice");
    //subscribes to notifications in the notification service
    $scope.notifications = notificationsService.current;
    $scope.$watch('notificationsService.current', function (newVal, oldVal, scope) {
        if (newVal) {
            $scope.notifications = newVal;
        }
    });

    $scope.removeNotification = function (index) {
        notificationsService.remove(index);
    };

    $scope.closeDialogs = function (event) {
        //only close dialogs if non-link and non-buttons are clicked
        var el = event.target.nodeName;
        var els = ["INPUT","A","BUTTON"];

        if(els.indexOf(el) >= 0){return;}

        var parents = $(event.target).parents("a,button");
        if(parents.length > 0){
            return;
        }

        //SD: I've updated this so that we don't close the dialog when clicking inside of the dialog
        var nav = $(event.target).parents("#navigation");
        if (nav.length === 1) {
            return;
        }

        $rootScope.$emit("closeDialogs", event);
    };

    //when a user logs out or timesout
    $scope.$on("notAuthenticated", function() {
        $scope.authenticated = null;
        $scope.user = null;
    });

    //when a user is authorized setup the data
    $scope.$on("authenticated", function (evt, data) {

        //We need to load in the legacy tree js but only once no matter what user has logged in
        if (!legacyTreeJsLoaded) {
            legacyJsLoader.loadLegacyTreeJs($scope).then(
                function (result) {
                    legacyTreeJsLoaded = true;

                    //TODO: We could wait for this to load before running the UI ?
                });
        }

        $scope.authenticated = data.authenticated;
        $scope.user = data.user;

        updateChecker.check().then(function(update){
            if(update && update !== "null"){
                if(update.type !== "None"){
                    var notification = {
                           headline: "Update available",
                           message: "Click to download",
                           sticky: true,
                           type: "info",
                           url: update.url
                    };
                    notificationsService.add(notification);
                }
            }
        });

        //if the user has changed we need to redirect to the root so they don't try to continue editing the
        //last item in the URL (NOTE: the user id can equal zero, so we cannot just do !data.lastUserId since that will resolve to true)
        if (data.lastUserId !== undefined && data.lastUserId !== null && data.lastUserId !== data.user.id) {
            $location.path("/").search("");
            historyService.removeAll();
            treeService.clearCache();
        }

        if($scope.user.emailHash){
            $timeout(function () {
                //yes this is wrong..
                $("#avatar-img").fadeTo(1000, 0, function () {
                    $timeout(function () {
                        //this can be null if they time out
                        if ($scope.user && $scope.user.emailHash) {
                            $scope.avatar = "http://www.gravatar.com/avatar/" + $scope.user.emailHash + ".jpg?s=64&d=mm";
                        }
                    });
                    $("#avatar-img").fadeTo(1000, 1);
                });

              }, 3000);
        }

    });

}

//register it
angular.module('umbraco').controller("Umbraco.MainController", MainController);
<commit_msg>Allows people to click tree to close dialogs<commit_after>
/**
 * @ngdoc controller
 * @name Umbraco.MainController
 * @function
 *
 * @description
 * The main application controller
 *
 */
function MainController($scope, $rootScope, $location, $routeParams, $timeout, $http, $log, appState, treeService, notificationsService, userService, navigationService, historyService, legacyJsLoader, updateChecker) {

    var legacyTreeJsLoaded = false;

    //the null is important because we do an explicit bool check on this in the view
    //the avatar is by default the umbraco logo
    $scope.authenticated = null;
    $scope.avatar = "assets/img/application/logo.png";
    $scope.touchDevice = appState.getGlobalState("touchDevice");
    //subscribes to notifications in the notification service
    $scope.notifications = notificationsService.current;
    $scope.$watch('notificationsService.current', function (newVal, oldVal, scope) {
        if (newVal) {
            $scope.notifications = newVal;
        }
    });

    $scope.removeNotification = function (index) {
        notificationsService.remove(index);
    };

    $scope.closeDialogs = function (event) {
        //only close dialogs if non-link and non-buttons are clicked
        var el = event.target.nodeName;
        var els = ["INPUT","A","BUTTON"];

        if(els.indexOf(el) >= 0){return;}

        var parents = $(event.target).parents("a,button");
        if(parents.length > 0){
            return;
        }

        //SD: I've updated this so that we don't close the dialog when clicking inside of the dialog
        var nav = $(event.target).parents("#dialog");
        if (nav.length === 1) {
            return;
        }

        $rootScope.$emit("closeDialogs", event);
    };

    //when a user logs out or timesout
    $scope.$on("notAuthenticated", function() {
        $scope.authenticated = null;
        $scope.user = null;
    });

    //when a user is authorized setup the data
    $scope.$on("authenticated", function (evt, data) {

        //We need to load in the legacy tree js but only once no matter what user has logged in
        if (!legacyTreeJsLoaded) {
            legacyJsLoader.loadLegacyTreeJs($scope).then(
                function (result) {
                    legacyTreeJsLoaded = true;

                    //TODO: We could wait for this to load before running the UI ?
                });
        }

        $scope.authenticated = data.authenticated;
        $scope.user = data.user;

        updateChecker.check().then(function(update){
            if(update && update !== "null"){
                if(update.type !== "None"){
                    var notification = {
                           headline: "Update available",
                           message: "Click to download",
                           sticky: true,
                           type: "info",
                           url: update.url
                    };
                    notificationsService.add(notification);
                }
            }
        });

        //if the user has changed we need to redirect to the root so they don't try to continue editing the
        //last item in the URL (NOTE: the user id can equal zero, so we cannot just do !data.lastUserId since that will resolve to true)
        if (data.lastUserId !== undefined && data.lastUserId !== null && data.lastUserId !== data.user.id) {
            $location.path("/").search("");
            historyService.removeAll();
            treeService.clearCache();
        }

        if($scope.user.emailHash){
            $timeout(function () {
                //yes this is wrong..
                $("#avatar-img").fadeTo(1000, 0, function () {
                    $timeout(function () {
                        //this can be null if they time out
                        if ($scope.user && $scope.user.emailHash) {
                            $scope.avatar = "http://www.gravatar.com/avatar/" + $scope.user.emailHash + ".jpg?s=64&d=mm";
                        }
                    });
                    $("#avatar-img").fadeTo(1000, 1);
                });

              }, 3000);
        }

    });

}

//register it
angular.module('umbraco').controller("Umbraco.MainController", MainController);
<|endoftext|>


<commit_before>(function (angular) {
    'use strict';
    /**
     * @ngdoc function
     * @name tubularAuthInterceptor
     * @description
     *
     * Implement a httpInterceptor to handle authorization using bearer tokens
     *
     * @constructor
     * @returns {Object} A httpInterceptor
     */
    angular.module('tubular.services')
        .factory('tubularAuthInterceptor', ['$q', '$injector', 'tubularConfig', function ($q, $injector, tubularConfig) {

            var authRequestRunning = null;
            var tubularHttpName = 'tubularHttp';

            var service = {
                request: request,
                requestError: requestError,
                response: response,
                responseError: responseError
            };

            return service;

            function request(config) {
                // Get the service here because otherwise, a circular dependency injection will be detected
                var tubularHttp = $injector.get(tubularHttpName);
                var webApiSettings = tubularConfig.webApi;
                var apiBaseUrl = webApiSettings.baseUrl();

                config.headers = config.headers || {};

                // Handle requests going to API
                if (webApiSettings.tokenUrl() !== config.url &&
                    webApiSettings.requireAuthentication() &&
                    tubularHttp.userData.bearerToken) {

                    config.headers.Authorization = 'Bearer ' + tubularHttp.userData.bearerToken;

                    // When using refresh tokens and bearer token has expired,
                    // avoid the round trip on go directly to try refreshing the token
                    if (webApiSettings.enableRefreshTokens() && tubularHttp.userData.refreshToken
                        && tubularHttp.isBearerTokenExpired()) {
                        return $q.reject({ error: 'expired token', status: 401, config: config });
                    }
                }

                return config;
            }

            function requestError(rejection) {
                return $q.reject(rejection);
            }

            function response(response) {
                return response;
            }

            function responseError(rejection) {
                var deferred = $q.defer();

                switch (rejection.status) {
                    case 401:
                        var tubularHttp = $injector.get(tubularHttpName);
                        var webApiSettings = tubularConfig.webApi;
                        var apiBaseUrl = webApiSettings.baseUrl();

                        if (
                            rejection.config.url.substring(0, apiBaseUrl.length) === apiBaseUrl &&
                            webApiSettings.tokenUrl() !== rejection.config.url &&
                            webApiSettings.enableRefreshTokens() &&
                            webApiSettings.requireAuthentication() &&
                            tubularHttp.userData.refreshToken) {

                            rejection.triedRefreshTokens = true;

                            if (!authRequestRunning) {
                                authRequestRunning = $injector.get('$http')({
                                    method: 'POST',
                                    url: webApiSettings.refreshTokenUrl(),
                                    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                                    data: 'grant_type=refresh_token&refresh_token=' + tubularHttp.userData.refreshToken
                                });
                            }

                            authRequestRunning.then(function (r) {
                                authRequestRunning = null;
                                tubularHttp.initAuth(r.data);

                                if (webApiSettings.requireAuthentication() && tubularHttp.isAuthenticated()) {
                                    rejection.config.headers.Authorization = 'Bearer ' + tubularHttp.userData.bearerToken;
                                    $injector.get('$http')(rejection.config).then(function (resp) {
                                        deferred.resolve(resp);
                                    }, function () {
                                        deferred.reject(r);
                                    });
                                }
                                else {
                                    deferred.reject(rejection);
                                }
                            }, function (response) {
                                authRequestRunning = null;
                                deferred.reject(response);
                                tubularHttp.removeAuthentication();
                                $injector.get('$state').go('/Login');
                                return;
                            });
                        }
                        else {
                            deferred.reject(rejection);
                        }

                        return deferred.promise;
                    default:
                        break;
                }

                deferred.reject(rejection);
                return deferred.promise;
            }
        }]);
})(angular);
<commit_msg>fixing eslint error<commit_after>(function (angular) {
    'use strict';
    /**
     * @ngdoc function
     * @name tubularAuthInterceptor
     * @description
     *
     * Implement a httpInterceptor to handle authorization using bearer tokens
     *
     * @constructor
     * @returns {Object} A httpInterceptor
     */
    angular.module('tubular.services')
        .factory('tubularAuthInterceptor', ['$q', '$injector', 'tubularConfig', function ($q, $injector, tubularConfig) {

            var authRequestRunning = null;
            var tubularHttpName = 'tubularHttp';

            var service = {
                request: request,
                requestError: requestError,
                response: response,
                responseError: responseError
            };

            return service;

            function request(config) {
                // Get the service here because otherwise, a circular dependency injection will be detected
                var tubularHttp = $injector.get(tubularHttpName);
                var webApiSettings = tubularConfig.webApi;

                config.headers = config.headers || {};

                // Handle requests going to API
                if (webApiSettings.tokenUrl() !== config.url &&
                    webApiSettings.requireAuthentication() &&
                    tubularHttp.userData.bearerToken) {

                    config.headers.Authorization = 'Bearer ' + tubularHttp.userData.bearerToken;

                    // When using refresh tokens and bearer token has expired,
                    // avoid the round trip on go directly to try refreshing the token
                    if (webApiSettings.enableRefreshTokens() && tubularHttp.userData.refreshToken
                        && tubularHttp.isBearerTokenExpired()) {
                        return $q.reject({ error: 'expired token', status: 401, config: config });
                    }
                }

                return config;
            }

            function requestError(rejection) {
                return $q.reject(rejection);
            }

            function response(response) {
                return response;
            }

            function responseError(rejection) {
                var deferred = $q.defer();

                switch (rejection.status) {
                    case 401:
                        var tubularHttp = $injector.get(tubularHttpName);
                        var webApiSettings = tubularConfig.webApi;
                        var apiBaseUrl = webApiSettings.baseUrl();

                        if (
                            rejection.config.url.substring(0, apiBaseUrl.length) === apiBaseUrl &&
                            webApiSettings.tokenUrl() !== rejection.config.url &&
                            webApiSettings.enableRefreshTokens() &&
                            webApiSettings.requireAuthentication() &&
                            tubularHttp.userData.refreshToken) {

                            rejection.triedRefreshTokens = true;

                            if (!authRequestRunning) {
                                authRequestRunning = $injector.get('$http')({
                                    method: 'POST',
                                    url: webApiSettings.refreshTokenUrl(),
                                    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                                    data: 'grant_type=refresh_token&refresh_token=' + tubularHttp.userData.refreshToken
                                });
                            }

                            authRequestRunning.then(function (r) {
                                authRequestRunning = null;
                                tubularHttp.initAuth(r.data);

                                if (webApiSettings.requireAuthentication() && tubularHttp.isAuthenticated()) {
                                    rejection.config.headers.Authorization = 'Bearer ' + tubularHttp.userData.bearerToken;
                                    $injector.get('$http')(rejection.config).then(function (resp) {
                                        deferred.resolve(resp);
                                    }, function () {
                                        deferred.reject(r);
                                    });
                                }
                                else {
                                    deferred.reject(rejection);
                                }
                            }, function (response) {
                                authRequestRunning = null;
                                deferred.reject(response);
                                tubularHttp.removeAuthentication();
                                $injector.get('$state').go('/Login');
                                return;
                            });
                        }
                        else {
                            deferred.reject(rejection);
                        }

                        return deferred.promise;
                    default:
                        break;
                }

                deferred.reject(rejection);
                return deferred.promise;
            }
        }]);
})(angular);
<|endoftext|>


<commit_before>const gulp = require('gulp');
const del = require('del');
const paths = require('vinyl-paths');
const rev = require('gulp-rev');
const through = require('through2');
const webpackStream = require('webpack-stream');
const webpack = require('webpack');
const { addToManifest } = require('./revision');

const gen = env => {
    process.env.NODE_ENV = env;
    return webpackStream(require('../webpack.config.web'), webpack).pipe(gulp.dest('www/js'));
};

const addRev = () =>
    gulp
        .src(['./www/js/{bot,index}*.js'])
        .pipe(rev())
        .pipe(through.obj(addToManifest))
        .pipe(gulp.dest('www/js'));

gulp.task(
    'clean-webpack',
    gulp.series(done => {
        del(['./www/js/*']).then(() => done());
    })
);

gulp.task(
    'webpack-gen-dev',
    gulp.series('clean-webpack', done => {
        gen('development');
        done();
    })
);

gulp.task(
    'webpack-gen-prod',
    gulp.series('clean-webpack', done => {
        gen('production');
        done();
    })
);

gulp.task(
    'webpack-dev',
    gulp.series('webpack-gen-dev', done => {
        addRev();
        done();
    })
);

gulp.task(
    'webpack-prod',
    gulp.series('webpack-gen-prod', done => {
        addRev();
        done();
    })
);
<commit_msg>Webpack asych task wait<commit_after>const gulp = require('gulp');
const del = require('del');
const paths = require('vinyl-paths');
const rev = require('gulp-rev');
const through = require('through2');
const webpackStream = require('webpack-stream');
const webpack = require('webpack');
const { addToManifest } = require('./revision');

const gen = env => {
    process.env.NODE_ENV = env;
    return webpackStream(require('../webpack.config.web'), webpack).pipe(gulp.dest('www/js'));
};

const addRev = () =>
    gulp
        .src(['./www/js/{bot,index}*.js'])
        .pipe(rev())
        .pipe(through.obj(addToManifest))
        .pipe(gulp.dest('www/js'));

gulp.task(
    'clean-webpack',
    gulp.series(done => {
        del(['./www/js/*']).then(() => done());
    })
);

gulp.task(
    'webpack-gen-dev',
    gulp.series('clean-webpack', done => {
        gen('development');
        done();
    })
);

gulp.task(
    'webpack-gen-prod',
    gulp.series('clean-webpack', done => {
        gen('production').on('end', () => done());
    })
);

gulp.task(
    'webpack-dev',
    gulp.series('webpack-gen-dev', done => {
        addRev();
        done();
    })
);

gulp.task(
    'webpack-prod',
    gulp.series('webpack-gen-prod', done => {
        addRev();
        done();
    })
);
<|endoftext|>


<commit_before>import { dest, parallel, series, src } from "gulp";

import autoprefixer from "gulp-autoprefixer";
import browserSync from "browser-sync";
import cssnano from "gulp-cssnano";
import envalid from "envalid";
import gulpif from "gulp-if";
import htmlmin from "gulp-htmlmin";
import merge2 from "merge2";
import plumber from "gulp-plumber";
import revAll from "gulp-rev-all";
import revDeleteOriginal from "gulp-rev-delete-original";
import sass from "gulp-sass";
import ssi from "gulp-ssi";
import uglify from "gulp-uglify";
import watch from "gulp-watch";

const environment = envalid.cleanEnv(process.env);
const browserSyncInstance = browserSync.create();

/**
 * Launch the Browsersync HTTP server while watching for file changes and refreshing the browser
 * or injecting assets on-the-fly.
 */
function initializeBrowserSync() {
    browserSyncInstance.init({
        files: "./dist/**/*",
        server: "./dist",
        online: false,
        open: false
    });
}

/**
 * Watch style related files for changes and pipe the modified ones into the build destination
 * folder, eventually notifying Browsersync of all changes causing a browser reload.
 */
function watchStylesTask() {
    return watch("./src/assets/sass/**/*.scss")
        .pipe(plumber())
        .pipe(sass().on("error", sass.logError))
        .pipe(plumber.stop())
        .pipe(dest("./dist/assets/css"))
        .pipe(browserSyncInstance.stream());
}

/**
 * Build style related files for either production or development. If building for production,
 * all CSS files will be minified and optimized.
 */
function buildStylesTask() {
    const cssnanoOptions = {
        autoprefixer: false
    };

    return src("./src/assets/sass/**/*.scss")
        .pipe(plumber())
        .pipe(sass().on("error", sass.logError))
        .pipe(plumber.stop())
        .pipe(gulpif(environment.isProduction, autoprefixer()))
        .pipe(gulpif(environment.isProduction, cssnano(cssnanoOptions)))
        .pipe(dest("./dist/assets/css"));
}

/**
 * Watch script related files for changes and pipe the modified ones into the build destination
 * folder, eventually notifying Browsersync of all changes causing a browser reload.
 */
function watchScriptsTask() {
    return watch("./src/assets/scripts/**/*.js")
        .pipe(dest("./dist/assets/scripts"))
        .pipe(browserSyncInstance.stream());
}

/**
 * Build script related files for either production or development. If building for production,
 * all JS filles will be uglified.
 */
function buildScriptsTask() {
    return src("./src/assets/scripts/**/*.js")
        .pipe(gulpif(environment.isProduction, uglify()))
        .pipe(dest("./dist/assets/scripts"));
}

/**
 * Watch template related files for changes and pipe the modified ones into the build destination
 * folder, eventually notifying Browsersync of all changes causing a browser reload.
 */
function watchTemplateTask() {
    return watch("./src/**/!(*.js|*.scss)")
        .pipe(dest("./dist"))
        .pipe(browserSyncInstance.stream());
}

/**
 * Build template related files for either production or development. If building for production,
 * all HTML will be minified and server-side includes will be parsed.
 */
function buildTemplateTask() {
    const ssiOptions = {
        root: "./"
    };

    return merge2(
        src("./src/index.html")
            .pipe(gulpif(environment.isProduction, ssi(ssiOptions)))
            .pipe(
                gulpif(
                    environment.isProduction,
                    htmlmin({
                        collapseBooleanAttributes: true,
                        collapseWhitespace: true,
                        minifyCSS: true,
                        minifyJS: true,
                        removeComments: true,
                        removeEmptyAttributes: true,
                        removeOptionalTags: true,
                        removeRedundantAttributes: true
                    })
                )
            ),
        src("./src/**/!(*.html|*.js|*.scss)", { nodir: true })
    ).pipe(dest("./dist"));
}

/**
 * Perform static asset revisioning - with dependency considerations - by appending content hash to
 * filenames (eg. unicorn.css => unicorn.098f6bcd.css).
 */
function revStaticAssetsTask() {
    const revAllOptions = {
        dontGlobal: [/^\/favicon.ico$/g],
        dontRenameFile: ["index.html", "keybase.txt", "open-graph-preview.png"]
    };

    return src("./dist/**/*")
        .pipe(revAll.revision(revAllOptions))
        .pipe(revDeleteOriginal())
        .pipe(dest("./dist"));
}

/**
 * Compile source files and launch a Browsersync development server. Changes made will either be
 * injected into the page or will cause all browsers to do a full-page refresh.
 *
 * @export `development` task.
 */
export const development = series(
    parallel(buildStylesTask, buildScriptsTask, buildTemplateTask),
    parallel(
        watchStylesTask,
        watchScriptsTask,
        watchTemplateTask,
        initializeBrowserSync
    )
);

/**
 * Compile source files ready for deployment to GitHub pages.
 *
 * @export `production` task.
 */
export const production = series(
    parallel(buildStylesTask, buildScriptsTask, buildTemplateTask),
    revStaticAssetsTask
);
<commit_msg>Restore single quotes removed by mistake<commit_after>import { dest, parallel, series, src } from 'gulp';

import autoprefixer from 'gulp-autoprefixer';
import browserSync from 'browser-sync';
import cssnano from 'gulp-cssnano';
import envalid from 'envalid';
import gulpif from 'gulp-if';
import htmlmin from 'gulp-htmlmin';
import merge2 from 'merge2';
import plumber from 'gulp-plumber';
import revAll from 'gulp-rev-all';
import revDeleteOriginal from 'gulp-rev-delete-original';
import sass from 'gulp-sass';
import ssi from 'gulp-ssi';
import uglify from 'gulp-uglify';
import watch from 'gulp-watch';

const environment = envalid.cleanEnv(process.env);
const browserSyncInstance = browserSync.create();

/**
 * Launch the Browsersync HTTP server while watching for file changes and refreshing the browser
 * or injecting assets on-the-fly.
 */
function initializeBrowserSync() {
    browserSyncInstance.init({
        files: './dist/**/*',
        server: './dist',
        online: false,
        open: false
    });
}

/**
 * Watch style related files for changes and pipe the modified ones into the build destination
 * folder, eventually notifying Browsersync of all changes causing a browser reload.
 */
function watchStylesTask() {
    return watch('./src/assets/sass/**/*.scss')
        .pipe(plumber())
        .pipe(sass().on('error', sass.logError))
        .pipe(plumber.stop())
        .pipe(dest('./dist/assets/css'))
        .pipe(browserSyncInstance.stream());
}

/**
 * Build style related files for either production or development. If building for production,
 * all CSS files will be minified and optimized.
 */
function buildStylesTask() {
    const cssnanoOptions = {
        autoprefixer: false
    };

    return src('./src/assets/sass/**/*.scss')
        .pipe(plumber())
        .pipe(sass().on('error', sass.logError))
        .pipe(plumber.stop())
        .pipe(gulpif(environment.isProduction, autoprefixer()))
        .pipe(gulpif(environment.isProduction, cssnano(cssnanoOptions)))
        .pipe(dest('./dist/assets/css'));
}

/**
 * Watch script related files for changes and pipe the modified ones into the build destination
 * folder, eventually notifying Browsersync of all changes causing a browser reload.
 */
function watchScriptsTask() {
    return watch('./src/assets/scripts/**/*.js')
        .pipe(dest('./dist/assets/scripts'))
        .pipe(browserSyncInstance.stream());
}

/**
 * Build script related files for either production or development. If building for production,
 * all JS filles will be uglified.
 */
function buildScriptsTask() {
    return src('./src/assets/scripts/**/*.js')
        .pipe(gulpif(environment.isProduction, uglify()))
        .pipe(dest('./dist/assets/scripts'));
}

/**
 * Watch template related files for changes and pipe the modified ones into the build destination
 * folder, eventually notifying Browsersync of all changes causing a browser reload.
 */
function watchTemplateTask() {
    return watch('./src/**/!(*.js|*.scss)')
        .pipe(dest('./dist'))
        .pipe(browserSyncInstance.stream());
}

/**
 * Build template related files for either production or development. If building for production,
 * all HTML will be minified and server-side includes will be parsed.
 */
function buildTemplateTask() {
    const ssiOptions = {
        root: './'
    };

    return merge2(
        src('./src/index.html')
            .pipe(gulpif(environment.isProduction, ssi(ssiOptions)))
            .pipe(
                gulpif(
                    environment.isProduction,
                    htmlmin({
                        collapseBooleanAttributes: true,
                        collapseWhitespace: true,
                        minifyCSS: true,
                        minifyJS: true,
                        removeComments: true,
                        removeEmptyAttributes: true,
                        removeOptionalTags: true,
                        removeRedundantAttributes: true
                    })
                )
            ),
        src('./src/**/!(*.html|*.js|*.scss)', { nodir: true })
    ).pipe(dest('./dist'));
}

/**
 * Perform static asset revisioning - with dependency considerations - by appending content hash to
 * filenames (eg. unicorn.css => unicorn.098f6bcd.css).
 */
function revStaticAssetsTask() {
    const revAllOptions = {
        dontGlobal: [/^\/favicon.ico$/g],
        dontRenameFile: ['index.html', 'keybase.txt', 'open-graph-preview.png']
    };

    return src('./dist/**/*')
        .pipe(revAll.revision(revAllOptions))
        .pipe(revDeleteOriginal())
        .pipe(dest('./dist'));
}

/**
 * Compile source files and launch a Browsersync development server. Changes made will either be
 * injected into the page or will cause all browsers to do a full-page refresh.
 *
 * @export `development` task.
 */
export const development = series(
    parallel(buildStylesTask, buildScriptsTask, buildTemplateTask),
    parallel(
        watchStylesTask,
        watchScriptsTask,
        watchTemplateTask,
        initializeBrowserSync
    )
);

/**
 * Compile source files ready for deployment to GitHub pages.
 *
 * @export `production` task.
 */
export const production = series(
    parallel(buildStylesTask, buildScriptsTask, buildTemplateTask),
    revStaticAssetsTask
);
<|endoftext|>


<commit_before>const express    = require('express');
const bodyParser = require('body-parser');
const exphbs     = require('express-handlebars');

module.exports = function() {
  console.log('init express...');
  let app = express();

  app.use(express.static('public'));
  app.use(bodyParser());
  app.engine('handlebars', exphbs({defaultLayout: 'main'})); //设置模板页名称main
  app.set('view engine', 'handlebars');

  //加载路由...
  require('../app/routes/daily.server.route')(app);

  //处理404
  app.use(function(req, res, next) {
  try {
    res.status(404).send('404 - 未找到');
  } catch(e) {
    console.error('404 set header agter sent');
  }
  });

  //处理500
  app.use(function(err, req, res, next) {
  console.log('检查到未处理的错误：' + err.message);
  res.status(500).send('500 - 服务器错误');
})

  return app;
}

<commit_msg>修复bodyParser的警告<commit_after>const express    = require('express');
const bodyParser = require('body-parser');
const exphbs     = require('express-handlebars');

module.exports = function() {
  console.log('init express...');
  let app = express();

  app.use(express.static('public'));
  app.use(bodyParser.urlencoded({extended: true}));
  app.use(bodyParser.json());
  app.engine('handlebars', exphbs({defaultLayout: 'main'})); //设置模板页名称main
  app.set('view engine', 'handlebars');

  //加载路由...
  require('../app/routes/daily.server.route')(app);

  //处理404
  app.use(function(req, res, next) {
  try {
    res.status(404).send('404 - 未找到');
  } catch(e) {
    console.error('404 set header agter sent');
  }
  });

  //处理500
  app.use(function(err, req, res, next) {
  console.log('检查到未处理的错误：' + err.message);
  res.status(500).send('500 - 服务器错误');
})

  return app;
}

<|endoftext|>


<commit_before>
/*
 * Copyright 2017 Banco Bilbao Vizcaya Argentaria, S.A.
 *
 * 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.
 */

var Service = (function() {
  'use strict';

  function Service(serviceType, dashboardId) {
    var url = serviceType.getUrl(dashboardId);
    var timer = serviceType.timer;

    var event = new Event(this);
    var pending = false;

    var attempt = 1;
    var breakTimeout;

    function callHttpService() {
      if (pending) {
        return;
      }
      pending = true;
      httpGetAsync(url, function(err, data) {

        if(err) {
          if(window.Service.reattempt) {
            if(breakTimeout) {
              clearTimeout(breakTimeout);
            }
            breakTimeout = setTimeout(function() {
              attempt++;
              breakTimeout = undefined;
              callHttpService();
            }, Math.min(32000, Math.pow(2, attempt) * 1000));
          }
        } else {
          attempt = 1;
        }

        pending = false;
        event.notify(data);
      });
    }

    function processServerEvent(serverEventType){
      var serverSentEventtype=JSON.parse(serverEventType);
      if(serverSentEventtype.type === serviceType.serverEventType){
        callHttpService();
      }
    }

    this.addListener = function(callback) {
      event.attach(callback);
      this._checkEventRegistration();
      this.request();
    };

    this.removeListener = function(callback) {
      event.detach(callback);
      this._checkEventRegistration();
    };

    this.request = function() { callHttpService(); };

    this._checkEventRegistration = function() {
      if (event.getListeners().length && !this._attached) {
        this._attached = true;
        if(serviceType.serverEventType){
          ServerSentEvent.addListener(processServerEvent);
        }
        timer && timer.attach(callHttpService);
      } else if (!event.getListeners().length && this._attached) {
        this._attached = false;
        if(serviceType.serverEventType){
          ServerSentEvent.removeListener(processServerEvent);
        }
        timer && timer.detach(callHttpService);
      }
    };

    this.dispose = function() {
      event.reset();
      this._checkEventRegistration();
    };
  }

  function ServiceType(timer, resource, serverEventType) {
    this._instances = {};
    this.timer = timer;
    this.serverEventType = serverEventType;
    this.getUrl = function(dashboardId) {
      var url = 'dashboards/';
      if (dashboardId) {
        url += dashboardId + '/';
        if (resource) {
          url += resource;
        }
      }
      return url;
    };
  }

  function NoTimerServiceType(resource, serverEventType) {
    this._instances = {};
    this.serverEventType = serverEventType;
    this.getUrl = function(dashboardId) {
      var url = 'dashboards/';
      if (dashboardId) {
        url += dashboardId + '/';
        if (resource) {
          url += resource;
        }
      }
      return url;
    };
  }

  var self = {
    types: {
      builds: new ServiceType(Timer.eventually, 'builds','BuildType'),
      bugs: new ServiceType(Timer.eventually, 'bugs'),
      stories: new ServiceType(Timer.rarely, 'stories', 'FeatureType'),
      apps: new ServiceType(Timer.rarely, 'applications', 'ReviewType'),
      dashboard: new ServiceType(Timer.never, 'details', 'DashboardType'),
      dashboards: new ServiceType(Timer.never),
      programincrement: new ServiceType(Timer.eventually, 'programincrement', 'FeatureType'),
      notifications: new ServiceType(Timer.never, 'notifications'),
      userMetrics: new ServiceType(Timer.eventually, 'user-metrics'),
      scmMetrics: new ServiceType(Timer.eventually, 'scm-metrics'),
      eventNotifications: new NoTimerServiceType('event-notification', 'NotificationType'),
    },
    get: function(type, dashboardId) {
      return (
          type._instances[dashboardId] =
              type._instances[dashboardId] || new Service(type, dashboardId));
    },
    reset: function() {
      for (var type in self.types) {
        var item = self.types[type];
        for (var board in item._instances) {
          item._instances[board].dispose();
        }
        item._instances = {};
      }
    },
    reattempt: true
  };

  return self;

})();
<commit_msg>fix(dashboard): resolve jshint problems<commit_after>
/*
 * Copyright 2017 Banco Bilbao Vizcaya Argentaria, S.A.
 *
 * 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.
 */

var Service = (function() {
  'use strict';

  function Service(serviceType, dashboardId) {
    var url = serviceType.getUrl(dashboardId);
    var timer = serviceType.timer;

    var event = new Event(this);
    var pending = false;

    var attempt = 1;
    var breakTimeout;

    function callHttpService() {
      if (pending) {
        return;
      }
      pending = true;
      httpGetAsync(url, function(err, data) {

        if(err) {
          if(window.Service.reattempt) {
            if(breakTimeout) {
              clearTimeout(breakTimeout);
            }
            breakTimeout = setTimeout(function() {
              attempt++;
              breakTimeout = undefined;
              callHttpService();
            }, Math.min(32000, Math.pow(2, attempt) * 1000));
          }
        } else {
          attempt = 1;
        }

        pending = false;
        event.notify(data);
      });
    }

    function processServerEvent(serverEventType){
      var serverSentEventtype=JSON.parse(serverEventType);
      if(serverSentEventtype.type === serviceType.serverEventType){
        callHttpService();
      }
    }

    this.addListener = function(callback) {
      event.attach(callback);
      this._checkEventRegistration();
      this.request();
    };

    this.removeListener = function(callback) {
      event.detach(callback);
      this._checkEventRegistration();
    };

    this.request = function() { callHttpService(); };

    this._checkEventRegistration = function() {
      if (event.getListeners().length && !this._attached) {
        this._attached = true;
        if(serviceType.serverEventType){
          ServerSentEvent.addListener(processServerEvent);
        }
        if(timer) {
          timer.attach(callHttpService);
        }
      } else if (!event.getListeners().length && this._attached) {
        this._attached = false;
        if(serviceType.serverEventType){
          ServerSentEvent.removeListener(processServerEvent);
        }
        if(timer) {
          timer.detach(callHttpService);
        }
      }
    };

    this.dispose = function() {
      event.reset();
      this._checkEventRegistration();
    };
  }

  function ServiceType(timer, resource, serverEventType) {
    this._instances = {};
    this.timer = timer;
    this.serverEventType = serverEventType;
    this.getUrl = function(dashboardId) {
      var url = 'dashboards/';
      if (dashboardId) {
        url += dashboardId + '/';
        if (resource) {
          url += resource;
        }
      }
      return url;
    };
  }

  function NoTimerServiceType(resource, serverEventType) {
    this._instances = {};
    this.serverEventType = serverEventType;
    this.getUrl = function(dashboardId) {
      var url = 'dashboards/';
      if (dashboardId) {
        url += dashboardId + '/';
        if (resource) {
          url += resource;
        }
      }
      return url;
    };
  }

  var self = {
    types: {
      builds: new ServiceType(Timer.eventually, 'builds','BuildType'),
      bugs: new ServiceType(Timer.eventually, 'bugs'),
      stories: new ServiceType(Timer.rarely, 'stories', 'FeatureType'),
      apps: new ServiceType(Timer.rarely, 'applications', 'ReviewType'),
      dashboard: new ServiceType(Timer.never, 'details', 'DashboardType'),
      dashboards: new ServiceType(Timer.never),
      programincrement: new ServiceType(Timer.eventually, 'programincrement', 'FeatureType'),
      notifications: new ServiceType(Timer.never, 'notifications'),
      userMetrics: new ServiceType(Timer.eventually, 'user-metrics'),
      scmMetrics: new ServiceType(Timer.eventually, 'scm-metrics'),
      eventNotifications: new NoTimerServiceType('event-notification', 'NotificationType'),
    },
    get: function(type, dashboardId) {
      return (
          type._instances[dashboardId] =
              type._instances[dashboardId] || new Service(type, dashboardId));
    },
    reset: function() {
      for (var type in self.types) {
        var item = self.types[type];
        for (var board in item._instances) {
          item._instances[board].dispose();
        }
        item._instances = {};
      }
    },
    reattempt: true
  };

  return self;

})();
<|endoftext|>


<commit_before>function lgksAlert(msg,title,callback) {
	return bootbox.alert(msg, callback);
}
function lgksPrompt(msg,title,callback) {
	return bootbox.prompt(msg, callback);
}
function lgksConfirm(msg,title,callback) {
	return bootbox.confirm(msg, callback);
}
function lgksLoader(msg,title) {
  if(title==null) title = "Loading ...";

  if($(".loadingmodal").length>0) {
    $(".loadingmodal").modal("hide");
  }
  a = lgksMsg("

"+msg+"

",title, {
    onEscape: false,
    className: "loadingmodal"
  });
  $(".loadingmodal .bootbox-close-button,.loadingmodal .close").detach();

  return a;
}
function lgksLoaderHide() {
  $(".loadingmodal").modal("hide");
}

function lgksOverlay(msg, title, paramsXtra) {
	params={
		className: "overlayBox",
		size: "large",
	};
	params=$.extend(params,paramsXtra);
	lgksMsg(msg, title, params);
}
function lgksOverlayDiv(divID,title, paramsXtra) {
	if(title==null) title=$(divID).attr('title');
	msg=$(divID).html();

	params={
		className: "overlayBox",
		size: "large",
	};
	params=$.extend(params,paramsXtra);
	lgksMsg(msg, title, params);
}

function lgksOverlayFrame(url, title, paramsXtra) {
	msg="";
	params={
		className: "overlayBox",
		size: "large",
	};
	params=$.extend(params,paramsXtra);
	lgksMsg(msg, title, params);
}

function lgksOverlayURL(url, title, callBackFunc, paramsXtra) {
	processAJAXQuery(url,function(txt) {
		params={
			className: "overlayBox",
			size: "large",
		};
		params=$.extend(params,paramsXtra);
		lgksMsg(txt, title, params);
		callBackFunc();
	},"TEXT");
}

function lgksMsg(msg,title,paramsXtra) {
	params={
	  /**
	   * @required String|Element
	   */
	  message: "I am a custom dialog",

	  /**
	   * @optional String|Element
	   * adds a header to the dialog and places this text in an h4
	   */
	  title: "Custom title",

	  /**
	   * @optional Function
	   * allows the user to dismisss the dialog by hitting ESC, which
	   * will invoke this function
	   */
	  onEscape: function() {},

	  /**
	   * @optional Boolean
	   * @default: true
	   * whether the dialog should be shown immediately
	   */
	  show: true,

	  /**
	   * @optional Boolean
	   * @default: true
	   * whether the dialog should be have a backdrop or not
	   */
	  backdrop: true,

	  /**
	   * @optional Boolean
	   * @default: true
	   * show a close button
	   */
	  closeButton: true,

	  /**
	   * @optional Boolean
	   * @default: true
	   * animate the dialog in and out (not supported in < IE 10)
	   */
	  animate: true,

	  /**
	   * @optional String
	   * @default: null
	   * an additional class to apply to the dialog wrapper
	   */
	  className: "my-modal",

	  /**
	   * @optional Object
	   * @default: {}
	   * any buttons shown in the dialog's footer
	   */
	  buttons: {
	  }
	};
	params.title=title;
	params.message=msg;

	params=$.extend(params,paramsXtra);

	bootbox.dialog(params);
}<commit_msg>Updated lgksLoader<commit_after>function lgksAlert(msg,title,callback) {
	return bootbox.alert(msg, callback);
}
function lgksPrompt(msg,title,callback) {
	return bootbox.prompt(msg, callback);
}
function lgksConfirm(msg,title,callback) {
	return bootbox.confirm(msg, callback);
}
function lgksLoader(msg,title) {
  if(title==null) title = "";

  if($(".loadingmodal").length>0) {
    $(".loadingmodal").modal("hide");
  }
  a = lgksMsg("

"+msg+"

",title, {
    onEscape: false,
    className: "loadingmodal"
  });
  $(".loadingmodal .bootbox-close-button,.loadingmodal .close").detach();

  return a;
}
function lgksLoaderHide() {
  $(".loadingmodal").modal("hide");
}

function lgksOverlay(msg, title, paramsXtra) {
	params={
		className: "overlayBox",
		size: "large",
	};
	params=$.extend(params,paramsXtra);
	lgksMsg(msg, title, params);
}
function lgksOverlayDiv(divID,title, paramsXtra) {
	if(title==null) title=$(divID).attr('title');
	msg=$(divID).html();

	params={
		className: "overlayBox",
		size: "large",
	};
	params=$.extend(params,paramsXtra);
	lgksMsg(msg, title, params);
}

function lgksOverlayFrame(url, title, paramsXtra) {
	msg="";
	params={
		className: "overlayBox",
		size: "large",
	};
	params=$.extend(params,paramsXtra);
	lgksMsg(msg, title, params);
}

function lgksOverlayURL(url, title, callBackFunc, paramsXtra) {
	processAJAXQuery(url,function(txt) {
		params={
			className: "overlayBox",
			size: "large",
		};
		params=$.extend(params,paramsXtra);
		lgksMsg(txt, title, params);
		callBackFunc();
	},"TEXT");
}

function lgksMsg(msg,title,paramsXtra) {
	params={
	  /**
	   * @required String|Element
	   */
	  message: "I am a custom dialog",

	  /**
	   * @optional String|Element
	   * adds a header to the dialog and places this text in an h4
	   */
	  title: "Custom title",

	  /**
	   * @optional Function
	   * allows the user to dismisss the dialog by hitting ESC, which
	   * will invoke this function
	   */
	  onEscape: function() {},

	  /**
	   * @optional Boolean
	   * @default: true
	   * whether the dialog should be shown immediately
	   */
	  show: true,

	  /**
	   * @optional Boolean
	   * @default: true
	   * whether the dialog should be have a backdrop or not
	   */
	  backdrop: true,

	  /**
	   * @optional Boolean
	   * @default: true
	   * show a close button
	   */
	  closeButton: true,

	  /**
	   * @optional Boolean
	   * @default: true
	   * animate the dialog in and out (not supported in < IE 10)
	   */
	  animate: true,

	  /**
	   * @optional String
	   * @default: null
	   * an additional class to apply to the dialog wrapper
	   */
	  className: "my-modal",

	  /**
	   * @optional Object
	   * @default: {}
	   * any buttons shown in the dialog's footer
	   */
	  buttons: {
	  }
	};
	params.title=title;
	params.message=msg;

	params=$.extend(params,paramsXtra);

	bootbox.dialog(params);
}<|endoftext|>


<commit_before>export const BLACK = 0x000000;
export const GRAY = 0x999999;
export const WHITE = 0xffffff;

export const GRAY_LIGHT = 0xbfbfbf;
export const GRAY_LIGHTER = 0xd9d9d9;
export const GRAY_LIGHTEST = 0xe5e5e5;
export const GRAY_DARK = 0x666666;
export const GRAY_DARKER = 0x444444;
export const GRAY_DARKEST = 0x222222;

export const CYAN = 0x3ae0e5;
export const GREEN = 0x40bf00;
export const ORANGE = 0xff5500;
export const PINK = 0xec3bb6;
export const RED = 0xf60029;
export const YELLOW = 0xffcc00;
export const BLUE = 0x4e40ff;

export const PRIMARY = ORANGE;
export const SECONDARY = BLUE;

export const LOW_QUALITY_BLUE = 0xdcd9ff;
export const LOW_QUALITY_BLUE_ARR = [0.862745098, 0.850980392, 1];
export const LOW_QUALITY_BLUE_RGBA = [220, 217, 255, 255];
export const LOW_QUALITY_ORANGE = 0xffd9cb;
export const LOW_QUALITY_ORANGE_ARR = [1, 0.890196078, 0.835294118];
export const LOW_QUALITY_ORANGE_RGBA = [255, 227, 213, 255];

export default {
  BLACK,
  GRAY,
  WHITE,
  GRAY_LIGHT,
  GRAY_LIGHTER,
  GRAY_LIGHTEST,
  GRAY_DARK,
  GRAY_DARKER,
  GRAY_DARKEST,
  CYAN,
  GREEN,
  ORANGE,
  PINK,
  RED,
  YELLOW,
  BLUE,
  PRIMARY,
  SECONDARY,
  LOW_QUALITY_BLUE,
  LOW_QUALITY_BLUE_ARR,
  LOW_QUALITY_BLUE_RGBA,
  LOW_QUALITY_ORANGE,
  LOW_QUALITY_ORANGE_ARR,
  LOW_QUALITY_ORANGE_RGBA
};
<commit_msg>Add RGBA colors<commit_after>export const BLACK = 0x000000;
export const GRAY = 0x999999;
export const WHITE = 0xffffff;

export const GRAY_LIGHT = 0xbfbfbf;
export const GRAY_LIGHTER = 0xd9d9d9;
export const GRAY_LIGHTEST = 0xe5e5e5;
export const GRAY_DARK = 0x666666;
export const GRAY_DARKER = 0x444444;
export const GRAY_DARKEST = 0x222222;

export const CYAN = 0x3ae0e5;
export const CYAN_RGBA = [58, 224, 229, 255];
export const GREEN = 0x40bf00;
export const GREEN_RGBA = [64, 191, 0, 255];
export const ORANGE = 0xff5500;
export const ORANGE_RGBA = [255, 85, 0, 255];
export const PINK = 0xec3bb6;
export const PINK_RGBA = [236, 59, 182, 255];
export const RED = 0xf60029;
export const RED_RGBA = [246, 0, 41, 255];
export const YELLOW = 0xffcc00;
export const YELLOW_RGBA = [255, 204, 0, 255];
export const BLUE = 0x4e40ff;
export const BLUE_RGBA = [78, 64, 255, 255];

export const PRIMARY = ORANGE;
export const SECONDARY = BLUE;

export const LOW_QUALITY_BLUE = 0xdcd9ff;
export const LOW_QUALITY_BLUE_ARR = [0.862745098, 0.850980392, 1];
export const LOW_QUALITY_BLUE_RGBA = [220, 217, 255, 255];
export const LOW_QUALITY_ORANGE = 0xffd9cb;
export const LOW_QUALITY_ORANGE_ARR = [1, 0.890196078, 0.835294118];
export const LOW_QUALITY_ORANGE_RGBA = [255, 227, 213, 255];

export default {
  BLACK,
  GRAY,
  WHITE,
  GRAY_LIGHT,
  GRAY_LIGHTER,
  GRAY_LIGHTEST,
  GRAY_DARK,
  GRAY_DARKER,
  GRAY_DARKEST,
  CYAN,
  CYAN_RGBA,
  GREEN,
  GREEN_RGBA,
  ORANGE,
  ORANGE_RGBA,
  PINK,
  PINK_RGBA,
  RED,
  RED_RGBA,
  YELLOW,
  YELLOW_RGBA,
  BLUE,
  BLUE_RGBA,
  PRIMARY,
  SECONDARY,
  LOW_QUALITY_BLUE,
  LOW_QUALITY_BLUE_ARR,
  LOW_QUALITY_BLUE_RGBA,
  LOW_QUALITY_ORANGE,
  LOW_QUALITY_ORANGE_ARR,
  LOW_QUALITY_ORANGE_RGBA
};
<|endoftext|>


<commit_before>/**
 * Each section of the site has its own module. It probably also has
 * submodules, though this boilerplate is too simple to demonstrate it. Within
 * `src/app/home`, however, could exist several additional folders representing
 * additional modules that would then be listed as dependencies of this one.
 * For example, a `note` section could have the submodules `note.create`,
 * `note.delete`, `note.edit`, etc.
 *
 * Regardless, so long as dependencies are managed correctly, the build process
 * will automatically take take of the rest.
 *
 * The dependencies block here is also where component dependencies should be
 * specified, as shown below.
 */
angular.module( 'app.home', [
  'ui.router',
  'plusOne',
  'firebase'
])

/**
 * Each section or module of the site can also have its own routes. AngularJS
 * will handle ensuring they are all available at run-time, but splitting it
 * this way makes each module more "self-contained".
 */
.config(function config( $stateProvider ) {
  $stateProvider.state( 'home', {
    url: '/home',
    views: {
      "main": {
        controller: 'HomeCtrl',
        templateUrl: 'home/home.tpl.html'
      }
    },
    data:{ pageTitle: 'Home' }
  });
})

/**
 * And of course we define a controller for our route.
 */
.controller( 'HomeCtrl', function HomeController( $scope, $firebase ) {
  var ref = new Firebase("https://languagehuntgamehub.firebaseio.com");
  // create an AngularFire reference to the data
  var sync = $firebase(ref);

  var syncObject = sync.$asObject();

  syncObject.$bindTo($scope, "game");

  $scope.audio_path = function (path, filename) { return path + filename; }
})

;

<commit_msg>Fix syntax error<commit_after>/**
 * Each section of the site has its own module. It probably also has
 * submodules, though this boilerplate is too simple to demonstrate it. Within
 * `src/app/home`, however, could exist several additional folders representing
 * additional modules that would then be listed as dependencies of this one.
 * For example, a `note` section could have the submodules `note.create`,
 * `note.delete`, `note.edit`, etc.
 *
 * Regardless, so long as dependencies are managed correctly, the build process
 * will automatically take take of the rest.
 *
 * The dependencies block here is also where component dependencies should be
 * specified, as shown below.
 */
angular.module( 'app.home', [
  'ui.router',
  'plusOne',
  'firebase'
])

/**
 * Each section or module of the site can also have its own routes. AngularJS
 * will handle ensuring they are all available at run-time, but splitting it
 * this way makes each module more "self-contained".
 */
.config(function config( $stateProvider ) {
  $stateProvider.state( 'home', {
    url: '/home',
    views: {
      "main": {
        controller: 'HomeCtrl',
        templateUrl: 'home/home.tpl.html'
      }
    },
    data:{ pageTitle: 'Home' }
  });
})

/**
 * And of course we define a controller for our route.
 */
.controller( 'HomeCtrl', function HomeController( $scope, $firebase ) {
  var ref = new Firebase("https://languagehuntgamehub.firebaseio.com");
  // create an AngularFire reference to the data
  var sync = $firebase(ref);

  var syncObject = sync.$asObject();

  syncObject.$bindTo($scope, "game");

  $scope.audio_path = function (path, filename) { return path + filename; };
})

;

<|endoftext|>


<commit_before>var schedule = [
{
  date: "12/1",
  author: "ymyzk",
  author_url: "http://www.ymyzk.com",
  entry_title: "CAMPHOR- アドベントカレンダー 2014 を始めます!",
  entry_url: "http://blog.camph.net/news/advent-calendar-2014/"
},
{
  date: "12/2",
  author: "ohmuraken",
  author_url: "https://github.com/ohmuraken",
  entry_title: "彼女のつくりかた (京大11月祭にて)",
  entry_url: "http://blog.camph.net/news/howtomakemygirlfriend2/"
},
{
  date: "12/3",
  author: "morishin",
  author_url: "https://twitter.com/morishin127",
  entry_title: "CAMPHOR-のYo活用",
  entry_url: "http://blog.camph.net/news/useful-yo/"
},
{
  date: "12/4",
  author: "kohey18",
  author_url: "https://github.com/kohey18",
  entry_title: "「hubot start tv」で家のテレビの電源を付ける。",
  entry_url: "http://tech.camph.net/hubot_start_tv/"
},
{
  date: "12/5",
  author: "Shtr28",
  author_url: "https://twitter.com/Shtr28",
  entry_title: "Python 3でお手軽並列計算 ~concurrent.futures を使った ngram 抽出~",
  entry_url: "http://tech.camph.net/python3-concurrent-futures/"
},
{
  date: "12/6",
  author: "yaitaimo",
  author_url: "https://github.com/yaitaimo",
  entry_title: "CAMPHOR-HOUSEの庭を美白した話",
  entry_url: "http://blog.camph.net/news/camphor-house-garden/"
},
{
  date: "12/7",
  author: "tomonkey1",
  author_url: "https://github.com/tomonkey1",
  entry_title: "宅建挑戦記",
  entry_url: "http://blog.camph.net/event/takken/"
},
{
  date: "12/8",
  author: "asadaman",
  author_url: "#",
  entry_title: "ロボットに負けたくない",
  entry_url: "#"
},
{
  date: "12/9",
  author: "akaaariiiiin",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
},
{
  date: "12/10",
  author: "To-Mikasa",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
},
{
  date: "12/11",
  author: "ryota-ka",
  author_url: "http://ryota-ka.me/",
  entry_title: "iOS 初心者が Swift を使ってN日でゲームを作った話",
  entry_url: "#"
},
{
  date: "12/12",
  author: "siriusjack",
  author_url: "#",
  entry_title: "食べられるドングリの見分け方(ドイツ編)",
  entry_url: "#"
},
{
  date: "12/13",
  author: "ivstivs",
  author_url: "https://github.com/ivstivs",
  entry_title: "ProjectileとHelm",
  entry_url: "#"
},
{
  date: "12/14",
  author: "kakenn",
  author_url: "http://shuto.info",
  entry_title: "格安3Dプリンター「daVinci 2.0」を買ってみた。",
  entry_url: "#"
},
{
  date: "12/15",
  author: "ymyzk",
  author_url: "http://www.ymyzk.com",
  entry_title: "sphinxcontrib.httpdomain で RESTful API のドキュメント作成",
  entry_url: "#"
},
{
  date: "12/16",
  author: "cotton_ori",
  author_url: "https://twitter.com/cotton_ori",
  entry_title: "準備中",
  entry_url: "#"
},
{
  date: "12/17",
  author: "pepoipod",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
},
{
  date: "12/18",
  author: "ohmuraken",
  author_url: "#",
  entry_title: "ソーシャルボタンで文字を作る！",
  entry_url: "#"
},
{
  date: "12/19",
  author: "準備中",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
},
{
  date: "12/20",
  author: "準備中",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
},
{
  date: "12/21",
  author: "morishin",
  author_url: "https://twitter.com/morishin127",
  entry_title: "準備中",
  entry_url: "#"
}
,
{
  date: "12/22",
  author: "準備中",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
}
,
{
  date: "12/23",
  author: "準備中",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
}
,
{
  date: "12/24",
  author: "準備中",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
}
,
{
  date: "12/25",
  author: "準備中",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
}
];
<commit_msg>Update 2014/12/8<commit_after>var schedule = [
{
  date: "12/1",
  author: "ymyzk",
  author_url: "http://www.ymyzk.com",
  entry_title: "CAMPHOR- アドベントカレンダー 2014 を始めます!",
  entry_url: "http://blog.camph.net/news/advent-calendar-2014/"
},
{
  date: "12/2",
  author: "ohmuraken",
  author_url: "https://github.com/ohmuraken",
  entry_title: "彼女のつくりかた (京大11月祭にて)",
  entry_url: "http://blog.camph.net/news/howtomakemygirlfriend2/"
},
{
  date: "12/3",
  author: "morishin",
  author_url: "https://twitter.com/morishin127",
  entry_title: "CAMPHOR-のYo活用",
  entry_url: "http://blog.camph.net/news/useful-yo/"
},
{
  date: "12/4",
  author: "kohey18",
  author_url: "https://github.com/kohey18",
  entry_title: "「hubot start tv」で家のテレビの電源を付ける。",
  entry_url: "http://tech.camph.net/hubot_start_tv/"
},
{
  date: "12/5",
  author: "Shtr28",
  author_url: "https://twitter.com/Shtr28",
  entry_title: "Python 3でお手軽並列計算 ~concurrent.futures を使った ngram 抽出~",
  entry_url: "http://tech.camph.net/python3-concurrent-futures/"
},
{
  date: "12/6",
  author: "yaitaimo",
  author_url: "https://github.com/yaitaimo",
  entry_title: "CAMPHOR-HOUSEの庭を美白した話",
  entry_url: "http://blog.camph.net/news/camphor-house-garden/"
},
{
  date: "12/7",
  author: "tomonkey1",
  author_url: "https://github.com/tomonkey1",
  entry_title: "宅建挑戦記",
  entry_url: "http://blog.camph.net/event/takken/"
},
{
  date: "12/8",
  author: "asadaman",
  author_url: "https://github.com/asadaman",
  entry_title: "ロボットに負けたくない",
  entry_url: "http://blog.camph.net/news/robo/"
},
{
  date: "12/9",
  author: "akaaariiiiin",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
},
{
  date: "12/10",
  author: "To-Mikasa",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
},
{
  date: "12/11",
  author: "ryota-ka",
  author_url: "http://ryota-ka.me/",
  entry_title: "iOS 初心者が Swift を使ってN日でゲームを作った話",
  entry_url: "#"
},
{
  date: "12/12",
  author: "siriusjack",
  author_url: "#",
  entry_title: "食べられるドングリの見分け方(ドイツ編)",
  entry_url: "#"
},
{
  date: "12/13",
  author: "ivstivs",
  author_url: "https://github.com/ivstivs",
  entry_title: "ProjectileとHelm",
  entry_url: "#"
},
{
  date: "12/14",
  author: "kakenn",
  author_url: "http://shuto.info",
  entry_title: "格安3Dプリンター「daVinci 2.0」を買ってみた。",
  entry_url: "#"
},
{
  date: "12/15",
  author: "ymyzk",
  author_url: "http://www.ymyzk.com",
  entry_title: "sphinxcontrib.httpdomain で RESTful API のドキュメント作成",
  entry_url: "#"
},
{
  date: "12/16",
  author: "cotton_ori",
  author_url: "https://twitter.com/cotton_ori",
  entry_title: "準備中",
  entry_url: "#"
},
{
  date: "12/17",
  author: "pepoipod",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
},
{
  date: "12/18",
  author: "ohmuraken",
  author_url: "#",
  entry_title: "ソーシャルボタンで文字を作る！",
  entry_url: "#"
},
{
  date: "12/19",
  author: "準備中",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
},
{
  date: "12/20",
  author: "準備中",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
},
{
  date: "12/21",
  author: "morishin",
  author_url: "https://twitter.com/morishin127",
  entry_title: "準備中",
  entry_url: "#"
}
,
{
  date: "12/22",
  author: "準備中",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
}
,
{
  date: "12/23",
  author: "準備中",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
}
,
{
  date: "12/24",
  author: "準備中",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
}
,
{
  date: "12/25",
  author: "準備中",
  author_url: "#",
  entry_title: "準備中",
  entry_url: "#"
}
];
<|endoftext|>


<commit_before>var locationX = 31.8772;
var locationY = 35.2402;//18

var shabbosStart = moment(SunCalc.getTimes(moment().startOf('week').day(5), locationX, locationY).sunset).subtract(40,'minute');
var shabbosEnd = moment(SunCalc.getTimes(moment().startOf('week').day(6), locationX, locationY).dusk).add(10,'minute');

var storeData = {
	PostOffice: {name: 'TZ Doar #2', info: 'Corner of Mekor Baruch and Ahavas Yisroel', coordX:31.879313, coordY: 35.239771}
	,RavFichel: {name: 'Rav Fichel Food Sale', info: 'Corner of Mekor Baruch and Ahavas Yisroel Parking Lot', coordX:31.879413, coordY: 35.239728}
	,PharmacyMeuchedet: {name: 'Meuchedet Pharmacy', info: 'Above TZ Makolet', coordX:31.880311, coordY: 35.239828}
	,BDStore:  {name: 'B&D Store', info: 'Ahavat Yisroel 18', coordX:31.878580, coordY: 35.239553}
	,ChadPaamit: {name: 'Chad Paamit', info: 'Ahavat Yisroel 14', coordX:31.878945, coordY: 35.239718}
	,EggsMB1: {name: 'Egg Sale MB1', info: 'Mekor Baruch 1, up 1/2 flight', coordX:31.878198, coordY: 35.240136}
	,WeberBakeStore: {name: 'Weber Bake Store', info: '5/1 Ahavat Yisroel (down 2 floors)\n997-9386 and 052-767-0471', coordX:31.879281, coordY: 35.240036}
	,KeiliMikvaTZ: {name: 'Keili Mikva TZ', info: 'Kehilat Yaakov 9\nOther time: Azulay on Ahavat Emet 17/2, 02-997-1490 until 4pm, by appointment.', coordX:31.881570, coordY: 35.239375}
	,MikvaTZ: {name: 'Mikva TZ',
		info: 'Kehilat Yaakov 9\nOnly times for normal days listed, on winter clock.\nYom Tov night: Tzeits. Motzei Yom Tov follow shabbos schedule.\nDifferent hours on: Motzei 17 Tammuz, 9 Av, Chol Hamoed, Purim. \nFor later, call 997-3441',
		coordX:31.881508, coordY: 35.239266}
	,KikarNetanelSweetsStand: {name: 'Kikar Netanel Sweets Store', info: 'Next to Kikar Netanel', coordX:31.879945, coordY: 35.242878}
	};

var storeHours = {
	PostOffice: [
		{day: 'Sunday', open: '15:30', close: 17}
		,{day: 'Monday', open: '8:30', close: 10}
		,{day: 'Tuesday', open: '15:30', close: 17}
		,{day: 'Wednesday', open: '1700', close: 18}
		,{day: 'Thursday', open: '15:30', close: 17}
		,{day: 'Friday', open: 11, close: 13}
		]
	,PharmacyMeuchedet: [
		{day: 'Sunday', open: 8, close: 14}
		,{day: 'Monday', open: 14, close: 19}
		,{day: 'Tuesday', open: 8, close: 15}
		,{day: 'Wednesday', open: 8, close: 13}
		,{day: 'Thursday', open: 13, close: 19}
		,{day: 'Friday', open: 8, close: 11}
		]
	,BDStore: [
		{day: 'Sunday', open: 16, close: 21}
		,{day: 'Monday', open: 16, close: 21}
		,{day: 'Tuesday', open: 16, close: 21}
		,{day: 'Wednesday', open: 13, close: 21}
		,{day: 'Thursday', open: 16, close: 21}
		,{day: 'Friday', open: 9, close: 13}
		]
	,LeumiRamatEshkol: [
		{day: 'Monday', open: 8.5, close: 13}
		,{day: 'Thursday', open: 8.5, close: 13}
		,{day: 'Monday', open: 16, close: '18:15'}
		,{day: 'Thursday', open: 16, close: '18:15'}

		,{day: 'Tuesday', open: 8.5, close: 14.5}
		,{day: 'Wednesday', open: 8.5, close: 14.5}

		,{day: 'Friday', open: 8.5, close: 12.5}
		]
	,RavFichel: [
		{day: 'Wednesday', open: 12, close: 22}
		]
	,WeberBakeStore: [
		{day: 'Thursday', open: 15.5, close: 17}

		,{day: 'Tuesday', open: 20.5, close: 22}
		,{day: 'Wednesday', open: 20.5, close: 22}
		,{day: 'Thursday', open: 20.5, close: 22}

		,{day: 'Friday', open: 10, close: 13}
		]
	,ChadPaamit: [
		{day: 'Monday', open: 17, close: 19}
		,{day: 'Tuesday', open: 17, close: 19}
		,{day: 'Wednesday', open: 16, close: 21}
		,{day: 'Thursday', open: 16, close: 21}
		,{day: 'Friday', open: 8.5, close: 13}
		]
	,EggsMB1: [
		{day: 'Sunday', open: 19, close: 20}
		,{day: 'Wednesday', open: 16, close: 18}
		]
	,KikarNetanelSweetsStand: [
		{day: 'Sunday', open: 12, close: 23}
		,{day: 'Monday', open: 12, close: 23}
		,{day: 'Tuesday', open: 12, close: 23}
		,{day: 'Wednesday', open: 12, close: 23}
		,{day: 'Thursday', open: 12, close: 23}
		,{day: 'Friday', open: 11, closeText: '1½ hours before Shabbos', close: shabbosStart.clone().subtract(90,'minutes').format('HHmm')}
		,{day: 'Saturday', openText: '40minutes after Tzeits', open: shabbosEnd.clone().add(40,'minutes').format('HHmm'), close: 23.5}
		]
	,KeiliMikvaTZ: [
		,{day: 'Friday', open: 6, closeText: 'until Shabbos', close: shabbosStart.clone().format('HHmm')}
		]
	,MikvaTZ: [
		{day: 'Sunday', open: 18.5, close: 21}
		,{day: 'Monday', open: 18.5, close: 21}
		,{day: 'Tuesday', open: 18.5, close: 21}
		,{day: 'Wednesday', open: 18.5, close: 21}
		,{day: 'Thursday', open: 18.5, close: 21}
		,{day: 'Friday', openText: 'Only Shkia/Tzeitz', open: shabbosStart.clone().add(40,'minutes').format('HHmm'),
						close: shabbosEnd.clone().add(10,'minutes').format('HHmm')	}
		,{day: 'Saturday', openText: '1½ after Shabbos', open: shabbosEnd.clone().add(90,'minutes').format('HHmm'),
						closeText: 'for 2 hours', close: shabbosEnd.clone().add(90+120,'minutes').format('HHmm') }
		]
};

var daysOfWeek = ['sunday','monday','tuesday','wednesday','thursday','friday','saturday'];
var daysOfWeekHuman = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];

var storeList = Object.keys(storeHours);//since object, make list of stores

storeList.forEach(function(name){//iterate list of stores, and overwrite data to normalize it.
	storeHours[name] = storeHours[name].map(function(timeEntry){
		timeEntry.day= daysOfWeek.indexOf(timeEntry.day.toLowerCase());//convert date to numbers in 0-6 format.
		['open','close'].forEach(function(which){//dumb stuff to make it DRY
			timeEntry[which] = normalizeTime(timeEntry[which]);//normalize
			//console.log('just normalized: '+typeof timeEntry[which] + timeEntry[which])
			timeEntry[which+'Human'] = showTime(timeEntry[which]);//and also human readable time
			});

		return timeEntry;
		});
	})

function normalizeTime(time){
	//console.log('about to normalize:' +typeof time + time);
	var arr=[0,0];
	if(typeof time === 'number' && Number.isInteger(time)) arr[0]=time;//if ints, just *60 to get minutes.
	else if(typeof time === 'number') arr= [Math.floor(time), time%1*60];//e.g. open at 8.5 = 8:30
	else if(time.indexOf(':')!==-1) arr = time.split(':');//hh:mm format
	else if(time.length==4) arr = [time.substring(0,2), time.substring(2,4)];//hhmm format
	else arr = [time.substring(0,1), time.substring(1,3)];//hmm format
	//console.log(arr);
	return arr;
	}

function showTime (arr){
	var time=arr.slice(0);//clone it, don't overwrite.
	if (time[0]==12 && time[1]==0) return 'noon';
	if(typeof time[1]==='number' && time[1]<10) time[1]='0'+time[1];//left pad for readability
	var zone='pm';
	if(time[0]>12) time[0]-=12;
	else zone = 'am';
	return time.join(':')+zone;
	}
<commit_msg>updated mikva time<commit_after>var locationX = 31.8772;
var locationY = 35.2402;//18

var shabbosStart = moment(SunCalc.getTimes(moment().startOf('week').day(5), locationX, locationY).sunset).subtract(40,'minute');
var shabbosEnd = moment(SunCalc.getTimes(moment().startOf('week').day(6), locationX, locationY).dusk).add(10,'minute');

var storeData = {
	PostOffice: {name: 'TZ Doar #2', info: 'Corner of Mekor Baruch and Ahavas Yisroel', coordX:31.879313, coordY: 35.239771}
	,RavFichel: {name: 'Rav Fichel Food Sale', info: 'Corner of Mekor Baruch and Ahavas Yisroel Parking Lot', coordX:31.879413, coordY: 35.239728}
	,PharmacyMeuchedet: {name: 'Meuchedet Pharmacy', info: 'Above TZ Makolet', coordX:31.880311, coordY: 35.239828}
	,BDStore:  {name: 'B&D Store', info: 'Ahavat Yisroel 18', coordX:31.878580, coordY: 35.239553}
	,ChadPaamit: {name: 'Chad Paamit', info: 'Ahavat Yisroel 14', coordX:31.878945, coordY: 35.239718}
	,EggsMB1: {name: 'Egg Sale MB1', info: 'Mekor Baruch 1, up 1/2 flight', coordX:31.878198, coordY: 35.240136}
	,WeberBakeStore: {name: 'Weber Bake Store', info: '5/1 Ahavat Yisroel (down 2 floors)\n997-9386 and 052-767-0471', coordX:31.879281, coordY: 35.240036}
	,KeiliMikvaTZ: {name: 'Keili Mikva TZ', info: 'Kehilat Yaakov 9\nOther time: Azulay on Ahavat Emet 17/2, 02-997-1490 until 4pm, by appointment.', coordX:31.881570, coordY: 35.239375}
	,MikvaTZ: {name: 'Women Mikva TZ',
		info: 'Kehilat Yaakov 9\nOnly times for normal days listed, on winter clock. Weekday winter: 6:30pm-9pm. Summer: 7:30pm-9:30pm\nYom Tov night: Tzeits. Motzei Yom Tov follow shabbos schedule.\nDifferent hours on: Motzei 17 Tammuz, 9 Av, Chol Hamoed, Purim. \nFor later, call 997-3441',
		coordX:31.881508, coordY: 35.239266}
	,KikarNetanelSweetsStand: {name: 'Kikar Netanel Sweets Store', info: 'Next to Kikar Netanel', coordX:31.879945, coordY: 35.242878}
	};

var storeHours = {
	PostOffice: [
		{day: 'Sunday', open: '15:30', close: 17}
		,{day: 'Monday', open: '8:30', close: 10}
		,{day: 'Tuesday', open: '15:30', close: 17}
		,{day: 'Wednesday', open: '1700', close: 18}
		,{day: 'Thursday', open: '15:30', close: 17}
		,{day: 'Friday', open: 11, close: 13}
		]
	,PharmacyMeuchedet: [
		{day: 'Sunday', open: 8, close: 14}
		,{day: 'Monday', open: 14, close: 19}
		,{day: 'Tuesday', open: 8, close: 15}
		,{day: 'Wednesday', open: 8, close: 13}
		,{day: 'Thursday', open: 13, close: 19}
		,{day: 'Friday', open: 8, close: 11}
		]
	,BDStore: [
		{day: 'Sunday', open: 16, close: 21}
		,{day: 'Monday', open: 16, close: 21}
		,{day: 'Tuesday', open: 16, close: 21}
		,{day: 'Wednesday', open: 13, close: 21}
		,{day: 'Thursday', open: 16, close: 21}
		,{day: 'Friday', open: 9, close: 13}
		]
	,LeumiRamatEshkol: [
		{day: 'Monday', open: 8.5, close: 13}
		,{day: 'Thursday', open: 8.5, close: 13}
		,{day: 'Monday', open: 16, close: '18:15'}
		,{day: 'Thursday', open: 16, close: '18:15'}

		,{day: 'Tuesday', open: 8.5, close: 14.5}
		,{day: 'Wednesday', open: 8.5, close: 14.5}

		,{day: 'Friday', open: 8.5, close: 12.5}
		]
	,RavFichel: [
		{day: 'Wednesday', open: 12, close: 22}
		]
	,WeberBakeStore: [
		{day: 'Thursday', open: 15.5, close: 17}

		,{day: 'Tuesday', open: 20.5, close: 22}
		,{day: 'Wednesday', open: 20.5, close: 22}
		,{day: 'Thursday', open: 20.5, close: 22}

		,{day: 'Friday', open: 10, close: 13}
		]
	,ChadPaamit: [
		{day: 'Monday', open: 17, close: 19}
		,{day: 'Tuesday', open: 17, close: 19}
		,{day: 'Wednesday', open: 16, close: 21}
		,{day: 'Thursday', open: 16, close: 21}
		,{day: 'Friday', open: 8.5, close: 13}
		]
	,EggsMB1: [
		{day: 'Sunday', open: 19, close: 20}
		,{day: 'Wednesday', open: 16, close: 18}
		]
	,KikarNetanelSweetsStand: [
		{day: 'Sunday', open: 12, close: 23}
		,{day: 'Monday', open: 12, close: 23}
		,{day: 'Tuesday', open: 12, close: 23}
		,{day: 'Wednesday', open: 12, close: 23}
		,{day: 'Thursday', open: 12, close: 23}
		,{day: 'Friday', open: 11, closeText: '1½ hours before Shabbos', close: shabbosStart.clone().subtract(90,'minutes').format('HHmm')}
		,{day: 'Saturday', openText: '40minutes after Tzeits', open: shabbosEnd.clone().add(40,'minutes').format('HHmm'), close: 23.5}
		]
	,KeiliMikvaTZ: [
		,{day: 'Friday', open: 6, closeText: 'until Shabbos', close: shabbosStart.clone().format('HHmm')}
		]
	,MikvaTZ: [
		{day: 'Sunday', open: 18.5, close: 21}
		,{day: 'Monday', open: 18.5, close: 21}
		,{day: 'Tuesday', open: 18.5, close: 21}
		,{day: 'Wednesday', open: 18.5, close: 21}
		,{day: 'Thursday', open: 18.5, close: 21}
		,{day: 'Friday', openText: 'Only Shkia/Tzeitz', open: shabbosStart.clone().add(40,'minutes').format('HHmm'),
						close: shabbosEnd.clone().add(10,'minutes').format('HHmm')	}
		,{day: 'Saturday', openText: '1½ after Shabbos', open: shabbosEnd.clone().add(90,'minutes').format('HHmm'),
						closeText: 'for 2 hours, get there first hour', close: shabbosEnd.clone().add(90+120,'minutes').format('HHmm') }
		]
};

var daysOfWeek = ['sunday','monday','tuesday','wednesday','thursday','friday','saturday'];
var daysOfWeekHuman = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];

var storeList = Object.keys(storeHours);//since object, make list of stores

storeList.forEach(function(name){//iterate list of stores, and overwrite data to normalize it.
	storeHours[name] = storeHours[name].map(function(timeEntry){
		timeEntry.day= daysOfWeek.indexOf(timeEntry.day.toLowerCase());//convert date to numbers in 0-6 format.
		['open','close'].forEach(function(which){//dumb stuff to make it DRY
			timeEntry[which] = normalizeTime(timeEntry[which]);//normalize
			//console.log('just normalized: '+typeof timeEntry[which] + timeEntry[which])
			timeEntry[which+'Human'] = showTime(timeEntry[which]);//and also human readable time
			});

		return timeEntry;
		});
	})

function normalizeTime(time){
	//console.log('about to normalize:' +typeof time + time);
	var arr=[0,0];
	if(typeof time === 'number' && Number.isInteger(time)) arr[0]=time;//if ints, just *60 to get minutes.
	else if(typeof time === 'number') arr= [Math.floor(time), time%1*60];//e.g. open at 8.5 = 8:30
	else if(time.indexOf(':')!==-1) arr = time.split(':');//hh:mm format
	else if(time.length==4) arr = [time.substring(0,2), time.substring(2,4)];//hhmm format
	else arr = [time.substring(0,1), time.substring(1,3)];//hmm format
	//console.log(arr);
	return arr;
	}

function showTime (arr){
	var time=arr.slice(0);//clone it, don't overwrite.
	if (time[0]==12 && time[1]==0) return 'noon';
	if(typeof time[1]==='number' && time[1]<10) time[1]='0'+time[1];//left pad for readability
	var zone='pm';
	if(time[0]>12) time[0]-=12;
	else zone = 'am';
	return time.join(':')+zone;
	}
<|endoftext|>


<commit_before>function flattenObject (obj) {
    var result = {};

    for (var key in obj) {
        if (!obj.hasOwnProperty(key)) continue;

        if (typeof obj[key] === 'object' && !(obj[key] instanceof Array)) {
            var flat = flattenObject(obj[key]);
            for (var x in flat) {
                if (!flat.hasOwnProperty(x)) {
                     continue;
                }

                result[key + '.' + x] = flat[x];
            }
        } else {
            result[key] = obj[key];
        }
    }
    return result;
};

function unflattenObject (flat) {
    var result = {};
    var parentObj = result;

    var keys = Object.keys(flat);
    for (var i = 0; i < keys.length; ++i) {
        var key = keys[i];
        var subkeys = key.split('.');
        var last = subkeys.pop();

        for (var ii = 0; ii < subkeys.length; ++ii) {
            var subkey = subkeys[ii];
            parentObj[subkey] = typeof parentObj[subkey] === 'undefined' ? {} : parentObj[subkey];
            parentObj = parentObj[subkey];
        }

        parentObj[last] = flat[key];
        parentObj = result;
    }

    return result;
}

function prepareData (data) {
    var self = this;

    // wait for html
    if (self.template.options && self.template.options.html && !self.formCache[self.template._id]) {
        self.once('formRendered', function () {
            self.data = flattenObject(data);
            self.emit('dataSet', self.data);
        });

        return;
    }

    self.data = flattenObject(data);
    self.emit('dataSet', self.data);
}

function setData (data, query) {
    var self = this;

    if (!self.template) {
        return;
    }

    // check if data has template
    if (typeof data !== 'object' || self.findBusy) {
        return;
    }

    // don't fetch data from server when query is false
    if (query === false) {
        prepareData.call(self, data);
        return;
    }

    self.findBusy = true;

    var crud = {
        t: self.template._id,
        q: query || {_id: data._id},
        o: {limit: 1},
        // TODO remove this when updates on linked fields are possible
        noJoins: true
    };

    self.emit('find', crud, function (err, resultData) {

        self.findBusy = false;

        // TODO handle error
        if (err) {
            return;
        }

        prepareData.call(self, resultData[0] || data);
    });
}

function setField (field, value) {
    var self = this;

    if (!self.data || !self.template) {
        return;
    }

    // check if field in tempalte exitst
    if (self.template.schema[field]) {
        self.data[field] = value;
        self.emit('dataChanged');
    }

    self.emit('fieldSet');
}

// adds $set and $unset if the field is enabled or disabled
function buildUpdateObject (data) {
    var self = this;

    var obj = {
        $set: {},
        $unset: {}
    }
    var fields = self.formCache[self.template._id].refs;

    for (var field in fields) {
        if (!fields.hasOwnProperty(field)) continue;

        if (!fields[field].disabled && data[field]) {
            obj['$set'][field] = data[field];
        } else if (fields[field].disabled) {
            obj['$unset'][field] = '';
        }
    }

    return obj;
}

function save (callback) {
    var self = this;
    callback = callback || function () {};

    // if no data is set, no data can be saved
    if (!self.data || !self.template) {
        return;
    }

    // create crud request
    var crud = {
        t: self.template._id,
        d: self.send
    };

    // upsert if item already exists
    if (self.data._id) {
        crud.q = {_id: self.data._id};
        delete crud.d._id;
        crud.d = buildUpdateObject.call(self, crud.d);
    }

    // do an insert if no query
    var isInsert = !crud.q;
    if (isInsert) {
        crud.d = unflattenObject(crud.d);
    }

    // do request with the crud module
    self.emit(isInsert ? 'insert' : 'update', crud, function (err, data) {

        // for insert queries

        if (isInsert) {

            if (err || !data || !data.length) {
                callback("No self.data or self.template set.");
                self.emit('saved', err || 'Missing insert result');
                return;
            }

            self.data = data[0];
            callback(null, self.data);
            self.emit('saved', null, self.data, true);
            return;
        }

        // for update queries

        self.once('dataSet', function () {

            if (!self.config.options.callGetItem) {
                callback(null, self.data);
                self.emit('saved', null, self.data);
                return;
            }

            self.emit('getItem', self.data, function (err, dataItem) {
                callback(err, dataItem);
                self.emit('saved', err, dataItem);
            });
        });

        // update queries require a form refresh
        self.emit('setData', {_id: self.data._id});
    });
}

function remove () {
    var self = this;

    // if not data is set, no data can be removed
    if (!self.data || !self.data._id || self.template) {
        return;
    }

    // create crud object
    var crud = {
        t: self.template._id,
        q: {_id: self.data._id}
    };

    // do request with the crud module
    self.emit('remove', crud, function (err, result) {

        // reset form data
        if (!err && result) {
            self.data = {};
        }

        // emit remove operation complete
        self.emit('removed', err, result);
    });
}

function init () {
    var self = this;

    // init data events when a template is set
    self.once('templateSet', function () {
        self.on('setData', setData);
        self.on('setField', setField);
        self.on('saveCrud', save);
        self.on('rm', remove);
    });
}

module.exports = init;
<commit_msg>Fixed the empty  and  update objects<commit_after>function flattenObject (obj) {
    var result = {};

    for (var key in obj) {
        if (!obj.hasOwnProperty(key)) continue;

        if (typeof obj[key] === 'object' && !(obj[key] instanceof Array)) {
            var flat = flattenObject(obj[key]);
            for (var x in flat) {
                if (!flat.hasOwnProperty(x)) {
                     continue;
                }

                result[key + '.' + x] = flat[x];
            }
        } else {
            result[key] = obj[key];
        }
    }
    return result;
};

function unflattenObject (flat) {
    var result = {};
    var parentObj = result;

    var keys = Object.keys(flat);
    for (var i = 0; i < keys.length; ++i) {
        var key = keys[i];
        var subkeys = key.split('.');
        var last = subkeys.pop();

        for (var ii = 0; ii < subkeys.length; ++ii) {
            var subkey = subkeys[ii];
            parentObj[subkey] = typeof parentObj[subkey] === 'undefined' ? {} : parentObj[subkey];
            parentObj = parentObj[subkey];
        }

        parentObj[last] = flat[key];
        parentObj = result;
    }

    return result;
}

function prepareData (data) {
    var self = this;

    // wait for html
    if (self.template.options && self.template.options.html && !self.formCache[self.template._id]) {
        self.once('formRendered', function () {
            self.data = flattenObject(data);
            self.emit('dataSet', self.data);
        });

        return;
    }

    self.data = flattenObject(data);
    self.emit('dataSet', self.data);
}

function setData (data, query) {
    var self = this;

    if (!self.template) {
        return;
    }

    // check if data has template
    if (typeof data !== 'object' || self.findBusy) {
        return;
    }

    // don't fetch data from server when query is false
    if (query === false) {
        prepareData.call(self, data);
        return;
    }

    self.findBusy = true;

    var crud = {
        t: self.template._id,
        q: query || {_id: data._id},
        o: {limit: 1},
        // TODO remove this when updates on linked fields are possible
        noJoins: true
    };

    self.emit('find', crud, function (err, resultData) {

        self.findBusy = false;

        // TODO handle error
        if (err) {
            return;
        }

        prepareData.call(self, resultData[0] || data);
    });
}

function setField (field, value) {
    var self = this;

    if (!self.data || !self.template) {
        return;
    }

    // check if field in tempalte exitst
    if (self.template.schema[field]) {
        self.data[field] = value;
        self.emit('dataChanged');
    }

    self.emit('fieldSet');
}

// adds $set and $unset if the field is enabled or disabled
function buildUpdateObject (data) {
    var self = this;

    var obj = {
        $set: {},
        $unset: {}
    }
    var fields = self.formCache[self.template._id].refs;

    for (var field in fields) {
        if (!fields.hasOwnProperty(field)) continue;

        if (!fields[field].disabled && data[field]) {
            obj['$set'][field] = data[field];
        } else if (fields[field].disabled) {
            obj['$unset'][field] = '';
        }
    }

    // empty $set or $unset object are invalid in a mongo update document
    for (var key in obj) {
        if (!Object.keys(obj[key]).length) {
            delete obj[key];
        }
    }

    return obj;
}

function save (callback) {
    var self = this;
    callback = callback || function () {};

    // if no data is set, no data can be saved
    if (!self.data || !self.template) {
        return;
    }

    // create crud request
    var crud = {
        t: self.template._id,
        d: self.send
    };

    // upsert if item already exists
    if (self.data._id) {
        crud.q = {_id: self.data._id};
        delete crud.d._id;
        crud.d = buildUpdateObject.call(self, crud.d);
    }

    // do an insert if no query
    var isInsert = !crud.q;
    if (isInsert) {
        crud.d = unflattenObject(crud.d);
    }

    // do request with the crud module
    self.emit(isInsert ? 'insert' : 'update', crud, function (err, data) {

        // for insert queries

        if (isInsert) {

            if (err || !data || !data.length) {
                callback("No self.data or self.template set.");
                self.emit('saved', err || 'Missing insert result');
                return;
            }

            self.data = data[0];
            callback(null, self.data);
            self.emit('saved', null, self.data, true);
            return;
        }

        // for update queries

        self.once('dataSet', function () {

            if (!self.config.options.callGetItem) {
                callback(null, self.data);
                self.emit('saved', null, self.data);
                return;
            }

            self.emit('getItem', self.data, function (err, dataItem) {
                callback(err, dataItem);
                self.emit('saved', err, dataItem);
            });
        });

        // update queries require a form refresh
        self.emit('setData', {_id: self.data._id});
    });
}

function remove () {
    var self = this;

    // if not data is set, no data can be removed
    if (!self.data || !self.data._id || self.template) {
        return;
    }

    // create crud object
    var crud = {
        t: self.template._id,
        q: {_id: self.data._id}
    };

    // do request with the crud module
    self.emit('remove', crud, function (err, result) {

        // reset form data
        if (!err && result) {
            self.data = {};
        }

        // emit remove operation complete
        self.emit('removed', err, result);
    });
}

function init () {
    var self = this;

    // init data events when a template is set
    self.once('templateSet', function () {
        self.on('setData', setData);
        self.on('setField', setField);
        self.on('saveCrud', save);
        self.on('rm', remove);
    });
}

module.exports = init;

<|endoftext|>