<commit_before>/* jshint devel:true, esnext: true */
/* globals nunjucks: true, $ */

$(function() {
    'use strict';

    /**
     * Disable and enable event on scroll begin and scroll end.
     * @see http://www.thecssninja.com/javascript/pointer-events-60fps
     */
    var root = document.documentElement;
    var timer;

    window.addEventListener('scroll', function() {
        // User scrolling so stop the timeout
        clearTimeout(timer);
        // Pointer events has not already been disabled.
        if (!root.style.pointerEvents) {
            root.style.pointerEvents = 'none';
        }

        timer = setTimeout(function() {
            root.style.pointerEvents = '';
        }, 500);
    }, false);

    var constants = $('#data'),
        wwwroot = constants.data('root'),
        icons = wwwroot + '/static/icons/',
        views = wwwroot + '/static/views';

    /**
     * Presents the user with a notification message
     * @param {string} type - The type of notification to set, must be one of info, warn or error.
     * @param {string} message - The message to be displayed.
     * @param {Object} target - The element to use as the display target for the message.
     */
    function setUserMessage(type, message, target) {
        var messageContainer = document.createElement('p'),
            msg = document.createTextNode(message);

        messageContainer.appendChild(msg);

        switch(type) {
            case 'info':
                messageContainer.setAttribute('class', 'message info');
                break;
            case 'warn':
                messageContainer.setAttribute('class', 'message warn');
                break;
            case 'error':
                messageContainer.setAttribute('class', 'message error');
                break;
            default:
                console.log('Unrecognized message type. See function documentation for supported types.');
                return;
        }
        // If we are already showing a user message in the target, do not append again.
        if (!$('.message', target).length) {
            target.append(messageContainer);
        }
    }

    /**
     * Removes previously added notification message from target.
     * @param {Object} target - The element to use as the display target for the message.
     */
    function removeUserMessage(target) {
        var userMessage = $('.message', target);

        // If the user message container is found, remove it completely.
        if (userMessage.length) {
            userMessage.remove();
        }
    }

    if (!nunjucks.env) {
        nunjucks.env = new nunjucks.Environment(new nunjucks.HttpLoader(views));
    }

    var env = nunjucks.env,
        tmpl = env.getTemplate('results.html'),
        pathLineTmpl = env.getTemplate('path_line.html');

    /**
     * Represents the path line displayed next to the file path label on individual document pages.
     * Also handles population of the path lines template in the correct format.
     *
     * @param {string} fullPath - The full path of the currently displayed file.
     * @param {string} tree - The tree which was searched and in which this file can be found.
     */
    function buildPathLine(fullPath, tree) {
        var pathLines = '',
            pathRoot = '/' + tree + '/source/',
            paths = fullPath.split('/'),
            splitPathLength = paths.length,
            dataPath = [];

        for (var pathIndex in paths) {
            var isFirstOrLast = false;

            if ((splitPathLength - 1) === pathIndex || splitPathLength === 1) {
                isFirstOrLast = true;
            }

            // Do not add a forward slash if there is only one item in the Array
            //or, if this is the last iteration.
            var displayPath = isFirstOrLast ? paths[pathIndex] : paths[pathIndex] + '/';

            dataPath.push(paths[pathIndex]);
            pathLines += pathLineTmpl.render({
                'data_path': dataPath.join('/'),
                'display_path': displayPath,
                'url': pathRoot + dataPath.join('/')
            });
        }

        return pathLines;
    }

    var searchForm = $('#basic_search'),
        queryField = $('#query'),
        contentContainer = $('#content');

    /**
     * Returns the full Ajax URL for search
     * @param {string} params - A serialized string of the form inputs.
     */
    function buildAjaxURL(params) {
        var search = constants.data('search');
        return search + '?' + params;
    }

    var waitr = null;
    /**
     * The poller used to track changes in the query input field value.
     * @param {string} previousQuery - The last query term that was sent.
     */
    function startQueryInputPoller(previousQuery) {

        (function poller() {
            var currentQuery = $.trim(queryField.val());

            if (previousQuery !== currentQuery && currentQuery.length > 2) {
                doQuery(currentQuery);
                previousQuery = currentQuery;
            } else {
                waitr = setTimeout(poller, 500);
            }
        })();
    }

    /**
     * Stops the QueryInputPoller
     */
    function stopQueryInputPoller() {
        // If a timer exists, clear it before continuing.
        if (waitr) {
            clearTimeout(waitr);
        }
    }

    /**
     * Executes queries and populates the results templates with the returned data.
     * @param {string} query - The query term sent when this function was called.
     */
    function doQuery(query) {

        var previousQuery = query ? query : previousQuery;

        $.getJSON(buildAjaxURL(searchForm.serialize()), function(data) {

            // If no data is returned, inform the user.
            if (!data.results.length) {
                contentContainer.empty();
                setUserMessage('info', contentContainer.data('no-results'), contentContainer);
            } else {
                var results = data.results;

                for (var result in results) {
                    results[result].pathLine = buildPathLine(results[result].path, data.tree);
                    results[result].iconPath = icons + results[result].icon;
                }

                contentContainer.empty().append(tmpl.render(data));
            }
        }).done(function() {
            var query = $.trim(queryField.val());

            if (previousQuery !== query && query.length > 2) {
                stopQueryInputPoller();
                doQuery(query);

                previousQuery = query;
            } else {
                // The query has not changed, start the poller.
                startQueryInputPoller(previousQuery);
            }
        }).fail(function(jqxhr, textStatus, error) {
            var errorMessage = searchForm.data('error');

            if (error) {
                errorMessage += ' Error: ' + error;
            }
            stopQueryInputPoller();
            setUserMessage('error', errorMessage, $('.text_search', searchForm));
        });
    }

    var previousQuery = '';

    // Start search as you type as soon as the field receives focus.
    queryField.on('focus', function() {
        var query = $.trim(queryField.val());

        if (query !== previousQuery && query.length > 2) {
            doQuery(query);
            // Because the search field might lose focus and regain
            // focus without the query text changing, we need to keep
            // track of previous queries here in order to avoid unnecessary
            // ajax calls.
            previousQuery = query;
        } else {
            // The query was either empty or there was less than
            // the mminimum three characters so, simply pass an
            // empty string as the previous query to the poller.
            startQueryInputPoller('');
        }
    });

    // Stop search as you type as soon as the field looses focus.
    queryField.on('blur', function() {
        stopQueryInputPoller();
    });

    searchForm.on('submit', function() {
        // Set redirect to true for direct results.
        $('#redirect').val('true');
        // Ensure JSON is not returned.
        $('#format').val('html');
    });

    /**
     * Converts string to new Date and returns a formatted date in the
     * format d-m-y h:m
     * @param String dateString A date in string form.
     *
     */
    function formatDate(dateString) {
        var fullDateTime = new Date(dateString);
        var date = fullDateTime.getDate() + '-' + (fullDateTime.getMonth() + 1) + '-' + fullDateTime.getFullYear();
        var time = fullDateTime.getHours() + ':' + fullDateTime.getMinutes();

        return date + ' ' + time;
    }

    var prettyDate = $('.pretty-date');
    prettyDate.each(function() {
        $(this).text(formatDate($(this).data('datetime')));
    });
});
<commit_msg>change date format and pad signle numbers<commit_after>/* jshint devel:true, esnext: true */
/* globals nunjucks: true, $ */

$(function() {
    'use strict';

    /**
     * Disable and enable event on scroll begin and scroll end.
     * @see http://www.thecssninja.com/javascript/pointer-events-60fps
     */
    var root = document.documentElement;
    var timer;

    window.addEventListener('scroll', function() {
        // User scrolling so stop the timeout
        clearTimeout(timer);
        // Pointer events has not already been disabled.
        if (!root.style.pointerEvents) {
            root.style.pointerEvents = 'none';
        }

        timer = setTimeout(function() {
            root.style.pointerEvents = '';
        }, 500);
    }, false);

    var constants = $('#data'),
        wwwroot = constants.data('root'),
        icons = wwwroot + '/static/icons/',
        views = wwwroot + '/static/views';

    /**
     * Presents the user with a notification message
     * @param {string} type - The type of notification to set, must be one of info, warn or error.
     * @param {string} message - The message to be displayed.
     * @param {Object} target - The element to use as the display target for the message.
     */
    function setUserMessage(type, message, target) {
        var messageContainer = document.createElement('p'),
            msg = document.createTextNode(message);

        messageContainer.appendChild(msg);

        switch(type) {
            case 'info':
                messageContainer.setAttribute('class', 'message info');
                break;
            case 'warn':
                messageContainer.setAttribute('class', 'message warn');
                break;
            case 'error':
                messageContainer.setAttribute('class', 'message error');
                break;
            default:
                console.log('Unrecognized message type. See function documentation for supported types.');
                return;
        }
        // If we are already showing a user message in the target, do not append again.
        if (!$('.message', target).length) {
            target.append(messageContainer);
        }
    }

    /**
     * Removes previously added notification message from target.
     * @param {Object} target - The element to use as the display target for the message.
     */
    function removeUserMessage(target) {
        var userMessage = $('.message', target);

        // If the user message container is found, remove it completely.
        if (userMessage.length) {
            userMessage.remove();
        }
    }

    if (!nunjucks.env) {
        nunjucks.env = new nunjucks.Environment(new nunjucks.HttpLoader(views));
    }

    var env = nunjucks.env,
        tmpl = env.getTemplate('results.html'),
        pathLineTmpl = env.getTemplate('path_line.html');

    /**
     * Represents the path line displayed next to the file path label on individual document pages.
     * Also handles population of the path lines template in the correct format.
     *
     * @param {string} fullPath - The full path of the currently displayed file.
     * @param {string} tree - The tree which was searched and in which this file can be found.
     */
    function buildPathLine(fullPath, tree) {
        var pathLines = '',
            pathRoot = '/' + tree + '/source/',
            paths = fullPath.split('/'),
            splitPathLength = paths.length,
            dataPath = [];

        for (var pathIndex in paths) {
            var isFirstOrLast = false;

            if ((splitPathLength - 1) === pathIndex || splitPathLength === 1) {
                isFirstOrLast = true;
            }

            // Do not add a forward slash if there is only one item in the Array
            //or, if this is the last iteration.
            var displayPath = isFirstOrLast ? paths[pathIndex] : paths[pathIndex] + '/';

            dataPath.push(paths[pathIndex]);
            pathLines += pathLineTmpl.render({
                'data_path': dataPath.join('/'),
                'display_path': displayPath,
                'url': pathRoot + dataPath.join('/')
            });
        }

        return pathLines;
    }

    var searchForm = $('#basic_search'),
        queryField = $('#query'),
        contentContainer = $('#content');

    /**
     * Returns the full Ajax URL for search
     * @param {string} params - A serialized string of the form inputs.
     */
    function buildAjaxURL(params) {
        var search = constants.data('search');
        return search + '?' + params;
    }

    var waitr = null;
    /**
     * The poller used to track changes in the query input field value.
     * @param {string} previousQuery - The last query term that was sent.
     */
    function startQueryInputPoller(previousQuery) {

        (function poller() {
            var currentQuery = $.trim(queryField.val());

            if (previousQuery !== currentQuery && currentQuery.length > 2) {
                doQuery(currentQuery);
                previousQuery = currentQuery;
            } else {
                waitr = setTimeout(poller, 500);
            }
        })();
    }

    /**
     * Stops the QueryInputPoller
     */
    function stopQueryInputPoller() {
        // If a timer exists, clear it before continuing.
        if (waitr) {
            clearTimeout(waitr);
        }
    }

    /**
     * Executes queries and populates the results templates with the returned data.
     * @param {string} query - The query term sent when this function was called.
     */
    function doQuery(query) {

        var previousQuery = query ? query : previousQuery;

        $.getJSON(buildAjaxURL(searchForm.serialize()), function(data) {

            // If no data is returned, inform the user.
            if (!data.results.length) {
                contentContainer.empty();
                setUserMessage('info', contentContainer.data('no-results'), contentContainer);
            } else {
                var results = data.results;

                for (var result in results) {
                    results[result].pathLine = buildPathLine(results[result].path, data.tree);
                    results[result].iconPath = icons + results[result].icon;
                }

                contentContainer.empty().append(tmpl.render(data));
            }
        }).done(function() {
            var query = $.trim(queryField.val());

            if (previousQuery !== query && query.length > 2) {
                stopQueryInputPoller();
                doQuery(query);

                previousQuery = query;
            } else {
                // The query has not changed, start the poller.
                startQueryInputPoller(previousQuery);
            }
        }).fail(function(jqxhr, textStatus, error) {
            var errorMessage = searchForm.data('error');

            if (error) {
                errorMessage += ' Error: ' + error;
            }
            stopQueryInputPoller();
            setUserMessage('error', errorMessage, $('.text_search', searchForm));
        });
    }

    var previousQuery = '';

    // Start search as you type as soon as the field receives focus.
    queryField.on('focus', function() {
        var query = $.trim(queryField.val());

        if (query !== previousQuery && query.length > 2) {
            doQuery(query);
            // Because the search field might lose focus and regain
            // focus without the query text changing, we need to keep
            // track of previous queries here in order to avoid unnecessary
            // ajax calls.
            previousQuery = query;
        } else {
            // The query was either empty or there was less than
            // the mminimum three characters so, simply pass an
            // empty string as the previous query to the poller.
            startQueryInputPoller('');
        }
    });

    // Stop search as you type as soon as the field looses focus.
    queryField.on('blur', function() {
        stopQueryInputPoller();
    });

    searchForm.on('submit', function() {
        // Set redirect to true for direct results.
        $('#redirect').val('true');
        // Ensure JSON is not returned.
        $('#format').val('html');
    });

    /**
     * Adds aleading 0 to numbers less than 10 and greater that 0
     *
     * @param int number The number to test against
     *
     * return Either the original number or the number prefixed with 0
     */
    function addLeadingZero(number) {
        return (number < 9) || (number > 0) ? "0" + number : number;
    }

    /**
     * Converts string to new Date and returns a formatted date in the
     * format YYYY-MM-DD h:m
     * @param String dateString A date in string form.
     *
     */
    function formatDate(dateString) {
        var fullDateTime = new Date(dateString);
        var date = fullDateTime.getFullYear() + '-' + (fullDateTime.getMonth() + 1) + '-' + addLeadingZero(fullDateTime.getDate());
        var time = fullDateTime.getHours() + ':' + addLeadingZero(fullDateTime.getMinutes());

        return date + ' ' + time;
    }

    var prettyDate = $('.pretty-date');
    prettyDate.each(function() {
        $(this).text(formatDate($(this).data('datetime')));
    });
});
<|endoftext|>


<commit_before>'use strict'

const http = require('http')

var methods = {}
var randomCache = []

function get (url, callback) {
  http.get(url, function (result) {
    const contentType = result.headers['content-type']
    const statusCode = result.statusCode

    let error
    if (statusCode !== 200) {
      error = new Error('Unable to send request for definitions. Status code: ' + statusCode)
    } else if ('application/json'.indexOf(contentType) > -1) {
      error = new Error("Content retrieved isn't JSON. Content type: '" + contentType + "'")
    }

    if (error) {
      // Removes response data to clear up memory.
      result.resume()
      callback(error)
      return
    }

    result.setEncoding('utf8')

    let rawData = ''
    result.on('data', function (buffer) {
      rawData += buffer
    })
    result.on('end', function () {
      try {
        callback(null, JSON.parse(rawData))
      } catch (error) {
        callback(new Error('Failed to parse retrieved Urban Dictionary JSON.'))
      }
    })
  })
}

methods.defid = function defid (id, callback) {
  get('http://api.urbandictionary.com/v0/define?defid=' + id, function (error, result) {
    if (error) {
      callback(error)
      return
    }

    if (!result || result.result_type !== 'exact') {
      callback(new Error('No result found.'))
      return
    }

    callback(null, result.list[0], result.tags, result.sounds)
  })
}

methods.random = function random (callback) {
  if (!randomCache[0]) {
    get('http://api.urbandictionary.com/v0/random', function (error, result) {
      if (error) {
        callback(error)
        return
      }
      randomCache = result.list
      callback(null, randomCache[0])
      randomCache.splice(0, 1)
    })
  } else {
    callback(null, randomCache[0])
    randomCache.splice(0, 1)
  }
}

methods.term = function term (word, callback) {
  get('http://api.urbandictionary.com/v0/define?term=' + encodeURIComponent(word), function (error, result) {
    if (error) {
      callback(error)
      return
    }

    if (!result || result.result_type !== 'exact') {
      callback(new Error(word + ' is undefined.'))
      return
    }

    callback(null, result.list, result.tags, result.sounds)
  })
}

module.exports = methods
<commit_msg>* Fixed application/json error handler.<commit_after>'use strict'

const http = require('http')

var methods = {}
var randomCache = []

function get (url, callback) {
  http.get(url, function (result) {
    const contentType = result.headers['content-type']
    const statusCode = result.statusCode

    let error
    if (statusCode !== 200) {
      error = new Error('Unable to send request for definitions. Status code: ' + statusCode)
    } else if (contentType.indexOf('application/json') === -1) {
      error = new Error("Content retrieved isn't JSON. Content type: '" + contentType + "'")
    }

    if (error) {
      // Removes response data to clear up memory.
      result.resume()
      callback(error)
      return
    }

    result.setEncoding('utf8')

    let rawData = ''
    result.on('data', function (buffer) {
      rawData += buffer
    })
    result.on('end', function () {
      try {
        callback(null, JSON.parse(rawData))
      } catch (error) {
        callback(new Error('Failed to parse retrieved Urban Dictionary JSON.'))
      }
    })
  })
}

methods.defid = function defid (id, callback) {
  get('http://api.urbandictionary.com/v0/define?defid=' + id, function (error, result) {
    if (error) {
      callback(error)
      return
    }

    if (!result || result.result_type !== 'exact') {
      callback(new Error('No result found.'))
      return
    }

    callback(null, result.list[0], result.tags, result.sounds)
  })
}

methods.random = function random (callback) {
  if (!randomCache[0]) {
    get('http://api.urbandictionary.com/v0/random', function (error, result) {
      if (error) {
        callback(error)
        return
      }
      randomCache = result.list
      callback(null, randomCache[0])
      randomCache.splice(0, 1)
    })
  } else {
    callback(null, randomCache[0])
    randomCache.splice(0, 1)
  }
}

methods.term = function term (word, callback) {
  get('http://api.urbandictionary.com/v0/define?term=' + encodeURIComponent(word), function (error, result) {
    if (error) {
      callback(error)
      return
    }

    if (!result || result.result_type !== 'exact') {
      callback(new Error(word + ' is undefined.'))
      return
    }

    callback(null, result.list, result.tags, result.sounds)
  })
}

module.exports = methods
<|endoftext|>


<commit_before>/* @flow */

const cheerio = require('cheerio')
const request = require('request-promise')
const url = require('url')
const logger = require('../../core/logger')
const Registration = require('../../core/remote/registration')

const log = logger({
  component: 'remote/automated_registration'
})

const client = request.defaults({
  jar: true, // Enable cookies so the stack doesn't change the CSRF token.
  resolveWithFullResponse: true, // So we can check headers & status code.
  simple: false, // Don't reject on redirect (e.g. after login).
  timeout: 120000 // Registration from AppVeyor can be slow.
})

/** Resolve with the CSRF token from the cozy-stack login page.
 *
 * So we can use it in the actual `login()`.
 */
const _getCsrfToken = async cozyUrl => {
  log.debug('Get CSRF token...')
  const { body } = await client.get({ url: cozyUrl('/auth/login') })
  const $ = cheerio.load(body)
  const csrf_token = $('#csrf_token').val()
  if (`${csrf_token}` === '') {
    throw new Error(
      `Could not parse CSRF token from login page:\n  ${$.text()}`
    )
  } else {
    return csrf_token
  }
}

/** Login to the Cozy using `getCsrfToken()` result.
 *
 * Resolves when login is successful. Rejects otherwise.
 */
const login = async (cozyUrl, passphrase) => {
  const csrf_token = await _getCsrfToken(cozyUrl)
  log.debug({ csrf_token }, 'Login...')
  const form = { passphrase, csrf_token }
  const response = await client.post({
    url: cozyUrl('/auth/login'),
    form
  })
  if (!response.headers.location) {
    const $ = cheerio.load(response.body)
    throw new Error(
      `Login failed (no redirect, code ${response.statusCode}):\n  ${$.text()}`
    )
  }
}

/** Retrieve the form fields expected by `authorize()`.
 *
 * - `authorizeUrl` is the one provided by `core/remote/registration`.
 *
 * Resolves when the form fields could be parsed from the authorization page.
 * Rejects otherwise.
 */
const _getAuthorizationForm = async authorizeUrl => {
  log.debug('Load authorization form...')
  const authorizePageResp = await client({ url: authorizeUrl })

  log.debug('Parse authorization form...')
  const $ = cheerio.load(authorizePageResp.body)
  return $('form.auth')
    .serializeArray()
    .reduce((data, param) => {
      data[param.name] = param.value
      return data
    }, {})
}

/** Authorize the client.
 *
 * - `authorizeUrl` is the one provided by `core/remote/registration`.
 *
 * Resolves with the URL to follow in order to finalize registration.
 * Rejects when the response is not a redirection.
 */
const authorize = async authorizeUrl => {
  const form = await _getAuthorizationForm(authorizeUrl)
  log.debug('Authorize...')
  const res = await client.post({ url: authorizeUrl, form })
  const redirectUrl = res.headers.location

  if (redirectUrl) {
    return res.headers.location
  } else {
    const $ = cheerio.load(res.body)
    throw new Error(
      `Authorization failed (code ${res.statusCode}):\n  ${$.text()}`
    )
  }
}

/** An automated Registration instance using the cozy-stack Web interface. */
const automatedRegistration = (
  cozyBaseUrl /*: string */,
  passphrase /*: string */,
  storage /*: * */
) /*: Registration */ => {
  const cozyUrl = path => new url.URL(cozyBaseUrl + path)
  const saveCredentials = async redirectUrl => {
    log.debug('Saving credentials...')
    await client({ url: redirectUrl })
  }

  return new Registration(cozyBaseUrl, storage, async authorizeUrl => {
    await login(cozyUrl, passphrase)
    const redirectUrl = await authorize(authorizeUrl)
    await saveCredentials(redirectUrl)
    return cozyUrl
  })
}

module.exports = automatedRegistration
<commit_msg>dev/remote/automated_registration: Fix URLs<commit_after>/* @flow */

const cheerio = require('cheerio')
const request = require('request-promise')
const url = require('url')
const logger = require('../../core/logger')
const Registration = require('../../core/remote/registration')

const log = logger({
  component: 'remote/automated_registration'
})

const client = request.defaults({
  jar: true, // Enable cookies so the stack doesn't change the CSRF token.
  resolveWithFullResponse: true, // So we can check headers & status code.
  simple: false, // Don't reject on redirect (e.g. after login).
  timeout: 120000 // Registration from AppVeyor can be slow.
})

/** Resolve with the CSRF token from the cozy-stack login page.
 *
 * So we can use it in the actual `login()`.
 */
const _getCsrfToken = async cozyUrl => {
  log.debug('Get CSRF token...')
  const { body } = await client.get({ url: cozyUrl('/auth/login') })
  const $ = cheerio.load(body)
  const csrf_token = $('#csrf_token').val()
  if (`${csrf_token}` === '') {
    throw new Error(
      `Could not parse CSRF token from login page:\n  ${$.text()}`
    )
  } else {
    return csrf_token
  }
}

/** Login to the Cozy using `getCsrfToken()` result.
 *
 * Resolves when login is successful. Rejects otherwise.
 */
const login = async (cozyUrl, passphrase) => {
  const csrf_token = await _getCsrfToken(cozyUrl)
  log.debug({ csrf_token }, 'Login...')
  const form = { passphrase, csrf_token }
  const response = await client.post({
    url: cozyUrl('/auth/login'),
    form
  })
  if (!response.headers.location) {
    const $ = cheerio.load(response.body)
    throw new Error(
      `Login failed (no redirect, code ${response.statusCode}):\n  ${$.text()}`
    )
  }
}

/** Retrieve the form fields expected by `authorize()`.
 *
 * - `authorizeUrl` is the one provided by `core/remote/registration`.
 *
 * Resolves when the form fields could be parsed from the authorization page.
 * Rejects otherwise.
 */
const _getAuthorizationForm = async authorizeUrl => {
  log.debug('Load authorization form...')
  const authorizePageResp = await client({ url: authorizeUrl })

  log.debug('Parse authorization form...')
  const $ = cheerio.load(authorizePageResp.body)
  return $('form.auth')
    .serializeArray()
    .reduce((data, param) => {
      data[param.name] = param.value
      return data
    }, {})
}

/** Authorize the client.
 *
 * - `authorizeUrl` is the one provided by `core/remote/registration`.
 *
 * Resolves with the URL to follow in order to finalize registration.
 * Rejects when the response is not a redirection.
 */
const authorize = async authorizeUrl => {
  const form = await _getAuthorizationForm(authorizeUrl)
  log.debug('Authorize...')
  const res = await client.post({ url: authorizeUrl, form })
  const redirectUrl = res.headers.location

  if (redirectUrl) {
    return res.headers.location
  } else {
    const $ = cheerio.load(res.body)
    throw new Error(
      `Authorization failed (code ${res.statusCode}):\n  ${$.text()}`
    )
  }
}

/** An automated Registration instance using the cozy-stack Web interface. */
const automatedRegistration = (
  cozyBaseUrl /*: string */,
  passphrase /*: string */,
  storage /*: * */
) /*: Registration */ => {
  const cozyUrl = path => new url.URL(path, cozyBaseUrl)
  const saveCredentials = async redirectUrl => {
    log.debug('Saving credentials...')
    await client({ url: redirectUrl })
  }

  return new Registration(cozyBaseUrl, storage, async authorizeUrl => {
    await login(cozyUrl, passphrase)
    const redirectUrl = await authorize(authorizeUrl)
    await saveCredentials(redirectUrl)
    return cozyUrl
  })
}

module.exports = automatedRegistration
<|endoftext|>


<commit_before>/*
*
*	Chimera abilities
*
*/
G.abilities[45] =[

// 	First Ability: Cyclic Duality
{
	trigger: "onReset",

	//	require() :
	require : function(){
		return this.testRequirements();
	},

	activate: function() {
		// Only activate when fatigued
		if (!this.creature.isFatigued()) {
			return;
		}

		if (this.isUpgraded()) {
			this.creature.heal(Math.floor(this.creature.stats.regrowth / 2), true);
		}
		if (this.creature.stats.meditation > 0) {
			this.creature.recharge(Math.floor(this.creature.stats.meditation / 2));
		}
	}
},

//	Second Ability: Tooth Fairy
{
	//	Type : Can be "onQuery","onStartPhase","onDamage"
	trigger : "onQuery",

	//	require() :
	require : function() {
		if( !this.testRequirements() ) return false;

		if( !this.atLeastOneTarget( G.grid.getHexMap(this.creature.x-3,this.creature.y-2,0,false,frontnback3hex),"enemy" ) ){
			this.message = G.msg.abilities.notarget;
			return false;
		}

		return true;
	},

	//	query() :
	query : function() {
		var ability = this;
		var chimera = this.creature;

		G.grid.queryCreature( {
			fnOnConfirm : function() { ability.animation.apply(ability, arguments); },
			team : 0, // Team, 0 = enemies
			id : chimera.id,
			flipped : chimera.flipped,
			hexs : G.grid.getHexMap(chimera.x - 3, chimera.y - 2, 0, false, frontnback3hex),
		});
	},

	//	activate() :
	activate : function(target, args) {
		var ability = this;

		ability.end();

		var damage = new Damage(
			ability.creature, // Attacker
			ability.damages, // Damage Type
			1, // Area
			[]	// Effects
		);
		target.takeDamage(damage);
		if (this.isUpgraded()) {
			// Second attack
			target.takeDamage(damage);
		}
	},
},

//	Third Ability: Disturbing Sound
{
	//	Type : Can be "onQuery", "onStartPhase", "onDamage"
	trigger : "onQuery",

	//	require() :
	require : function() {
		if( !this.testRequirements() ) return false;

		if (!this.testDirection({ team: "both", sourceCreature: this.creature })) {
			this.message = G.msg.abilities.notarget;
			return false;
		}
		return true;
	},

	//	query() :
	query : function(){
		var ability = this;
		var chimera = this.creature;

		G.grid.queryDirection({
			fnOnConfirm : function(){ ability.animation.apply(ability, arguments); },
			flipped : chimera.player.flipped,
			team : "both",
			id : chimera.id,
			requireCreature : true,
			x : chimera.x,
			y : chimera.y,
			sourceCreature: chimera
		});
	},

	//	activate() :
	activate : function(path, args) {
		var ability = this;

		ability.end();

		var target = path.last().creature;
		var hexes = G.grid.getHexLine(
			target.x, target.y, args.direction, target.flipped);

		var damage = new Damage(
			ability.creature, // Attacker
			ability.damages, // Damage Type
			1, // Area
			[]	// Effects
		);
		result = target.takeDamage(damage);

		var i = 0;
		while(result.kill) {
			i++;
			if (i >= hexes.length) {
				break;
			}
			var hex = hexes[i];
			if (!hex.creature) {
				continue;
			}
			target = hex.creature;

			// extra sonic damage if upgraded
			var sonic = ability.damages.sonic + (this.isUpgraded() ? 9 : 0);
			if (sonic <= 0) {
				break;
			}
			damage = new Damage(
				ability.creature, // Attacker
				{sonic: sonic}, // Damage Type
				1, // Area
				[]	// Effects
			);
			result = target.takeDamage(damage);
		}
	}
},

// Fourth Ability: Battering Ram
{
	//	Type : Can be "onQuery", "onStartPhase", "onDamage"
	trigger : "onQuery",

	_targetTeam: "both",

	_getDirections: function() {
		return this.testDirections({
			flipped: this.creature.player.flipped,
			team: this._targetTeam,
			id: this.creature.id,
			requireCreature: true,
			x: this.creature.x,
			y: this.creature.y,
			distance: 1,
			sourceCreature: this.creature,
			directions: [1, 1, 1, 1, 1, 1],
			includeCrea: true,
			stopOnCreature: true
		});
	},

	require : function() {
		if( !this.testRequirements() ) return false;

		var directions = this._getDirections();
		for (var i = 0; i < directions.length; i++) {
			if (directions[i] === 1) {
				return true;
			}
		}
		this.message = G.msg.abilities.notarget;
		return false;
	},

	//	query() :
	query : function(){
		var ability = this;
		var chimera = this.creature;

		G.grid.queryDirection({
			fnOnConfirm : function(){ ability.animation.apply(ability, arguments); },
			flipped : chimera.player.flipped,
			team: this._targetTeam,
			id : chimera.id,
			directions: this._getDirections(),
			requireCreature : true,
			x : chimera.x,
			y : chimera.y,
			sourceCreature: chimera
		});
	},

	activate: function(path, args) {
		var ability = this;
		this.end();

		var knockback = function(_target, _crush, _range) {
			var damage = new Damage(
				ability.creature, // Attacker
				{crush: _crush}, // Damage Type
				1, // Area
				[]	// Effects
			);
			var result = _target.takeDamage(damage);
			// Knock the target back if they are still alive and there is enough range
			if (result.kill || _range <= 0) {
				return;
			}
			// See how far we can knock the target back
			var hexes = G.grid.getHexLine(
				_target.x, _target.y, args.direction, _target.flipped);
			// Skip the first hex as it is the same hex as the target
			hexes = hexes.splice(1, _range + 1);
			var hex = null;
			var nextHex = null;
			// See how far the target can be knocked back
			for (var i = 0; i < hexes.length; i++) {
				nextHex = hexes[i];
				// Check that the next knockback hex is valid
				if (i === hexes.length - 1) break;
				if (!hexes[i].isWalkable(_target.size, _target.id, true)) break;
				hex = hexes[i];
			}

			var knockbackEnd = function() {
				if (nextHex !== null && nextHex !== hex && nextHex.creature) {
					// Diminishing crush damage if unupgraded
					var crush = ability.isUpgraded() ? _crush : _crush - 5;
					// Diminishing range if unupgraded
					var range = ability.isUpgraded() ? _range : _range - 1;
					knockback(nextHex.creature, crush, range);
				} else {
					G.activeCreature.queryMove();
				}
			};

			if (hex !== null) {
				_target.moveTo(hex, {
					callback: knockbackEnd,
					ignoreMovementPoint: true,
					ignorePath: true,
					overrideSpeed: 400, // Custom speed for knockback
					animation: "push"
				});
			} else {
				// No knockback distance, but there may be a creature behind the target
				knockbackEnd();
			}
		};

		var target = path.last().creature;
		var crush = this.damages.crush;
		var range = 3;
		knockback(target, crush, range);
	}
}

];
<commit_msg>Fix Battering Ram hitting left (#1047)<commit_after>/*
*
*	Chimera abilities
*
*/
G.abilities[45] =[

// 	First Ability: Cyclic Duality
{
	trigger: "onReset",

	//	require() :
	require : function(){
		return this.testRequirements();
	},

	activate: function() {
		// Only activate when fatigued
		if (!this.creature.isFatigued()) {
			return;
		}

		if (this.isUpgraded()) {
			this.creature.heal(Math.floor(this.creature.stats.regrowth / 2), true);
		}
		if (this.creature.stats.meditation > 0) {
			this.creature.recharge(Math.floor(this.creature.stats.meditation / 2));
		}
	}
},

//	Second Ability: Tooth Fairy
{
	//	Type : Can be "onQuery","onStartPhase","onDamage"
	trigger : "onQuery",

	//	require() :
	require : function() {
		if( !this.testRequirements() ) return false;

		if( !this.atLeastOneTarget( G.grid.getHexMap(this.creature.x-3,this.creature.y-2,0,false,frontnback3hex),"enemy" ) ){
			this.message = G.msg.abilities.notarget;
			return false;
		}

		return true;
	},

	//	query() :
	query : function() {
		var ability = this;
		var chimera = this.creature;

		G.grid.queryCreature( {
			fnOnConfirm : function() { ability.animation.apply(ability, arguments); },
			team : 0, // Team, 0 = enemies
			id : chimera.id,
			flipped : chimera.flipped,
			hexs : G.grid.getHexMap(chimera.x - 3, chimera.y - 2, 0, false, frontnback3hex),
		});
	},

	//	activate() :
	activate : function(target, args) {
		var ability = this;

		ability.end();

		var damage = new Damage(
			ability.creature, // Attacker
			ability.damages, // Damage Type
			1, // Area
			[]	// Effects
		);
		target.takeDamage(damage);
		if (this.isUpgraded()) {
			// Second attack
			target.takeDamage(damage);
		}
	},
},

//	Third Ability: Disturbing Sound
{
	//	Type : Can be "onQuery", "onStartPhase", "onDamage"
	trigger : "onQuery",

	//	require() :
	require : function() {
		if( !this.testRequirements() ) return false;

		if (!this.testDirection({ team: "both", sourceCreature: this.creature })) {
			this.message = G.msg.abilities.notarget;
			return false;
		}
		return true;
	},

	//	query() :
	query : function(){
		var ability = this;
		var chimera = this.creature;

		G.grid.queryDirection({
			fnOnConfirm : function(){ ability.animation.apply(ability, arguments); },
			flipped : chimera.player.flipped,
			team : "both",
			id : chimera.id,
			requireCreature : true,
			x : chimera.x,
			y : chimera.y,
			sourceCreature: chimera
		});
	},

	//	activate() :
	activate : function(path, args) {
		var ability = this;

		ability.end();

		var target = path.last().creature;
		var hexes = G.grid.getHexLine(
			target.x, target.y, args.direction, target.flipped);

		var damage = new Damage(
			ability.creature, // Attacker
			ability.damages, // Damage Type
			1, // Area
			[]	// Effects
		);
		result = target.takeDamage(damage);

		var i = 0;
		while(result.kill) {
			i++;
			if (i >= hexes.length) {
				break;
			}
			var hex = hexes[i];
			if (!hex.creature) {
				continue;
			}
			target = hex.creature;

			// extra sonic damage if upgraded
			var sonic = ability.damages.sonic + (this.isUpgraded() ? 9 : 0);
			if (sonic <= 0) {
				break;
			}
			damage = new Damage(
				ability.creature, // Attacker
				{sonic: sonic}, // Damage Type
				1, // Area
				[]	// Effects
			);
			result = target.takeDamage(damage);
		}
	}
},

// Fourth Ability: Battering Ram
{
	//	Type : Can be "onQuery", "onStartPhase", "onDamage"
	trigger : "onQuery",

	_targetTeam: "both",

	_getDirections: function() {
		return this.testDirections({
			flipped: this.creature.player.flipped,
			team: this._targetTeam,
			id: this.creature.id,
			requireCreature: true,
			x: this.creature.x,
			y: this.creature.y,
			distance: 1,
			sourceCreature: this.creature,
			directions: [1, 1, 1, 1, 1, 1],
			includeCrea: true,
			stopOnCreature: true
		});
	},

	require : function() {
		if( !this.testRequirements() ) return false;

		var directions = this._getDirections();
		for (var i = 0; i < directions.length; i++) {
			if (directions[i] === 1) {
				return true;
			}
		}
		this.message = G.msg.abilities.notarget;
		return false;
	},

	//	query() :
	query : function(){
		var ability = this;
		var chimera = this.creature;

		G.grid.queryDirection({
			fnOnConfirm : function(){ ability.animation.apply(ability, arguments); },
			flipped : chimera.player.flipped,
			team: this._targetTeam,
			id : chimera.id,
			directions: this._getDirections(),
			requireCreature : true,
			x : chimera.x,
			y : chimera.y,
			sourceCreature: chimera
		});
	},

	activate: function(path, args) {
		var ability = this;
		this.end();

		var knockback = function(_target, _crush, _range) {
			var damage = new Damage(
				ability.creature, // Attacker
				{crush: _crush}, // Damage Type
				1, // Area
				[]	// Effects
			);
			var result = _target.takeDamage(damage);
			// Knock the target back if they are still alive and there is enough range
			if (result.kill || _range <= 0) {
				return;
			}
			// See how far we can knock the target back
			var hexes = G.grid.getHexLine(
				_target.x, _target.y, args.direction, _target.player.flipped);
			// Skip the first hex as it is the same hex as the target
			hexes = hexes.splice(1, _range + 1);
			var hex = null;
			var nextHex = null;
			// See how far the target can be knocked back
			for (var i = 0; i < hexes.length; i++) {
				nextHex = hexes[i];
				// Check that the next knockback hex is valid
				if (i === hexes.length - 1) break;
				if (!hexes[i].isWalkable(_target.size, _target.id, true)) break;
				hex = hexes[i];
			}

			var knockbackEnd = function() {
				// Special case when hitting left: the next hex is still the same
				// creature, so continue in this direction until we reach the next
				// creature
				if (nextHex.creature === _target && args.direction === 4) {
					var nextHexes = G.grid.getHexLine(
						_target.x, _target.y, args.direction, _target.player_flipped);
					nextHexes = nextHexes.splice(_target.size);
					if (nextHexes.length > 0) {
						nextHex = nextHexes[0];
					}
				}
				if (nextHex !== null && nextHex !== hex && nextHex.creature) {
					// Diminishing crush damage if unupgraded
					var crush = ability.isUpgraded() ? _crush : _crush - 5;
					// Diminishing range if unupgraded
					var range = ability.isUpgraded() ? _range : _range - 1;
					knockback(nextHex.creature, crush, range);
				} else {
					G.activeCreature.queryMove();
				}
			};

			if (hex !== null) {
				_target.moveTo(hex, {
					callback: knockbackEnd,
					ignoreMovementPoint: true,
					ignorePath: true,
					overrideSpeed: 400, // Custom speed for knockback
					animation: "push"
				});
			} else {
				// No knockback distance, but there may be a creature behind the target
				knockbackEnd();
			}
		};

		var target = path.last().creature;
		var crush = this.damages.crush;
		var range = 3;
		knockback(target, crush, range);
	}
}

];
<|endoftext|>


<commit_before>class AdminController {
    constructor(data) {
        this.data = data;
    }

    getViewBookings(req, res) {
        return res.render('auth/admin/viewbookings', { req: req });
    }

    getViewCars(req, res) {
        Promise.resolve(this.data.cars.getAll())
            .then((cars) => {
                return res.render('auth/admin/viewcars', {
                    context: cars,
                    req: req,
                });
            });
    }

    getViewUsers(req, res) {
        Promise.resolve(this.data.users.getAll())
            .then((user) => {
                return res.render('auth/admin/viewusers', {
                    context: user,
                    req: req,
                });
            });
    }

    getViewDeals(req, res) {
        Promise.resolve(this.data.cars.filterBy({ 'specialpriceactivated': '1' }))
            .then((deals) => {
                return res.render('auth/admin/viewdeals', {
                        context: deals,
                        req: req,
                    },
                );
            });
    }
}

const init = (data) => {
    return new AdminController(data);
};

module.exports = { init };
<commit_msg>added edituser functionality<commit_after>class AdminController {
    constructor(data) {
        this.data = data;
    }

    getViewBookings(req, res) {
        return res.render('auth/admin/viewbookings', { req: req });
    }

    getViewCars(req, res) {
        Promise.resolve(this.data.cars.getAll())
            .then((cars) => {
                return res.render('auth/admin/viewcars', {
                    context: cars,
                    req: req,
                });
            });
    }

    getViewUsers(req, res) {
        Promise.resolve(this.data.users.getAll())
            .then((user) => {
                return res.render('auth/admin/viewusers', {
                    context: user,
                    req: req,
                });
            });
    }

    getViewDeals(req, res) {
        Promise.resolve(this.data.cars.filterBy({ 'specialpriceactivated': '1' }))
            .then((deals) => {
                return res.render('auth/admin/viewdeals', {
                        context: deals,
                        req: req,
                    },
                );
            });
    }

    getEditUserByIdForm(req, res) {
        Promise.resolve(this.data.users.findById(req.params.id))
            .then((user) => {
                return res.render('auth/admin/edituser', {
                        user,
                    req: req,
                });
            });
    }

    updateUserProfile(req, res) {
        const bodyUser = req.body;
        return this._updateUserProperties(req.params.id, bodyUser)
            .then((user) => {
                return this.data.users.updateById(user);
            })
            .then(() => {
                return res.redirect('/auth/viewusers');
            })
            .catch((err) => {
                req.toastr.error(err.message);
                return res.redirect('/auth/viewusers');
            });
    }

    _updateUserProperties(userId, user) {
        return this.data.users.findById(userId)
            .then((dbUser) => {
                user._id = dbUser._id;
                user.username = dbUser.username;
                user.role = dbUser.role;
                user.bookings = dbUser.bookings;
                user.passHash = dbUser.passHash;

                return Promise.resolve(user);
            });
    }
}

const init = (data) => {
    return new AdminController(data);
};

module.exports = { init };
<|endoftext|>


<commit_before>import React from 'react';
import CodeMirror from 'react-codemirror';
import 'codemirror/lib/codemirror.css';
import './TextEditor.css';
import { testCode, submitCode } from '../../../../ContestActions';

// This hot-loads all the various syntax highlighting client-side since they depend
// on the window and navigator objects
if (typeof window !== 'undefined' && typeof window.navigator !== 'undefined') {
    require('codemirror/mode/python/python');
    require('codemirror/mode/javascript/javascript');
    require('codemirror/mode/clike/clike');
    require('codemirror/mode/ruby/ruby');
    require('codemirror/mode/octave/octave');
}

// Initial text editor prompts in different languages
const prompts = {
    python: '# Your code will be saved automatically\ndef addOne(x):\n  return x + 1\nprint addOne(1)',
};
// local storage addresses
let code_str, mode_str, lang_str = "";

// The text editor where users can write and edit code
export default class TextEditor extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            code: prompts.python,
            readOnly: false,
            mode: 'python', // Syntax for text editor
            lang: 'python',
            isBusy: false,
        };
        this.onTestClick = this.onTestClick.bind(this);
        this.onSubmitClick = this.onSubmitClick.bind(this);
        code_str = `${this.props.contest_id}p${this.props.problemNum}code`;
        mode_str = `${this.props.contest_id}p${this.props.problemNum}mode`;
        lang_str = `${this.props.contest_id}p${this.props.problemNum}lang`;
        // Check local storage to recover any autosaved code
        if (localStorage[code_str]) { this.state.code = localStorage[code_str]; }
        if (localStorage[mode_str]) { this.state.mode = localStorage[mode_str]; }
        if (localStorage[lang_str]) { this.state.lang = localStorage[lang_str]; }
    }

    updateCode = (newCode) => {
        this.setState({ code: newCode });
        // autosave code to local storage for each problem
        localStorage[code_str] = this.state.code;
    };

    changeMode = (e) => {
        let lang = e.target.value;
        let mode = lang;
        // Sometimes language != mode so we handle it here
        switch (lang) {
        case 'c':
            mode = 'text/x-csrc';
            break;
        case 'cpp':
            mode = 'text/x-c++src';
            break;
        case 'java':
            mode = 'text/x-java';
            break;
        case 'python3':
            mode = 'python';
            break;
        case 'scala':
            mode = 'text/x-scala';
            break;
        }
        this.setState({
          mode: mode,
          lang: lang
        });
        // Update local storage
        localStorage[mode_str] = mode;
        localStorage[lang_str] = lang;
    };

    onTestClick() {
        this.setState({isBusy: true});
        const { contest_id, team_id } = this.props;
        let userTestInput = document.getElementById('custom_in').value;
        testCode(contest_id, team_id, this.state.code, this.state.lang, [userTestInput]).then(res => {
          this.setState({isBusy: false});
        });
    }

    onSubmitClick() {
        this.setState({isBusy: true});
        const { contest_id, team_id, problemNum } = this.props;
        submitCode(contest_id, team_id, this.state.code, this.state.lang, (problemNum-1)).then(res => {
          this.setState({isBusy: false});
        });
    }

    render() {
        let options = {
            lineNumbers: true,
            readOnly: false,
            mode: this.state.mode,
        };

        return (

                <select onChange={this.changeMode} value={this.state.lang}>
                    <option value='python'>Python</option>
                    <option value='python3'>Python 3</option>
                    <option value='c'>C</option>
                    <option value='cpp'>C++</option>
                    <option value='java'>Java</option>
                    <option value='javascript'>JavaScript</option>
                    <option value='octave'>Matlab</option>
                    <option value='ruby'>Ruby</option>
                    <option value='scala'>Scala</option>
                </select>

                <CodeMirror ref='editor' value={this.state.code} onChange={this.updateCode} options={options} />
                Test against your own custom input

                <textarea name='custom_in' id='custom_in' cols='30' rows='10' />

                  <button ref='testButton' disabled={this.state.isBusy} onClick={this.onTestClick} type="button" className="btn btn-primary">Test</button>
                  <button ref='subButton' disabled={this.state.isBusy} onClick={this.onSubmitClick} type="button" className="btn btn-primary">Submit</button>

        );
    }
}

TextEditor.propTypes = {
    contest_id: React.PropTypes.string.isRequired,
    team_id: React.PropTypes.string.isRequired,
    problemNum: React.PropTypes.string.isRequired,
};
<commit_msg>Changed prompt<commit_after>import React from 'react';
import CodeMirror from 'react-codemirror';
import 'codemirror/lib/codemirror.css';
import './TextEditor.css';
import { testCode, submitCode } from '../../../../ContestActions';

// This hot-loads all the various syntax highlighting client-side since they depend
// on the window and navigator objects
if (typeof window !== 'undefined' && typeof window.navigator !== 'undefined') {
    require('codemirror/mode/python/python');
    require('codemirror/mode/javascript/javascript');
    require('codemirror/mode/clike/clike');
    require('codemirror/mode/ruby/ruby');
    require('codemirror/mode/octave/octave');
}

// Initial text editor prompts in different languages
const prompts = {
    python: '# This is just an example\n# Your code will be saved automatically\ndef addOne(x):\n  return x + 1\nprint addOne(1)',
};
// local storage addresses
let code_str, mode_str, lang_str = "";

// The text editor where users can write and edit code
export default class TextEditor extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            code: prompts.python,
            readOnly: false,
            mode: 'python', // Syntax for text editor
            lang: 'python',
            isBusy: false,
        };
        this.onTestClick = this.onTestClick.bind(this);
        this.onSubmitClick = this.onSubmitClick.bind(this);
        code_str = `${this.props.contest_id}p${this.props.problemNum}code`;
        mode_str = `${this.props.contest_id}p${this.props.problemNum}mode`;
        lang_str = `${this.props.contest_id}p${this.props.problemNum}lang`;
        // Check local storage to recover any autosaved code
        if (localStorage[code_str]) { this.state.code = localStorage[code_str]; }
        if (localStorage[mode_str]) { this.state.mode = localStorage[mode_str]; }
        if (localStorage[lang_str]) { this.state.lang = localStorage[lang_str]; }
    }

    updateCode = (newCode) => {
        this.setState({ code: newCode });
        // autosave code to local storage for each problem
        localStorage[code_str] = this.state.code;
    };

    changeMode = (e) => {
        let lang = e.target.value;
        let mode = lang;
        // Sometimes language != mode so we handle it here
        switch (lang) {
        case 'c':
            mode = 'text/x-csrc';
            break;
        case 'cpp':
            mode = 'text/x-c++src';
            break;
        case 'java':
            mode = 'text/x-java';
            break;
        case 'python3':
            mode = 'python';
            break;
        case 'scala':
            mode = 'text/x-scala';
            break;
        }
        this.setState({
          mode: mode,
          lang: lang
        });
        // Update local storage
        localStorage[mode_str] = mode;
        localStorage[lang_str] = lang;
    };

    onTestClick() {
        this.setState({isBusy: true});
        const { contest_id, team_id } = this.props;
        let userTestInput = document.getElementById('custom_in').value;
        testCode(contest_id, team_id, this.state.code, this.state.lang, [userTestInput]).then(res => {
          this.setState({isBusy: false});
        });
    }

    onSubmitClick() {
        this.setState({isBusy: true});
        const { contest_id, team_id, problemNum } = this.props;
        submitCode(contest_id, team_id, this.state.code, this.state.lang, (problemNum-1)).then(res => {
          this.setState({isBusy: false});
        });
    }

    render() {
        let options = {
            lineNumbers: true,
            readOnly: false,
            mode: this.state.mode,
        };

        return (

                <select onChange={this.changeMode} value={this.state.lang}>
                    <option value='python'>Python</option>
                    <option value='python3'>Python 3</option>
                    <option value='c'>C</option>
                    <option value='cpp'>C++</option>
                    <option value='java'>Java</option>
                    <option value='javascript'>JavaScript</option>
                    <option value='octave'>Matlab</option>
                    <option value='ruby'>Ruby</option>
                    <option value='scala'>Scala</option>
                </select>

                <CodeMirror ref='editor' value={this.state.code} onChange={this.updateCode} options={options} />
                Test against your own custom input

                <textarea name='custom_in' id='custom_in' cols='30' rows='10' />

                  <button ref='testButton' disabled={this.state.isBusy} onClick={this.onTestClick} type="button" className="btn btn-primary">Test</button>
                  <button ref='subButton' disabled={this.state.isBusy} onClick={this.onSubmitClick} type="button" className="btn btn-primary">Submit</button>

        );
    }
}

TextEditor.propTypes = {
    contest_id: React.PropTypes.string.isRequired,
    team_id: React.PropTypes.string.isRequired,
    problemNum: React.PropTypes.string.isRequired,
};
<|endoftext|>


<commit_before>"use strict";

let testTasks = [];

if (configuration.host.java) {
    testTasks.push("exec:testRhino");
}

if (configuration.host.nashorn) {
    testTasks.push("exec:testNashorn");
}

if (configuration.host.wscript) {
    testTasks.push("exec:testWscript");
} else {
    testTasks.push("exec:testNodewscript");
}

Object.keys(configuration.browsers).forEach(browserName => {
    testTasks.push(`exec:test${browserName.charAt(0).toUpperCase()}${browserName.substr(1)}`);
});

module.exports = {

    // Linters
    linters: [
        "jshint",
        "eslint"
    ],

    // Code quality tools
    quality: [
        "istanbul",
        "plato"
    ],

    // Tests on sources
    source: [
        "mocha:source",
        "mochaTest:source"
    ].concat(testTasks),

    // Tests on debug version
    debug: [
        "mocha:debug",
        "mochaTest:debug"
    ].concat(testTasks.map(name => name + "Debug")),

    // Tests on release version
    release: [
        "mocha:release",
        "mochaTest:release"
    ].concat(testTasks.map(name => name + "Release"))

};

configuration.files.legacyTest.forEach(versionFile => {
    let version = versionFile.substr(0, versionFile.lastIndexOf("."));
    module.exports[`legacy${version}`] = testTasks.map(task => `${task}Legacy:${version}`);
});
<commit_msg>Removes useless concurrent tasks (#258)<commit_after>"use strict";

let testTasks = [];

if (configuration.host.java) {
    testTasks.push("exec:testRhino");
}

if (configuration.host.nashorn) {
    testTasks.push("exec:testNashorn");
}

if (configuration.host.wscript) {
    testTasks.push("exec:testWscript");
} else {
    testTasks.push("exec:testNodewscript");
}

Object.keys(configuration.browsers).forEach(browserName => {
    testTasks.push(`exec:test${browserName.charAt(0).toUpperCase()}${browserName.substr(1)}`);
});

module.exports = {

    // Tests on sources
    source: [
        "mocha:source",
        "mochaTest:source"
    ].concat(testTasks),

    // Tests on debug version
    debug: [
        "mocha:debug",
        "mochaTest:debug"
    ].concat(testTasks.map(name => name + "Debug")),

    // Tests on release version
    release: [
        "mocha:release",
        "mochaTest:release"
    ].concat(testTasks.map(name => name + "Release"))

};

configuration.files.legacyTest.forEach(versionFile => {
    let version = versionFile.substr(0, versionFile.lastIndexOf("."));
    module.exports[`legacy${version}`] = testTasks.map(task => `${task}Legacy:${version}`);
});
<|endoftext|>


<commit_before>angular.module('resizeImagesApp', [])
    .controller('resizeImagesCtrl', function($scope) {

        // When Dynamic Image is loaded, remove the loader
		var loadedImage = document.getElementById('loadedImage'),
			progress = document.getElementById('progress');

		loadedImage.onload = function () {
		   progress.innerHTML = '';
		   loadedImage.setAttribute("style", "display:block");
	     };

        $scope.resizeImage = function() {

            // Hide Image
            loadedImage.setAttribute("style", "display:none");

            var url = $scope.url,
                width = $scope.width,
                height = $scope.height;

                // Loading...
                progress.innerHTML = '

';

                //remove HTTPS or HTTP
                url = url.replace('https://','').replace('http://','');

                // Photon Jetpack URL (server 1 or 0)
                $scope.resizedImage = "http://i" + Math.round(Math.random()) +  ".wp.com/" + url + "?resize=" + width + "," + height;

        };// END resizeImage function

    }); // END controller
<commit_msg>Strip image information<commit_after>angular.module('resizeImagesApp', [])
    .controller('resizeImagesCtrl', function($scope) {

        // When Dynamic Image is loaded, remove the loader
		var loadedImage = document.getElementById('loadedImage'),
			progress = document.getElementById('progress');

		loadedImage.onload = function () {
		   progress.innerHTML = '';
		   loadedImage.setAttribute("style", "display:block");
	     };

        $scope.resizeImage = function() {

            // Hide Image
            loadedImage.setAttribute("style", "display:none");

            var url = $scope.url,
                width = $scope.width,
                height = $scope.height;

                // Loading...
                progress.innerHTML = '

';

                //remove HTTPS or HTTP
                url = url.replace('https://','').replace('http://','');

                // Photon Jetpack URL (server 1 or 0)
                $scope.resizedImage = "http://i" + Math.round(Math.random()) +  ".wp.com/" + url + "?strip=all&resize=" + width + "," + height;

        };// END resizeImage function

    }); // END controller
<|endoftext|>


<commit_before>// const io = require('socket.io')();
const { tokenStore } = require('../common');
const config = require('../config');

const handlePreflightRequest = (req, res) => {
  res.setHeader('Access-Control-Allow-Origin', req.headers.origin);
  res.setHeader('Access-Control-Allow-Headers', `Content-Type, ${config.tokenName}`);
  res.setHeader('Access-Control-Allow-Credentials', true);
  res.end();
};

const initSocketIOBiz = () => {
  io.use(async (socket, next) => {
    const token = socket.handshake.headers[config.tokenName];
    if (token) {
      const userInfo = await tokenStore.get(token);
      if (userInfo) {
        socket.handshake.user = userInfo;
        return next();
      }
    }
    return next(new Error('401'));
  });
  io.on('connection', socket => {
    socket.emit('test', 'hello');
    socket.on('disconnect', function() {
      console.log('user disconnected');
    });
  });
};

module.exports = {
  initSocketIOBiz,
  handlePreflightRequest
};
<commit_msg>api logic<commit_after>// const io = require('socket.io')();
const { tokenStore } = require('../common');
const config = require('../config');

const handlePreflightRequest = (req, res) => {
  res.setHeader('Access-Control-Allow-Origin', req.headers.origin);
  res.setHeader('Access-Control-Allow-Headers', `Content-Type, ${config.tokenName}`);
  res.setHeader('Access-Control-Allow-Credentials', true);
  res.end();
};

const userMap = new global.Map();

function handleMessage(io, socket, msg) {
  if (!msg || !msg.type) {
    return;
  }
  switch (msg.type) {
    case 'SEND_MESSAGE':
      console.log(msg.message);
      socket.to('user_10000_10001').broadcast.emit('message', {
        type: 'NEW_MESSAGE',
        message: {
          message: msg.message.message
        }
      });
      break;
  }
}

const initSocketIOBiz = () => {
  global.io.use(async (socket, next) => {
    const token = socket.handshake.headers[config.tokenName];
    if (token) {
      const userInfo = await tokenStore.get(token);
      if (userInfo) {
        socket.handshake.user = userInfo;
        return next();
      }
    }
    return next(new Error('401'));
  });
  global.io.on('connection', socket => {
    const user = socket.handshake.user;
    socket.join('user_10000_10001');
    // 如果存在，先踢掉
    if (userMap.has(user.userId)) {
      const oldSocket = userMap.get(user.userId);
      oldSocket.emit('message', { type: 'FORCED_DISCONNECT', message: '您的账号在其他设备登录，您已被强制下线。' });
      oldSocket.disconnect();
    }
    userMap.set(user.userId, socket);
    socket.on('message', msg => {
      handleMessage(global.io, socket, msg);
    });
    socket.on('disconnect', function() {
      userMap.delete(user.userId);
    });
  });
};

module.exports = {
  initSocketIOBiz,
  handlePreflightRequest
};
<|endoftext|>


<commit_before>
import _$$ from '../../_scripts/_helpers/_$selector';

const m = 'm-revealer';
const _m = '.'+m;

class Revealer {
	constructor(wrapperElem){
		this._$wrapper = wrapperElem;
		this._$trigger = this._$wrapper.querySelector(`${_m}__trigger`);
		this._$slider = this._$wrapper.querySelector(`${_m}__slider`);
		this._$content = this._$wrapper.querySelector(`${_m}__content`);
		this.isReady = false;
		this.timer;
		this.relevantIDs = this.gather_ids();
		this.initialise();
	}

	initialise(){
		this.isOpen = this.check_url();
		if (!this.isOpen) {
			this.close();
		}
		this._$wrapper.classList.add('-set');
		this._$trigger.onclick = ()=> this.toggle();
		this.isReady = true;
	}

	open(){
		this._$wrapper.classList.remove('-closed');
		this.wait_for_animation().then(()=>{
			this.isOpen = true;
			this.clear_max_height();
		});
	}

	close() {
		this.set_max_height();
		this.delay(1).then(()=>{
			this._$wrapper.classList.add('-closed');
			this.isOpen = false;
		})
	}

	toggle(){
		if (this.isOpen) {
			this.close();
		} else {
			this.open();
		}
	}

	set_max_height(){
		const height = getComputedStyle(this._$content).height;
		this._$slider.style.maxHeight = height;
	}
	clear_max_height(){
		this._$slider.style.maxHeight = 'none';
	}

	delay(delay){
		return new Promise(resolve => {
			setTimeout(resolve, delay);
		})
	}

	wait_for_animation(){
		clearTimeout(this.timer);
		this.isReady = false;
		return new Promise(resolve => {
			this.timer = setTimeout(resolve, 500);
		}).then(()=> {
			return Promise.resolve(()=> this.isReady = true);
		});
	}

	check_url(){
		const hash = window.location.hash.replace('#','');
		const hasID = this.relevantIDs.some(id => id === hash);
		return hasID;
	}

	gather_ids(){
		const children = _$$(_m, this._$content);
		const child_trigger_ids = children.map(get_id);

		return [this._$trigger.id, ...child_trigger_ids];

		function get_id (_$wrapper) {
			const _$trigger = _$wrapper.querySelector(`${_m}__trigger`);
			return _$trigger.id;
		}
	}

	get_parents_revelers(){
		let parents = [];
		let elem = this._$trigger;
		while (elem.classList) {
			if (elem.classList.contains(m)){
				parents.push(elem);
			}
			elem = elem.parentNode;
		}
		return parents;
	}
}

export default function(){
	const _$$revealers = [...document.querySelectorAll(_m)];
	_$$revealers.forEach(_$revealer => new Revealer(_$revealer));
}
<commit_msg>Made this.delay() easier to reuse<commit_after>
import _$$ from '../../_scripts/_helpers/_$selector';

const m = 'm-revealer';
const _m = '.'+m;

class Revealer {
	constructor(wrapperElem){
		this._$wrapper = wrapperElem;
		this._$trigger = this._$wrapper.querySelector(`${_m}__trigger`);
		this._$slider = this._$wrapper.querySelector(`${_m}__slider`);
		this._$content = this._$wrapper.querySelector(`${_m}__content`);
		this.isReady = false;
		this.timer;
		this.relevantIDs = this.gather_ids();
		this.initialise();
	}

	initialise(){
		this.isOpen = this.check_url();
		if (!this.isOpen) {
			this.close();
		}
		this._$wrapper.classList.add('-set');
		this._$trigger.onclick = ()=> this.toggle();
		this.isReady = true;
	}

	open(){
		this._$wrapper.classList.remove('-closed');
		this.wait_for_animation().then(()=>{
			this.isOpen = true;
			this.clear_max_height();
		});
	}

	close() {
		this.set_max_height();
		this.delay(1).then(()=>{
			this._$wrapper.classList.add('-closed');
			this.isOpen = false;
		})
	}

	toggle(){
		if (this.isOpen) {
			this.close();
		} else {
			this.open();
		}
	}

	set_max_height(){
		const height = getComputedStyle(this._$content).height;
		this._$slider.style.maxHeight = height;
	}
	clear_max_height(){
		this._$slider.style.maxHeight = 'none';
	}

	delay(delay, timeout){
		return new Promise(resolve => {
			if (timeout) {
				timeout = setTimeout(resolve, delay);
			} else {
			setTimeout(resolve, delay);
			}
		})
	}

	wait_for_animation(){
		clearTimeout(this.timer);
		this.isReady = false;
		return this.delay(500, this.timer).then(()=> {
			return Promise.resolve(()=> this.isReady = true);
		});
	}

	check_url(){
		const hash = window.location.hash.replace('#','');
		const hasID = this.relevantIDs.some(id => id === hash);
		return hasID;
	}

	gather_ids(){
		const children = _$$(_m, this._$content);
		const child_trigger_ids = children.map(get_id);

		return [this._$trigger.id, ...child_trigger_ids];

		function get_id (_$wrapper) {
			const _$trigger = _$wrapper.querySelector(`${_m}__trigger`);
			return _$trigger.id;
		}
	}

	get_parents_revelers(){
		let parents = [];
		let elem = this._$trigger;
		while (elem.classList) {
			if (elem.classList.contains(m)){
				parents.push(elem);
			}
			elem = elem.parentNode;
		}
		return parents;
	}
}

export default function(){
	const _$$revealers = [...document.querySelectorAll(_m)];
	_$$revealers.forEach(_$revealer => new Revealer(_$revealer));
}
<|endoftext|>


<commit_before>const { BagItProfile } = require('../../bagit/bagit_profile');
const { BaseController } = require('./base_controller');
const { Context } = require('../../core/context');
const { Job } = require('../../core/job');
const { JobFileUIHelper } = require('../common/job_file_ui_helper');
const { JobPackagingUIHelper } = require('../common/job_packaging_ui_helper');
const { JobForm } = require('../forms/job_form');
const { JobPackageOpForm } = require('../forms/job_package_op_form');
const Templates = require('../common/templates');

const typeMap = {
    limit: 'number',
    offset: 'number',
}

class JobController extends BaseController {

    constructor(params) {
        super(params, 'Jobs');
        this.typeMap = typeMap;

        this.model = Job;
        this.formClass = JobForm;
        //this.formTemplate = Templates.jobForm;
        this.listTemplate = Templates.jobList;
        this.nameProperty = 'name';
        this.defaultOrderBy = 'createdAt';
        this.defaultSortDirection = 'desc';
    }

    new() {
        let job = new Job();
        job.save();
        this.params.set('id', job.id);
        return this.files();
    }

    files() {
        let job = Job.find(this.params.get('id'));
        let data = {
            alertMessage: this.alertMessage,
            job: job
        }
        this.alertMessage = null;
        let html = Templates.jobFiles(data);
        return this.containerContent(html);
    }

    packaging() {
        let job = Job.find(this.params.get('id'));
        let form = new JobPackageOpForm(job);
        return this._renderPackagingForm(job, form);
    }

    _renderPackagingForm(job, form) {
        let data = {
            job: job,
            form: form
        }
        let html = Templates.jobPackaging(data);
        return this.containerContent(html);
    }

    _parseJobPackagingForm() {
        let job = Job.find(this.params.get('id'));
        let form = new JobPackageOpForm(job);
        form.parseFromDOM();
        job.packageOp.packageFormat = form.obj.packageFormat;
        job.packageOp.pluginId = form.obj.pluginId;
        job.bagItProfile = BagItProfile.find(form.obj.bagItProfileId);
        job.packageOp.outputPath = form.obj.outputPath;
        job.packageOp.packageName = form.obj.packageName;
        return [job, form]
    }

    _updatePackaging(withValidation) {
        let [job, form] = this._parseJobPackagingForm();
        if (withValidation) {
            if (job.packageOp.packageFormat == 'BagIt' && !job.bagItProfile) {
                form.obj.errors['bagItProfileId'] = Context.y18n.__("When choosing BagIt format, you must choose a BagIt profile.");
            }
            if (!job.packageOp.outputPath) {
                form.obj.errors['outputPath'] = Context.y18n.__("You must specify an output path.");
            }
            if (!job.packageOp.packageName) {
                form.obj.errors['packageName'] = Context.y18n.__("You must specify a package name.");
            }
        }
        if(!withValidation || (withValidation && !form.hasErrors())) {
            job.save();
        }
        return [job, form]
    }

    // User clicked Back button from packaging page.
    // Save work without validating.
    backToFiles() {
        this._updatePackaging(false);
        return this.files();
    }

    // User clicked Next button from packaging page.
    postPackaging() {
        // this._updatePackaging(true);
        // let job = Job.find(this.params.get('id'));
        let [job, form] = this._updatePackaging(true);
        if (form.hasErrors()) {
            // Errors. Stay on packaging screen.
            form.setErrors();
            return this._renderPackagingForm(job, form);
        }
        else if (job.packageOp.packageFormat == 'BagIt') {
            alert('Next is bag metadata form');
            return this.noContent();
        } else {
            alert('Next is upload form');
            return this.noContent();
        }
    }

    // update() {
    //     return this.containerContent('Update Job');
    // }

    list() {
        let listParams = this.paramsToHash();
        listParams.orderBy = listParams.sortBy || this.defaultOrderBy;
        listParams.sortDirection = listParams.sortOrder || this.defaultSortDirection;
        let jobs = Job.list(null, listParams);
        this.colorCodeJobs(jobs);
        let data = {
            alertMessage: this.alertMessage,
            items: jobs
        };
        let html = this.listTemplate(data);
        return this.containerContent(html);
    }

    /**
     * This adds some custom display properties to each jobs hash
     * so we can color-code the display.
     */
    colorCodeJobs(jobs) {
        for(let i=0; i < jobs.length; i++) {
            let job = Job.inflateFrom(jobs[i]);
            job.pkgDate = '-';
            job.valDate = '-';
            job.uploadDate = '-';
            if (job.packageAttempted()) {
                job.pkgColor = (job.packageSucceeded() ? 'text-success' : 'text-danger');
                job.pkgDate = dateFormat(job.packagedAt(), 'shortDate');
            }
            if (job.validationAttempted()) {
                job.valColor = (job.validateSucceeded() ? 'text-success' : 'text-danger');
                job.valDate = dateFormat(job.validatedAt(), 'shortDate');
            }
            if (job.uploadAttempted()) {
                job.uploadColor = (job.uploadSucceeded() ? 'text-success' : 'text-danger');
                job.uploadDate = dateFormat(job.uploadedAt(), 'shortDate');
            }
            jobs[i] = job;
        }
    }

    // destroy() {
    //     return this.containerContent('Destroy Job');
    // }

    postRenderCallback(fnName) {
        if (['new', 'files', 'backToFiles'].includes(fnName)) {
            let job = Job.find(this.params.get('id'));
            let helper = new JobFileUIHelper(job);
            helper.initUI();
        } else if (fnName == 'packaging') {
            let job = Job.find(this.params.get('id'));
            let helper = new JobPackagingUIHelper(job);
            helper.initUI();
        }
    }
}

module.exports.JobController = JobController;
<commit_msg>Reset form correctly after validation failure<commit_after>const { BagItProfile } = require('../../bagit/bagit_profile');
const { BaseController } = require('./base_controller');
const { Context } = require('../../core/context');
const { Job } = require('../../core/job');
const { JobFileUIHelper } = require('../common/job_file_ui_helper');
const { JobPackagingUIHelper } = require('../common/job_packaging_ui_helper');
const { JobForm } = require('../forms/job_form');
const { JobPackageOpForm } = require('../forms/job_package_op_form');
const Templates = require('../common/templates');

const typeMap = {
    limit: 'number',
    offset: 'number',
}

class JobController extends BaseController {

    constructor(params) {
        super(params, 'Jobs');
        this.typeMap = typeMap;

        this.model = Job;
        this.formClass = JobForm;
        //this.formTemplate = Templates.jobForm;
        this.listTemplate = Templates.jobList;
        this.nameProperty = 'name';
        this.defaultOrderBy = 'createdAt';
        this.defaultSortDirection = 'desc';
    }

    new() {
        let job = new Job();
        job.save();
        this.params.set('id', job.id);
        return this.files();
    }

    files() {
        let job = Job.find(this.params.get('id'));
        let data = {
            alertMessage: this.alertMessage,
            job: job
        }
        this.alertMessage = null;
        let html = Templates.jobFiles(data);
        return this.containerContent(html);
    }

    packaging() {
        let job = Job.find(this.params.get('id'));
        let form = new JobPackageOpForm(job);
        return this._renderPackagingForm(job, form);
    }

    _renderPackagingForm(job, form) {
        let data = {
            job: job,
            form: form
        }
        let html = Templates.jobPackaging(data);
        return this.containerContent(html);
    }

    _parseJobPackagingForm() {
        let job = Job.find(this.params.get('id'));
        let form = new JobPackageOpForm(job);
        form.parseFromDOM();
        job.packageOp.packageFormat = form.obj.packageFormat;
        job.packageOp.pluginId = form.obj.pluginId;
        job.bagItProfile = BagItProfile.find(form.obj.bagItProfileId);
        job.packageOp.outputPath = form.obj.outputPath;
        job.packageOp.packageName = form.obj.packageName;
        return [job, form]
    }

    _updatePackaging(withValidation) {
        let [job, form] = this._parseJobPackagingForm();
        if (withValidation) {
            if (job.packageOp.packageFormat == 'BagIt' && !job.bagItProfile) {
                form.obj.errors['bagItProfileId'] = Context.y18n.__("When choosing BagIt format, you must choose a BagIt profile.");
            }
            if (!job.packageOp.outputPath) {
                form.obj.errors['outputPath'] = Context.y18n.__("You must specify an output path.");
            }
            if (!job.packageOp.packageName) {
                form.obj.errors['packageName'] = Context.y18n.__("You must specify a package name.");
            }
        }
        if(!withValidation || (withValidation && !form.hasErrors())) {
            job.save();
        }
        return [job, form]
    }

    // User clicked Back button from packaging page.
    // Save work without validating.
    backToFiles() {
        this._updatePackaging(false);
        return this.files();
    }

    // User clicked Next button from packaging page.
    postPackaging() {
        let [job, form] = this._updatePackaging(true);
        if (form.hasErrors()) {
            // Errors. Stay on packaging screen.
            form.setErrors();
            form._listPackageFormats();
            form._listBagItProfiles();
            return this._renderPackagingForm(job, form);
        }
        else if (job.packageOp.packageFormat == 'BagIt') {
            alert('Next is bag metadata form');
            return this.noContent();
        } else {
            alert('Next is upload form');
            return this.noContent();
        }
    }

    // update() {
    //     return this.containerContent('Update Job');
    // }

    list() {
        let listParams = this.paramsToHash();
        listParams.orderBy = listParams.sortBy || this.defaultOrderBy;
        listParams.sortDirection = listParams.sortOrder || this.defaultSortDirection;
        let jobs = Job.list(null, listParams);
        this.colorCodeJobs(jobs);
        let data = {
            alertMessage: this.alertMessage,
            items: jobs
        };
        let html = this.listTemplate(data);
        return this.containerContent(html);
    }

    /**
     * This adds some custom display properties to each jobs hash
     * so we can color-code the display.
     */
    colorCodeJobs(jobs) {
        for(let i=0; i < jobs.length; i++) {
            let job = Job.inflateFrom(jobs[i]);
            job.pkgDate = '-';
            job.valDate = '-';
            job.uploadDate = '-';
            if (job.packageAttempted()) {
                job.pkgColor = (job.packageSucceeded() ? 'text-success' : 'text-danger');
                job.pkgDate = dateFormat(job.packagedAt(), 'shortDate');
            }
            if (job.validationAttempted()) {
                job.valColor = (job.validateSucceeded() ? 'text-success' : 'text-danger');
                job.valDate = dateFormat(job.validatedAt(), 'shortDate');
            }
            if (job.uploadAttempted()) {
                job.uploadColor = (job.uploadSucceeded() ? 'text-success' : 'text-danger');
                job.uploadDate = dateFormat(job.uploadedAt(), 'shortDate');
            }
            jobs[i] = job;
        }
    }

    // destroy() {
    //     return this.containerContent('Destroy Job');
    // }

    postRenderCallback(fnName) {
        if (['new', 'files', 'backToFiles'].includes(fnName)) {
            let job = Job.find(this.params.get('id'));
            let helper = new JobFileUIHelper(job);
            helper.initUI();
        } else if (fnName == 'packaging') {
            let job = Job.find(this.params.get('id'));
            let helper = new JobPackagingUIHelper(job);
            helper.initUI();
        }
    }
}

module.exports.JobController = JobController;
<|endoftext|>


<commit_before>git'use strict';
module.exports = {
  up: function(queryInterface, Sequelize) {
    return queryInterface.createTable('GameStats', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      percentComplete: {
        type: Sequelize.DECIMAL
      },
      totalWordsCompleted: {
        type: Sequelize.INTEGER
      },
      gameMistakes: {
        type: Sequelize.INTEGER
      },
      totalTimeElapsed: {
        type: Sequelize.INTEGER
      },
      userId: {
        type: Sequelize.INTEGER
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: function(queryInterface, Sequelize) {
    return queryInterface.dropTable('GameStats');
  }
};<commit_msg>Creation of DB files for User and Gamestats<commit_after>'use strict';
module.exports = {
  up: function(queryInterface, Sequelize) {
    return queryInterface.createTable('GameStats', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      percentComplete: {
        type: Sequelize.DECIMAL
      },
      totalWordsCompleted: {
        type: Sequelize.INTEGER
      },
      gameMistakes: {
        type: Sequelize.INTEGER
      },
      totalTimeElapsed: {
        type: Sequelize.INTEGER
      },
      userId: {
        type: Sequelize.INTEGER
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: function(queryInterface, Sequelize) {
    return queryInterface.dropTable('GameStats');
  }
};<|endoftext|>