<commit_before>// Node.js libraries.
var http = require("http");
var url  = require("url");
var path = require("path");
var fs   = require("fs");

// Depended libraries.
var mime = require("mime");

// Process info
var baseDir = process.cwd();

// Configurations
var logFormat    = ["client_ip", "req_method", "req_path", "req_host",
                   "resp_code", "actual_path", "error"];
var serverPort   = 8080;
var defaultFile  = ["index.html", "index.htm"];
var cacheAllowed = false;
var cacheSecond  = 3600;

// -----------------------------------------------------------------------------

var logOutputFunc = console.log;

var logger = function(log) {
  if (log instanceof Object) {
    var out = "";
    for (var i = 0; i < logFormat.length; i++) {
      if (log.hasOwnProperty(logFormat[i])) {
        out += (log[logFormat[i]] + " ");
      }
    }
    logOutputFunc(out);
  } else {
    logOutputFunc(log);
  }
};

var sendError404 = function(resp, log, error) {
  resp.statusCode = 404;
  resp.end();

  error = error || "Error: 404";

  log['resp_code'] = 404;
  log['error'] = error;
  logger(log);
};

var tryDefaultFile = function(p, serveFileFunc, req, resp, log, count) {
  count = count || 0;

  if (count < defaultFile.length) {
    fs.stat(p + "/" + defaultFile[count], function(err, stats) {
      if (stats === undefined || stats === null || !stats.isFile()) {
        // Still not found.
        tryDefaultFile(p, serveFileFunc, req, resp, log, count + 1);
      } else {
        // Found.
        serveFileFunc(p + "/" + defaultFile[count], req, resp, log);
      }
    });
  } else {
    // Finally, not found.
    sendError404(resp, log, "Found directionary, but not any default file");
  }
};

var buildFileResponseHeader = function(filePath, resp) {
  resp.setHeader('Content-Type', mime.lookup(filePath));

  if (cacheAllowed) {
    resp.setHeader('Cache-Control', 'max-age=' + cacheSecond);
  } else {
    resp.setHeader('Cache-Control', 'no-cache');
  }
}

var serveFile = function(filePath, req, resp, log) {
  var fileStream = fs.createReadStream(filePath, {
    "flags" : "r",
  });

  buildFileResponseHeader(filePath, resp);
  resp.statusCode = log['resp_code'] = 200;
  fileStream.on("data", function(d) {
    resp.write(d);
  });
  fileStream.on("end", function() {
    resp.end();
  });
  logger(log);
};

var server = http.createServer(function(req, resp) {
  var u = url.parse(req.url);
  var filePath = path.resolve(baseDir, u.pathname.slice(1));

  var log = {
    "req_path"    : u.pathname,
    "actual_path" : filePath
  };

  // Restrict in working directory.
  var relative = path.relative(baseDir, filePath);
  if (relative.length >= 2 && relative.slice(0, 2) == "..") {
    sendError404(resp, log, "Illegal path");
    return;
  }

  // Check target file. Exist, is a directory or not exist.
  fs.stat(filePath, function (err, stats) {
    if (stats === null || stats === undefined) {
      sendError404(resp, log, "Path not found");
    } else {
      if (stats.isFile()) {
        // Serve file
        serveFile(filePath, req, resp, log);
      } else if (stats.isDirectory()) {
        // Try default file
        tryDefaultFile(filePath, serveFile, req, resp, log);
      }
    }
  });
});

// Start server ----------------------------------------------------------------

var startServer = function() {
  server.listen(serverPort);
  console.log("Serving file based on: " + baseDir);
};

// Load user defined configuration ---------------------------------------------

fs.readFile(baseDir + "/setting.json", function(err, d) {
  if (err === null || err === undefined) {
    // User has his own setting.
    var setting = JSON.parse(d);

    if (setting.hasOwnProperty("port")) {
      serverPort = setting['port'];
    }

    if (setting.hasOwnProperty("cache_allowed")) {
      cacheAllowed = !!setting['cache_allowed'];
    }

    if (setting.hasOwnProperty("cache_second")
        && typeof setting['cache_second'] == 'number') {
      cacheSecond = setting['cache_second'];
    }

    if (setting.hasOwnProperty("mime")) {
      mime.define(setting['mime']);
    }

    startServer();
  } else {
    startServer();
  }
});
<commit_msg>Update master<commit_after>#!/usr/bin/env node

// Node.js libraries.
var http = require("http");
var url  = require("url");
var path = require("path");
var fs   = require("fs");

// Depended libraries.
var mime = require("mime");

// Process info
var baseDir = process.cwd();

// Configurations
var logFormat    = ["client_ip", "req_method", "req_path", "req_host",
                   "resp_code", "actual_path", "error"];
var serverPort   = 8080;
var defaultFile  = ["index.html", "index.htm"];
var cacheAllowed = false;
var cacheSecond  = 3600;

// -----------------------------------------------------------------------------

var logOutputFunc = console.log;

var logger = function(log) {
  if (log instanceof Object) {
    var out = "";
    for (var i = 0; i < logFormat.length; i++) {
      if (log.hasOwnProperty(logFormat[i])) {
        out += (log[logFormat[i]] + " ");
      }
    }
    logOutputFunc(out);
  } else {
    logOutputFunc(log);
  }
};

var sendError404 = function(resp, log, error) {
  resp.statusCode = 404;
  resp.end();

  error = error || "Error: 404";

  log['resp_code'] = 404;
  log['error'] = error;
  logger(log);
};

var tryDefaultFile = function(p, serveFileFunc, req, resp, log, count) {
  count = count || 0;

  if (count < defaultFile.length) {
    fs.stat(p + "/" + defaultFile[count], function(err, stats) {
      if (stats === undefined || stats === null || !stats.isFile()) {
        // Still not found.
        tryDefaultFile(p, serveFileFunc, req, resp, log, count + 1);
      } else {
        // Found.
        serveFileFunc(p + "/" + defaultFile[count], req, resp, log);
      }
    });
  } else {
    // Finally, not found.
    sendError404(resp, log, "Found directionary, but not any default file");
  }
};

var buildFileResponseHeader = function(filePath, resp) {
  resp.setHeader('Content-Type', mime.lookup(filePath));

  if (cacheAllowed) {
    resp.setHeader('Cache-Control', 'max-age=' + cacheSecond);
  } else {
    resp.setHeader('Cache-Control', 'no-cache');
  }
}

var serveFile = function(filePath, req, resp, log) {
  var fileStream = fs.createReadStream(filePath, {
    "flags" : "r",
  });

  buildFileResponseHeader(filePath, resp);
  resp.statusCode = log['resp_code'] = 200;
  fileStream.on("data", function(d) {
    resp.write(d);
  });
  fileStream.on("end", function() {
    resp.end();
  });
  logger(log);
};

var server = http.createServer(function(req, resp) {
  var u = url.parse(req.url);
  var filePath = path.resolve(baseDir, u.pathname.slice(1));

  var log = {
    "req_path"    : u.pathname,
    "actual_path" : filePath
  };

  // Restrict in working directory.
  var relative = path.relative(baseDir, filePath);
  if (relative.length >= 2 && relative.slice(0, 2) == "..") {
    sendError404(resp, log, "Illegal path");
    return;
  }

  // Check target file. Exist, is a directory or not exist.
  fs.stat(filePath, function (err, stats) {
    if (stats === null || stats === undefined) {
      sendError404(resp, log, "Path not found");
    } else {
      if (stats.isFile()) {
        // Serve file
        serveFile(filePath, req, resp, log);
      } else if (stats.isDirectory()) {
        // Try default file
        tryDefaultFile(filePath, serveFile, req, resp, log);
      }
    }
  });
});

// Start server ----------------------------------------------------------------

var startServer = function() {
  server.listen(serverPort);
  console.log("Serving file based on: " + baseDir);
};

// Load user defined configuration ---------------------------------------------

fs.readFile(baseDir + "/setting.json", function(err, d) {
  if (err === null || err === undefined) {
    // User has his own setting.
    var setting = JSON.parse(d);

    if (setting.hasOwnProperty("port")) {
      serverPort = setting['port'];
    }

    if (setting.hasOwnProperty("cache_allowed")) {
      cacheAllowed = !!setting['cache_allowed'];
    }

    if (setting.hasOwnProperty("cache_second")
        && typeof setting['cache_second'] == 'number') {
      cacheSecond = setting['cache_second'];
    }

    if (setting.hasOwnProperty("mime")) {
      mime.define(setting['mime']);
    }

    startServer();
  } else {
    startServer();
  }
});
<|endoftext|>


<commit_before>var $ = function (s) {
  return document.querySelector(s);
};
var $$ = function (s) {
  return document.querySelectorAll(s);
};

var l = function (string) {
    return string.toLocaleString("zh_tw");
};

var clear_message = function () {
  $$('#message-box section').forEach(function (it) { it.innerHTML = '';});
};

var change_button_state = function (s) {
  var valid_action = { 'activate' : true, 'deactivate' : false };
  if (!valid_action[s]) {
    $('#accept').setAttribute('disabled', true);
    $('#reject').setAttribute('disabled', true);
    $('#dismiss').removeAttribute('disabled');
  } else {
    $('#accept').removeAttribute('disabled');
    $('#reject').removeAttribute('disabled');
    $('#dismiss').setAttribute('disabled', true);
  }
};

var timeout = null;

var socket = io('http://vote.local');
socket.on('card attach', function(data) {
  $('#name').innerHTML = data;
  $('#message').innerHTML = '';
  // $('#name').innerHTML = data.id;
  // $('#message').innerHTML = data.type;
  change_button_state('activate');
});

socket.on('message', function(data) {
  $('#name').innerHTML = '';
  $('#message').innerHTML = l(data);
  change_button_state('deactivate');
  if (timeout !== null){
    clearTimeout(timeout);
  }
  timeout = setTimeout(clear_message, 5000);
});

socket.on('station', function (data) {
  $('#station').innerHTML = data;
});

// Connection ON
socket.on('connect', function () {
  $('#status').innerHTML = l('online');
  change_button_state('deactivate');
});
socket.on('reconnect', function () {
  $('#status').innerHTML = l('online');
  change_button_state('deactivate');
});

// Connection OFF
socket.on('disconnect', function () {
  $('#status').innerHTML = l('offline');
  change_button_state('deactivate');
  clear_message();
});

$('#accept').addEventListener('click', function (ev) {
  socket.emit('accept');
  change_button_state('deactivate');
});

$('#reject').addEventListener('click', function (ev) {
  socket.emit('reject');
  change_button_state('deactivate');
});

$('#dismiss').addEventListener('click', function (ev) {
  change_button_state('deactivate');
  clear_message();
  clearTimeout(timeout);
});

$$('button').forEach(function (it) {
  // active style
  it.addEventListener('touchstart', function (ev) { ev.preventDefault(); ev.target.className = 'active'; });
  it.addEventListener('mousedown', function (ev) { ev.preventDefault(); ev.target.className = 'active'; });

  // normal style
  it.addEventListener('touchend', function (ev) { ev.preventDefault(); ev.target.className = ''; });
  it.addEventListener('mouseup', function (ev) { ev.preventDefault(); ev.target.className = ''; });
});
<commit_msg>fix bug when string is null<commit_after>var $ = function (s) {
  return document.querySelector(s);
};
var $$ = function (s) {
  return document.querySelectorAll(s);
};

var l = function (string) {
    if (string) {
        return string.toLocaleString("zh_tw");
    } else {
        return string;
    }
};

var clear_message = function () {
  $$('#message-box section').forEach(function (it) { it.innerHTML = '';});
};

var change_button_state = function (s) {
  var valid_action = { 'activate' : true, 'deactivate' : false };
  if (!valid_action[s]) {
    $('#accept').setAttribute('disabled', true);
    $('#reject').setAttribute('disabled', true);
    $('#dismiss').removeAttribute('disabled');
  } else {
    $('#accept').removeAttribute('disabled');
    $('#reject').removeAttribute('disabled');
    $('#dismiss').setAttribute('disabled', true);
  }
};

var timeout = null;

var socket = io('http://vote.local');
socket.on('card attach', function(data) {
  $('#name').innerHTML = data;
  $('#message').innerHTML = '';
  // $('#name').innerHTML = data.id;
  // $('#message').innerHTML = data.type;
  change_button_state('activate');
});

socket.on('message', function(data) {
  $('#name').innerHTML = '';
  $('#message').innerHTML = l(data);
  change_button_state('deactivate');
  if (timeout !== null){
    clearTimeout(timeout);
  }
  timeout = setTimeout(clear_message, 5000);
});

socket.on('station', function (data) {
  $('#station').innerHTML = data;
});

// Connection ON
socket.on('connect', function () {
  $('#status').innerHTML = l('online');
  change_button_state('deactivate');
});
socket.on('reconnect', function () {
  $('#status').innerHTML = l('online');
  change_button_state('deactivate');
});

// Connection OFF
socket.on('disconnect', function () {
  $('#status').innerHTML = l('offline');
  change_button_state('deactivate');
  clear_message();
});

$('#accept').addEventListener('click', function (ev) {
  socket.emit('accept');
  change_button_state('deactivate');
});

$('#reject').addEventListener('click', function (ev) {
  socket.emit('reject');
  change_button_state('deactivate');
});

$('#dismiss').addEventListener('click', function (ev) {
  change_button_state('deactivate');
  clear_message();
  clearTimeout(timeout);
});

$$('button').forEach(function (it) {
  // active style
  it.addEventListener('touchstart', function (ev) { ev.preventDefault(); ev.target.className = 'active'; });
  it.addEventListener('mousedown', function (ev) { ev.preventDefault(); ev.target.className = 'active'; });

  // normal style
  it.addEventListener('touchend', function (ev) { ev.preventDefault(); ev.target.className = ''; });
  it.addEventListener('mouseup', function (ev) { ev.preventDefault(); ev.target.className = ''; });
});
<|endoftext|>


<commit_before>// Invoked by: SNS Subscription
// Returns: Error or status message
//
// Recieves notifications from the CI process, generally as a result of
// CodeBuild status changes. The messages are sent to the Slack Message Relay
// SNS topic in order to be sent to Slack. All messages handled by this function
// are sent to the #ops-builds (this could change at some point).
//
// CI Status message can be sent from several sources. The GitHub event handler
// will send messages after a build has started, and includes data about the
// GitHub event that triggered the build, and the build itself.
// eg { event: {...}, build: {...} }

const AWS = require('aws-sdk');

const sns = new AWS.SNS({ apiVersion: '2010-03-31' });

const SLACK_CHANNEL = '#ops-builds';
const SLACK_ICON = ':ops-codebuild:';
const SLACK_USERNAME = 'AWS CodeBuild';

function attachmentsForGitHubEvent(gitHubEvent, gitHubBuild) {
    const repo = gitHubEvent.repository.full_name;
    const sha = gitHubEvent.after || gitHubEvent.pull_request.head.sha;
    const sha7 = sha.substring(0, 7);
    const branch = gitHubEvent.pull_request ? gitHubEvent.pull_request.head.ref : gitHubEvent.ref.replace(/refs\/heads\//, '');

    const { arn } = gitHubBuild;
    const region = arn.split(':')[3];
    const buildId = arn.split('/')[1];

    const commitUrl = `https://github.com/${repo}/commit/${sha7}`;
    const buildUrl = `https://${region}.console.aws.amazon.com/codebuild/home#/builds/${buildId}/view/new`;

    const attachment = {
        ts: Math.floor(Date.parse(gitHubBuild.startTime) / 1000),
        footer: branch,
        color: 'warning',
        mrkdwn_in: ['text'],
    };

    if (gitHubEvent.pull_request) {
        const pr = gitHubEvent.pull_request;
        const action = gitHubEvent.action.charAt(0).toUpperCase() + gitHubEvent.action.slice(1);

        attachment.fallback = `Building ${repo} #${pr.number} with commit ${sha7}`;
        attachment.title = `Building <${buildUrl}|${repo}> with commit <${commitUrl}|${sha7}>`;
        attachment.text = `${action} <${pr.html_url}|#${pr.number}> ${pr.title} – ${pr.user.login}`;
    } else {
        attachment.fallback = `Building ${repo}:${branch} with commit ${sha7}`;
        attachment.title = `Building <${buildUrl}|${repo}:${branch}> with commit <${commitUrl}|${sha7}>`;

        const compareUrl = `https://github.com/${repo}/compare/${gitHubEvent.before}...${gitHubEvent.after}`;

        const text = [];
        text.push(`<${compareUrl}|${gitHubEvent.commits.length} new commits> pushed by ${gitHubEvent.pusher.name}`);

        gitHubEvent.commits.forEach((commit) => {
            text.push(`<${commit.url}|\`${commit.id.substring(0, 7)}\`> ${commit.author.username}:${commit.message}`);
        });

        attachment.text = text.join('\n');
    }

    return [attachment];
}

function attachmentsForCiCallback(ciResult) {
    const repo = ciResult.prxRepo;
    const sha = ciResult.prxCommit;
    const sha7 = sha.substring(0, 7);

    const arn = ciResult.buildArn;
    const region = arn.split(':')[3];
    const buildId = arn.split('/')[1];

    const commitUrl = `https://github.com/${repo}/commit/${sha7}`;
    const buildUrl = `https://${region}.console.aws.amazon.com/codebuild/home#/builds/${buildId}/view/new`;

    const attachment = {
        ts: Math.floor(Date.now() / 1000),
        // footer: branch,
        mrkdwn_in: ['text'],
    };

    let extra = '';

    if (ciResult.prxGithubPr) {
        const num = ciResult.prxGithubPr;
        const prUrl = `https://github.com/${repo}/pull/${num}`;
        extra = ` <${prUrl}|#${num}>`;
    } else {
        // This assumes that anything other than PR is master, which, for the
        // time being, is true. But that may not always be the case
        extra = ':master';
    }

    if (ciResult.success) {
        attachment.color = 'good';
        attachment.fallback = `Built ${repo}${extra} with commit ${sha7}`;
        attachment.title = `Built <${buildUrl}|${repo}>${extra} with commit <${commitUrl}|${sha7}>`;

        if (ciResult.prxGithubPr) {
            const num = ciResult.prxGithubPr;
            const prUrl = `https://github.com/${repo}/pull/${num}`;
            attachment.text = `<${prUrl}|${prUrl}>`;
        } else if (ciResult.prxEcrTag) {
            const ecrUrl = `https://console.aws.amazon.com/ecs/home?region=${ciResult.prxEcrRegion}#/repositories/${repo.split('/')[1]}`;
            attachment.text = `Docker image pushed to <${ecrUrl}|ECR> with tag \`${sha7}\``;
        } else {
            attachment.text = 'Tktktk Lambda deploy';
        }
    } else {
        attachment.color = 'danger';
        attachment.fallback = `Failed to build ${repo}${extra} with commit ${sha7}`;
        attachment.title = `Failed to build <${buildUrl}|${repo}>${extra} with commit <${commitUrl}|${sha7}>`;
        attachment.text = `> _${ciResult.reason}_`;
    }

    return [attachment];
}

// This event argument is the standard Lambda execution event data
function messageForEvent(event) {
    const noteJson = event.Records[0].Sns.Message;
    const note = JSON.parse(noteJson);

    let attachments;

    // Note is either data related to a GitHub event, or the result of a CI
    // build. They are handled differently. A GitHub event will have an `event`
    // and `build` property.
    if (note.event && note.build) {
        attachments = attachmentsForGitHubEvent(note.event, note.build);
    } else {
        // If the object didn't look like it came from GitHub assume it came
        // from CI. CI objects have a `callback` wrapper property.
        attachments = attachmentsForCiCallback(note.callback);
    }

    return {
        channel: SLACK_CHANNEL,
        username: SLACK_USERNAME,
        icon_emoji: SLACK_ICON,
        attachments,
    };
}

function main(event, context, callback) {
    const message = messageForEvent(event);

    const messageJson = JSON.stringify(message);

    sns.publish({
        TopicArn: process.env.SLACK_MESSAGE_RELAY_TOPIC_ARN,
        Message: messageJson,
    }, (err) => {
        if (err) {
            callback(err);
        } else {
            callback(null);
        }
    });
}

exports.handler = (event, context, callback) => {
    try {
        main(event, context, callback);
    } catch (e) {
        callback(e);
    }
};
<commit_msg>Make CI Slack notifications more intuitive<commit_after>// Invoked by: SNS Subscription
// Returns: Error or status message
//
// Recieves notifications from the CI process, generally as a result of
// CodeBuild status changes. The messages are sent to the Slack Message Relay
// SNS topic in order to be sent to Slack. All messages handled by this function
// are sent to the #ops-builds (this could change at some point).
//
// CI Status message can be sent from several sources. The GitHub event handler
// will send messages after a build has started, and includes data about the
// GitHub event that triggered the build, and the build itself.
// eg { event: {...}, build: {...} }

const AWS = require('aws-sdk');

const sns = new AWS.SNS({ apiVersion: '2010-03-31' });

const SLACK_CHANNEL = '#ops-builds';
const SLACK_ICON = ':ops-codebuild:';
const SLACK_USERNAME = 'AWS CodeBuild';

function attachmentsForGitHubEvent(gitHubEvent, gitHubBuild) {
    const repo = gitHubEvent.repository.full_name;
    const sha = gitHubEvent.after || gitHubEvent.pull_request.head.sha;
    const sha7 = sha.substring(0, 7);
    const branch = gitHubEvent.pull_request ? gitHubEvent.pull_request.head.ref : gitHubEvent.ref.replace(/refs\/heads\//, '');

    const { arn } = gitHubBuild;
    const region = arn.split(':')[3];
    const buildId = arn.split('/')[1];

    const commitUrl = `https://github.com/${repo}/commit/${sha7}`;
    const buildUrl = `https://${region}.console.aws.amazon.com/codebuild/home#/builds/${buildId}/view/new`;

    const attachment = {
        ts: Math.floor(Date.parse(gitHubBuild.startTime) / 1000),
        footer: branch,
        color: 'warning',
        mrkdwn_in: ['text'],
    };

    if (gitHubEvent.pull_request) {
        const pr = gitHubEvent.pull_request;
        const action = gitHubEvent.action.charAt(0).toUpperCase() + gitHubEvent.action.slice(1);

        attachment.fallback = `Building ${repo} #${pr.number} with commit ${sha7}`;
        attachment.title = `<${buildUrl}|Building> ${repo} with commit <${commitUrl}|${sha7}>`;
        attachment.text = `${action} <${pr.html_url}|#${pr.number}> ${pr.title} – ${pr.user.login}`;
    } else {
        attachment.fallback = `Building ${repo}:${branch} with commit ${sha7}`;
        attachment.title = `<${buildUrl}|Building> ${repo}:${branch} with commit <${commitUrl}|${sha7}>`;

        const compareUrl = `https://github.com/${repo}/compare/${gitHubEvent.before}...${gitHubEvent.after}`;

        const text = [];
        text.push(`<${compareUrl}|${gitHubEvent.commits.length} new commits> pushed by ${gitHubEvent.pusher.name}`);

        gitHubEvent.commits.forEach((commit) => {
            text.push(`<${commit.url}|\`${commit.id.substring(0, 7)}\`> ${commit.author.username}:${commit.message}`);
        });

        attachment.text = text.join('\n');
    }

    return [attachment];
}

function attachmentsForCiCallback(ciResult) {
    const repo = ciResult.prxRepo;
    const sha = ciResult.prxCommit;
    const sha7 = sha.substring(0, 7);

    const arn = ciResult.buildArn;
    const region = arn.split(':')[3];
    const buildId = arn.split('/')[1];

    const commitUrl = `https://github.com/${repo}/commit/${sha7}`;
    const buildUrl = `https://${region}.console.aws.amazon.com/codebuild/home#/builds/${buildId}/view/new`;

    const attachment = {
        ts: Math.floor(Date.now() / 1000),
        // footer: branch,
        mrkdwn_in: ['text'],
    };

    let extra = '';

    if (ciResult.prxGithubPr) {
        const num = ciResult.prxGithubPr;
        const prUrl = `https://github.com/${repo}/pull/${num}`;
        extra = ` <${prUrl}|#${num}>`;
    } else {
        // This assumes that anything other than PR is master, which, for the
        // time being, is true. But that may not always be the case
        // TODO This needs to be determined from the event info
        extra = ':master';
    }

    if (ciResult.success) {
        attachment.color = 'good';
        attachment.fallback = `Built ${repo}${extra} with commit ${sha7}`;
        attachment.title = `Built <${buildUrl}|${repo}>${extra} with commit <${commitUrl}|${sha7}>`;

        if (ciResult.prxGithubPr) {
            const num = ciResult.prxGithubPr;
            const prUrl = `https://github.com/${repo}/pull/${num}`;
            attachment.text = `<${prUrl}|${prUrl}>`;
        } else if (ciResult.prxEcrTag) {
            const ecrUrl = `https://console.aws.amazon.com/ecs/home?region=${ciResult.prxEcrRegion}#/repositories/${repo.split('/')[1]}`;
            attachment.text = `Docker image pushed to <${ecrUrl}|ECR> with tag \`${sha7}\``;
        } else {
            attachment.text = 'Tktktk Lambda deploy';
        }
    } else {
        attachment.color = 'danger';
        attachment.fallback = `Failed to build ${repo}${extra} with commit ${sha7}`;
        attachment.title = `Failed to build <${buildUrl}|${repo}>${extra} with commit <${commitUrl}|${sha7}>`;
        attachment.title = `Failed to <${buildUrl}|build> ${repo}${extra} with commit <${commitUrl}|${sha7}>`;
        attachment.text = `> _${ciResult.reason}_`;
    }

    return [attachment];
}

// This event argument is the standard Lambda execution event data
function messageForEvent(event) {
    const noteJson = event.Records[0].Sns.Message;
    const note = JSON.parse(noteJson);

    let attachments;

    // Note is either data related to a GitHub event, or the result of a CI
    // build. They are handled differently. A GitHub event will have an `event`
    // and `build` property.
    if (note.event && note.build) {
        attachments = attachmentsForGitHubEvent(note.event, note.build);
    } else {
        // If the object didn't look like it came from GitHub assume it came
        // from CI. CI objects have a `callback` wrapper property.
        attachments = attachmentsForCiCallback(note.callback);
    }

    return {
        channel: SLACK_CHANNEL,
        username: SLACK_USERNAME,
        icon_emoji: SLACK_ICON,
        attachments,
    };
}

function main(event, context, callback) {
    const message = messageForEvent(event);

    const messageJson = JSON.stringify(message);

    sns.publish({
        TopicArn: process.env.SLACK_MESSAGE_RELAY_TOPIC_ARN,
        Message: messageJson,
    }, (err) => {
        if (err) {
            callback(err);
        } else {
            callback(null);
        }
    });
}

exports.handler = (event, context, callback) => {
    try {
        main(event, context, callback);
    } catch (e) {
        callback(e);
    }
};
<|endoftext|>


<commit_before>"use strict";

let path = require("path");
let shell = require("shelljs");
let fileUrl = require("file-url");
let Nightmare = require("nightmare");

// Get list of names to process
let names = [];
if (process.argv.length == 2) {
    // Default to all Elm files
    names = shell.ls("*.elm").map(function(filename) {
        return path.basename(filename, ".elm");
    });
} else {
    // Otherwise, use specified names
    names = process.argv.slice(2);
}

// Create output directory if necessary
if (!shell.test("-d", "output")) {
    shell.mkdir("output");
}

// Loop through each input
names.forEach(function(name) {
    let elmFilename = name + ".elm";
    let htmlFilename = "output/" + name + ".html";
    // Compile Elm file to HTML
    if (shell.exec("elm make --output " + htmlFilename + " " + elmFilename).code == 0) {
        // Render HTML to PNG
        let nightmare = Nightmare({show: false});
        let dimensions = {x: 0, y: 0, width: 320, height : 240};
        let pngFilename = "output/" + name + ".png";
        let url = fileUrl(htmlFilename);
        nightmare.viewport(1024, 768).goto(url).screenshot(pngFilename, dimensions).end().then(function (result) {
            console.log("Rendered " + pngFilename);
        }).catch(function (error) {
            console.error("Render failed:", error);
        });
    } else {
        shell.echo("Elm compilation failed");
    }
})
<commit_msg>Tweak image build script formatting/organization<commit_after>"use strict";

let path = require("path");
let shell = require("shelljs");
let fileUrl = require("file-url");
let Nightmare = require("nightmare");

// Get list of names to process
let names = [];
if (process.argv.length == 2) {
    // Default to all Elm files
    names = shell.ls("*.elm").map(function(filename) {
        return path.basename(filename, ".elm");
    });
} else {
    // Otherwise, use specified names
    names = process.argv.slice(2);
}

// Create output directory if necessary
if (!shell.test("-d", "output")) {
    shell.mkdir("output");
}

// Loop through each input
names.forEach(function(name) {
    let elmFilename = name + ".elm";
    let htmlFilename = "output/" + name + ".html";
    let elmMakeCommand = "elm make --output " + htmlFilename + " " + elmFilename;
    // Compile Elm file to HTML
    if (shell.exec(elmMakeCommand).code == 0) {
        // Render HTML to PNG
        let nightmare = Nightmare({show: false}).viewport(1024, 768);
        let pngFilename = "output/" + name + ".png";
        let dimensions = {x: 0, y: 0, width: 320, height : 240};
        let url = fileUrl(htmlFilename);
        nightmare.goto(url).screenshot(pngFilename, dimensions).end().then(function (result) {
            console.log("Rendered " + pngFilename);
        }).catch(function (error) {
            console.error("Render failed:", error);
        });
    } else {
        shell.echo("Elm compilation failed");
    }
})
<|endoftext|>


<commit_before>import angular from 'angular';

export default angular
.module('SirTrevor', [])
    .provider('SirTrevor', function() {
        this.$get = function() {
            return window.SirTrevor;
        };
        angular.extend(this, window.SirTrevor);
    })
    .provider('SirTrevorOptions', function() {
        var options = {
            blockTypes: ['Text'],
            transform: {
                get: function(block) {
                    return {
                        type: block.blockStorage.type,
                        data: block.blockStorage.data
                    };
                },
                set: function(block) {
                    return {
                        type: block.type,
                        data: block.data
                    };
                }
            }
        };
        this.$get = function() {
            return options;
        };
        this.$extend = function(opts) {
            angular.extend(options, opts);
        };
        this.$set = function(opts) {
            options = opts;
        };
    })
    .directive('ngSirTrevor', ['SirTrevor', 'SirTrevorOptions', function(SirTrevor, options) {
        var directive = {
            template: function(element, attr) {
                var str = '<textarea class="sir-trevor" name="content"></textarea>';
                // sir trevor needs a parent `form` tag.
                if (!element.parent('form').length) {
                    str = '<form>' + str + '</form>';
                }
                return str;
            },
            scope: {
                'editor': '=stModel',
                'onChange': '=stChange',
                'params': '=stParams'
            },
            link: function (scope, element, attrs) {
                var opts = angular.copy(options);
                angular.extend(opts, scope.params);
                opts.el = $(element.find('textarea'));
                scope.editor = new SirTrevor.Editor(opts);
                scope.editor.get = function() {
                    var list = [];
                    // sort blocks by index.
                    scope.editor.blocks.sort(function(a, b) {
                        return (a.$el.index() - b.$el.index());
                    });
                    angular.forEach(scope.editor.blocks, function(block) {
                        scope.editor.saveBlockStateToStore(block);
                        list.push(opts.transform.get(block));
                    });
                    return list;
                };
                scope.editor.set = function(list) {
                    var item;
                    angular.forEach(list, function(block) {
                        item = opts.transform.set(block);
                        scope.editor.createBlock(item.type, item.data);
                    });
                };

                scope.editor.clear = function() {
                    angular.forEach(scope.editor.blocks, function(block) {
                        block.remove();
                    });
                    scope.editor.dataStore.data = [];
                };

                $('.st-text-block').on('keyup', scope.onChange);

                // @TODO: investigate how to better `digest` out of $scope  variables.
                //scope.$watchCollection('editor.blocks', function(blocks) {
                //     var list = [];
                //     _.each(blocks, function(block) {
                //         list.push(scope.editor.get(block));
                //     });
                //     scope.model = list;
                //});
            }
        };
        return directive;
    }]);

<commit_msg>LBSD-1614<commit_after>import angular from 'angular';

export default angular
.module('SirTrevor', [])
    .provider('SirTrevor', function() {
        this.$get = function() {
            return window.SirTrevor;
        };
        angular.extend(this, window.SirTrevor);
    })
    .provider('SirTrevorOptions', function() {
        var options = {
            blockTypes: ['Text'],
            transform: {
                get: function(block) {
                    return {
                        type: block.blockStorage.type,
                        data: block.blockStorage.data
                    };
                },
                set: function(block) {
                    return {
                        type: block.type,
                        data: block.data
                    };
                }
            }
        };
        this.$get = function() {
            return options;
        };
        this.$extend = function(opts) {
            angular.extend(options, opts);
        };
        this.$set = function(opts) {
            options = opts;
        };
    })
    .directive('ngSirTrevor', ['SirTrevor', 'SirTrevorOptions', function(SirTrevor, options) {
        var directive = {
            template: function(element, attr) {
                var str = '<textarea class="sir-trevor" name="content"></textarea>';
                // sir trevor needs a parent `form` tag.
                if (!element.parent('form').length) {
                    str = '<form>' + str + '</form>';
                }
                return str;
            },
            scope: {
                'editor': '=stModel',
                'onChange': '=stChange',
                'params': '=stParams'
            },
            link: function (scope, element, attrs) {
                var opts = angular.copy(options);
                angular.extend(opts, scope.params);
                opts.el = $(element.find('textarea'));
                scope.editor = new SirTrevor.Editor(opts);
                scope.editor.get = function() {
                    var list = [];
                    // sort blocks by index.
                    scope.editor.blocks.sort(function(a, b) {
                        return (a.$el.index() - b.$el.index());
                    });
                    angular.forEach(scope.editor.blocks, function(block) {
                        scope.editor.saveBlockStateToStore(block);
                        list.push(opts.transform.get(block));
                    });
                    return list;
                };
                scope.editor.set = function(list) {
                    var item;
                    angular.forEach(list, function(block) {
                        item = opts.transform.set(block);
                        scope.editor.createBlock(item.type, item.data);
                    });
                };

                scope.editor.clear = function() {
                    angular.forEach(scope.editor.blocks, function(block) {
                        block.remove();
                    });
                    scope.editor.dataStore.data = [];
                };

                element.on('keyup', scope.onChange);

                // @TODO: investigate how to better `digest` out of $scope  variables.
                //scope.$watchCollection('editor.blocks', function(blocks) {
                //     var list = [];
                //     _.each(blocks, function(block) {
                //         list.push(scope.editor.get(block));
                //     });
                //     scope.model = list;
                //});
            }
        };
        return directive;
    }]);

<|endoftext|>


<commit_before>const exam = require('./exam')

describe('generating exams', () => {
  studend1 = {q1: 'a', q2: 'b', q3: 'b', q4: 'b', q5: 'b'}
  studend2 = {q1: 'c', q2: 'b', q3: 'a', q4: 'c', q5: 'd'}
  weight =   {q1:  2 , q2:  2 , q3:  2 , q4:  2 , q5:  2 }
  answer =   {q1: 'a', q2: 'b', q3: 'a', q4: 'c', q5: 'd'}

  students = [

    {"student": "Sicrano", "grade": 5},
    {"student": "Beltrano", "grade": 7},
    {"student": "Fulano", "grade": 10},
  ]

  test('generating exams studend1', () => {
    expect(exam.grade(studend1, weight, answer)).toBe(4)
  })

  test('generating exams studend2', () => {
    expect(exam.grade(studend2, weight, answer)).toBe(8)
  })

  test('generating avg of all studants', () => {
    expect(exam.avg(students)).toBe(7.333333333333333)
  })

  test('generating min grade of studants', () => {
    expect(exam.min(students)).toBe(5)
  })

  test('generating max grade of studants', () => {
    expect(exam.max(students)).toBe(10)
  })

  test('generating lt grade of studants', () => {
    expect(exam.lt(students, 6)).toEqual([5])
  })

  test('generating lt grade of studants', () => {
    expect(exam.gt(students, 6)).toEqual([7, 10])
  })
})
<commit_msg>Update exam.test.js<commit_after>const exam = require('./exam')

describe('generating exams', () => {
  studend1 = {q1: 'a', q2: 'b', q3: 'b', q4: 'b', q5: 'b'}
  studend2 = {q1: 'c', q2: 'b', q3: 'a', q4: 'c', q5: 'd'}
  weight =   {q1:  2 , q2:  2 , q3:  2 , q4:  2 , q5:  2 }
  answer =   {q1: 'a', q2: 'b', q3: 'a', q4: 'c', q5: 'd'}

  students = [
    {"student": "Fulano", "grade": 10},
    {"student": "Sicrano", "grade": 5},
    {"student": "Beltrano", "grade": 7}

  ]

  test('generating exams studend1', () => {
    expect(exam.grade(studend1, weight, answer)).toBe(4)
  })

  test('generating exams studend2', () => {
    expect(exam.grade(studend2, weight, answer)).toBe(8)
  })

  test('generating avg of all studants', () => {
    expect(exam.avg(students)).toBe(7.333333333333333)
  })

  test('generating min grade of studants', () => {
    expect(exam.min(students)).toBe(5)
  })

  test('generating min grade of studants', () => {
    expect(exam.min(students, 2)).toEqual([5, 7])
  })

  test('generating max grade of studants', () => {
    expect(exam.max(students)).toBe(10)
  })

  test('generating max grade of studants', () => {
    expect(exam.max(students, 2)).toEqual([10, 7])
  })

  test('generating lt grade of studants', () => {
    expect(exam.lt(students, 6)).toEqual([5])
  })

  test('generating gt grade of studants', () => {
    expect(exam.gt(students, 6)).toEqual([7, 10])
  })
})
<|endoftext|>


<commit_before>/*
This file is part of the Juju GUI, which lets users view and manage Juju
environments within a graphical interface (https://launchpad.net/juju-gui).
Copyright (C) 2016 Canonical Ltd.

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License version 3, as published by
the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
General Public License for more details.

You should have received a copy of the GNU Affero General Public License along
with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

'use strict';

const BudgetTable = React.createClass({
  propTypes: {
    acl: React.PropTypes.object.isRequired,
    allocationEditable: React.PropTypes.bool,
    charmsGetById: React.PropTypes.func,
    extraInfo: React.PropTypes.object,
    listPlansForCharm: React.PropTypes.func,
    parseTermId: React.PropTypes.func,
    plansEditable: React.PropTypes.bool,
    services: React.PropTypes.array.isRequired,
    showExtra: React.PropTypes.bool,
    showTerms: React.PropTypes.func.isRequired,
    withPlans: React.PropTypes.bool
  },

  /**
   Generate the list of services.

   @method _generateServices
   @returns {Array} The list of services.
  */
  _generateServices: function() {
    return this.props.services.map((service, i) => {
      return (
        <juju.components.BudgetTableRow
          acl={this.props.acl}
          key={i}
          allocationEditable={this.props.allocationEditable}
          charmsGetById={this.props.charmsGetById}
          extraInfo={
            this.props.extraInfo && this.props.extraInfo[service.get('id')]}
          listPlansForCharm={this.props.listPlansForCharm}
          parseTermId={this.props.parseTermId}
          plansEditable={this.props.plansEditable}
          service={service}
          showExtra={this.props.showExtra}
          showTerms={this.props.showTerms}
          withPlans={this.props.withPlans} />);
    });
  },

  /**
    Generate plan headers.

    @method _generatePlanHeaders
    @returns {Object} The plan headers markup.
  */
  _generatePlanHeaders: function() {
    if (!this.props.withPlans) {
      return;
    }
    const plansEditable = this.props.plansEditable;
    return (

          Details

          Usage

          Allocation

          Spend

    );
  },

  render: function() {
    return (

            Name

            Units

          {this._generatePlanHeaders()}

        {this._generateServices()}

    );
  }

});

YUI.add('budget-table', function() {
  juju.components.BudgetTable = BudgetTable;
}, '0.1.0', {
  requires: [
    'budget-table-row'
  ]
});
<commit_msg>Update BudgetTable to use es6 class.<commit_after>/*
This file is part of the Juju GUI, which lets users view and manage Juju
environments within a graphical interface (https://launchpad.net/juju-gui).
Copyright (C) 2016 Canonical Ltd.

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License version 3, as published by
the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
General Public License for more details.

You should have received a copy of the GNU Affero General Public License along
with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

'use strict';

class BudgetTable extends React.Component {
  /**
   Generate the list of services.

   @method _generateServices
   @returns {Array} The list of services.
  */
  _generateServices() {
    return this.props.services.map((service, i) => {
      return (
        <juju.components.BudgetTableRow
          acl={this.props.acl}
          key={i}
          allocationEditable={this.props.allocationEditable}
          charmsGetById={this.props.charmsGetById}
          extraInfo={
            this.props.extraInfo && this.props.extraInfo[service.get('id')]}
          listPlansForCharm={this.props.listPlansForCharm}
          parseTermId={this.props.parseTermId}
          plansEditable={this.props.plansEditable}
          service={service}
          showExtra={this.props.showExtra}
          showTerms={this.props.showTerms}
          withPlans={this.props.withPlans} />);
    });
  }

  /**
    Generate plan headers.

    @method _generatePlanHeaders
    @returns {Object} The plan headers markup.
  */
  _generatePlanHeaders() {
    if (!this.props.withPlans) {
      return;
    }
    const plansEditable = this.props.plansEditable;
    return (

          Details

          Usage

          Allocation

          Spend

    );
  }

  render() {
    return (

            Name

            Units

          {this._generatePlanHeaders()}

        {this._generateServices()}

    );
  }
};

BudgetTable.propTypes = {
  acl: React.PropTypes.object.isRequired,
  allocationEditable: React.PropTypes.bool,
  charmsGetById: React.PropTypes.func,
  extraInfo: React.PropTypes.object,
  listPlansForCharm: React.PropTypes.func,
  parseTermId: React.PropTypes.func,
  plansEditable: React.PropTypes.bool,
  services: React.PropTypes.array.isRequired,
  showExtra: React.PropTypes.bool,
  showTerms: React.PropTypes.func.isRequired,
  withPlans: React.PropTypes.bool
};

YUI.add('budget-table', function() {
  juju.components.BudgetTable = BudgetTable;
}, '0.1.0', {
  requires: [
    'budget-table-row'
  ]
});
<|endoftext|>


<commit_before>import React from 'react';
import info from '../data/info';
import fuzzyFind from '../logic/fuzzyFind';
import Header from './Header';
import Searchbar from './searchbar';
import Results from './results';

class MainComponent extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			input: ''
		}
	   	this.query = this.query.bind(this)
	}

	query(e) {
		this.setState({input: e.target.value})
	}

	render() {
        const data = info.map((item, idx) => {
            let result = fuzzyFind(item, this.state.input)
            if (result && this.state.input) return
{result}

        })
		return (

                <Searchbar
                    query={this.query}
                    value={this.state.input}
                />
                <Results
                    data={data}
                />

	    )
	}
}

MainComponent.proptypes = {
	query: React.PropTypes.func.isRequired,
	value: React.PropTypes.string.isRequired,
	data: React.PropTypes.array.isRequired,
	key: React.PropTypes.number.isRequired,
}

export default MainComponent;
<commit_msg>Update main-component.js<commit_after>import React from 'react';
import info from '../data/info';
import fuzzyFind from '../logic/fuzzyFind';
import header from './Header';
import Searchbar from './searchbar';
import Results from './results';

class MainComponent extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			input: ''
		}
	   	this.query = this.query.bind(this)
	}

	query(e) {
		this.setState({input: e.target.value})
	}

	render() {
        const data = info.map((item, idx) => {
            let result = fuzzyFind(item, this.state.input)
            if (result && this.state.input) return
{result}

        })
		return (

                <Searchbar
                    query={this.query}
                    value={this.state.input}
                />
                <Results
                    data={data}
                />

	    )
	}
}

MainComponent.proptypes = {
	query: React.PropTypes.func.isRequired,
	value: React.PropTypes.string.isRequired,
	data: React.PropTypes.array.isRequired,
	key: React.PropTypes.number.isRequired,
}

export default MainComponent;
<|endoftext|>


<commit_before>/*global Handlebars:true, $: true */
/**
 * @license MIT License
 *
 * Copyright (c) 2015 Tetsuharu OHZEKI <saneyuki.snyk@gmail.com>
 * Copyright (c) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

import AppActionCreator from '../../intent/action/AppActionCreator';
import UIActionCreator from '../../intent/action/UIActionCreator';

export default class SidebarViewController {

    /**
     *  @constructor
     *  @param  {DomainState}   domain
     *  @param  {Element}   element
     */
    constructor(domain, element) {
        if (!element) {
            throw new Error();
        }

        /** @type   {Element}   */
        this._element = element;

        /*eslint-disable valid-jsdoc */
        /** @type   {Rx.IDisposable}  */
        this._disposeSignout = AppActionCreator.getDispatcher().signout.subscribe(() => {
            this.clearAllNetworks();
            this.showEmptinesse();
        });

        /** @type   {Rx.IDisposable}  */
        this._disposeRenderNetworks = AppActionCreator.getDispatcher().renderNetworksInView.subscribe((networks) => {
            this.hideEmptinesse();
            this.renderNetworks(networks);
        });

        /** @type   {Rx.IDisposable}  */
        this._disposeSelectChannel = UIActionCreator.getDispatcher().selectChannel.subscribe((channelId) => {
            this.selectChannel(channelId);
        });

        /** @type   {Rx.IDisposable}  */
        this._disposeAddedNetwork = domain.networkSet.addedStream().subscribe((network) => {
            this.addNetwork(network);
        });
        /*eslint-enable */

        element.addEventListener('click', this);
    }

    /**
     *  @param  {Event} aEvent
     *  @return {void}
     */
    handleEvent(aEvent) {
        switch (aEvent.type) {
            case 'click':
                this.onClick(aEvent);
        }
    }

    /**
     *  @param  {Event} aEvent
     *  @return {void}
     */
    onClick(aEvent) {
        const target = aEvent.target;
        if (!target.matches('.js-sidebar-channel, .js-sidebar-channel > :not(.close)')) {
            return;
        }

        const channelId = parseInt(target.getAttribute('data-id'), 10);
        UIActionCreator.selectChannel(channelId);
    }

    /**
     *  @return {void}
     */
    clearAllNetworks() {
        let element = this._element.querySelector('.networks');
        element.innerHTML = '';
    }

    /**
     *  @param  {Network}   network
     *  @return {void}
     */
    addNetwork(network) {
        this.hideEmptinesse();
        this.appendNetworks([network]);

        const channelList = network.getChannelList();
        const lastId = channelList[channelList.length - 1].id;
        UIActionCreator.selectChannel(lastId);
    }

    /**
     *  @return {void}
     */
    showEmptinesse() {
        let element = this._element.querySelector('.empty');
        element.style.display = 'block';
    }

    /**
     *  @return {void}
     */
    hideEmptinesse() {
        let element = this._element.querySelector('.empty');
        element.style.display = 'none';
    }

    /**
     *  @param  {Array<Network>} networks
     *  @return {void}
     */
    renderNetworks(networks) {
        const element = this._element.querySelector('.networks');
        const html = Handlebars.templates.network({
            networks,
        });

        element.innerHTML = html;
    }

    /**
     *  @param  {Array<Network>} networks
     *  @return {void}
     */
    appendNetworks(networks) {
        const element = this._element.querySelector('.networks');
        const html = Handlebars.templates.network({
            networks,
        });

        element.innerHTML = element.innerHTML + html;
    }

    /**
     *  @param  {number}    id
     *  @return {void}
     */
    selectChannel(id) {
        const active = this._element.querySelector('.active');
        if (!!active) {
            active.classList.remove('active');
        }

        const selector = '.js-sidebar-channel[data-id="' + String(id) + '"]';
        const target = this._element.querySelector(selector);
        if (!target) {
            return;
        }

        target.classList.add('active');

        const badge = target.querySelector('.badge');
        if (!!badge) {
            badge.classList.remove('highlight');
            // FIXME:
            $(badge).data('count', '');
            badge.textContent = '';
        }
    }
}
<commit_msg>Fix the regression: sidebar don't react in some case.<commit_after>/*global Handlebars:true, $: true */
/**
 * @license MIT License
 *
 * Copyright (c) 2015 Tetsuharu OHZEKI <saneyuki.snyk@gmail.com>
 * Copyright (c) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

import AppActionCreator from '../../intent/action/AppActionCreator';
import UIActionCreator from '../../intent/action/UIActionCreator';

export default class SidebarViewController {

    /**
     *  @constructor
     *  @param  {DomainState}   domain
     *  @param  {Element}   element
     */
    constructor(domain, element) {
        if (!element) {
            throw new Error();
        }

        /** @type   {Element}   */
        this._element = element;

        /*eslint-disable valid-jsdoc */
        /** @type   {Rx.IDisposable}  */
        this._disposeSignout = AppActionCreator.getDispatcher().signout.subscribe(() => {
            this.clearAllNetworks();
            this.showEmptinesse();
        });

        /** @type   {Rx.IDisposable}  */
        this._disposeRenderNetworks = AppActionCreator.getDispatcher().renderNetworksInView.subscribe((networks) => {
            this.hideEmptinesse();
            this.renderNetworks(networks);
        });

        /** @type   {Rx.IDisposable}  */
        this._disposeSelectChannel = UIActionCreator.getDispatcher().selectChannel.subscribe((channelId) => {
            this.selectChannel(channelId);
        });

        /** @type   {Rx.IDisposable}  */
        this._disposeAddedNetwork = domain.networkSet.addedStream().subscribe((network) => {
            this.addNetwork(network);
        });
        /*eslint-enable */

        element.addEventListener('click', this);
    }

    /**
     *  @param  {Event} aEvent
     *  @return {void}
     */
    handleEvent(aEvent) {
        switch (aEvent.type) {
            case 'click':
                this.onClick(aEvent);
        }
    }

    /**
     *  @param  {Event} aEvent
     *  @return {void}
     */
    onClick(aEvent) {
        const target = aEvent.target;
        if (!target.matches('.js-sidebar-channel, .js-sidebar-channel > :not(.close)')) {
            return;
        }

        // This is very heuristic way.
        let button = target;
        if (!target.classList.contains('js-sidebar-channel')) {
            button = target.parentNode;
        }

        const channelId = parseInt(button.getAttribute('data-id'), 10);
        UIActionCreator.selectChannel(channelId);
    }

    /**
     *  @return {void}
     */
    clearAllNetworks() {
        let element = this._element.querySelector('.networks');
        element.innerHTML = '';
    }

    /**
     *  @param  {Network}   network
     *  @return {void}
     */
    addNetwork(network) {
        this.hideEmptinesse();
        this.appendNetworks([network]);

        const channelList = network.getChannelList();
        const lastId = channelList[channelList.length - 1].id;
        UIActionCreator.selectChannel(lastId);
    }

    /**
     *  @return {void}
     */
    showEmptinesse() {
        let element = this._element.querySelector('.empty');
        element.style.display = 'block';
    }

    /**
     *  @return {void}
     */
    hideEmptinesse() {
        let element = this._element.querySelector('.empty');
        element.style.display = 'none';
    }

    /**
     *  @param  {Array<Network>} networks
     *  @return {void}
     */
    renderNetworks(networks) {
        const element = this._element.querySelector('.networks');
        const html = Handlebars.templates.network({
            networks,
        });

        element.innerHTML = html;
    }

    /**
     *  @param  {Array<Network>} networks
     *  @return {void}
     */
    appendNetworks(networks) {
        const element = this._element.querySelector('.networks');
        const html = Handlebars.templates.network({
            networks,
        });

        element.innerHTML = element.innerHTML + html;
    }

    /**
     *  @param  {number}    id
     *  @return {void}
     */
    selectChannel(id) {
        const active = this._element.querySelector('.active');
        if (!!active) {
            active.classList.remove('active');
        }

        const selector = '.js-sidebar-channel[data-id="' + String(id) + '"]';
        const target = this._element.querySelector(selector);
        if (!target) {
            return;
        }

        target.classList.add('active');

        const badge = target.querySelector('.badge');
        if (!!badge) {
            badge.classList.remove('highlight');
            // FIXME:
            $(badge).data('count', '');
            badge.textContent = '';
        }
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 Vanderbilt University, All rights reserved.
 *
 * Author: Robert Kereskenyi
 */

"use strict";

define(['jquery',
        'underscore',
        'js/Constants',
        'js/NodePropertyNames',
        'logManager',
        'js/Panels/MetaEditor/MetaEditorConstants',
        'eventDispatcher',
        'text!./METATemplate.js'], function (_jquery,
                                    _underscore,
                                    CONSTANTS,
                                    nodePropertyNames,
                                    logManager,
                                    MetaEditorConstants,
                                    EventDispatcher,
                                    METATemplateJS) {

    var META_RULES_CONTAINER_NODE_ID = MetaEditorConstants.META_ASPECT_CONTAINER_ID,
        _client,
        _territoryId,
        _territoryUI,
        TerritoryUI,
        _metaMembers,
        _patterns = {},
        _logger = logManager.create("METAAspectHelper"),
        _events = {'META_ASPECT_CHANGED': 'META_ASPECT_CHANGED'},
        _metaTypes;

    TerritoryUI = function () {
        $.extend(this, new EventDispatcher());
    };

    TerritoryUI.prototype.onOneEvent = function (/*events*/) {
        _processMetaContainer();

        this.dispatchEvent(_events.META_ASPECT_CHANGED);
    };

    var _reset = function () {
        _metaTypes = {};

        if (_territoryId) {
            _client.removeUI(_territoryId);
        }

        //there is an open project
        if (_client.getActiveProject()) {
            _territoryId = _client.addUI(_territoryUI, true);

            _patterns = {};
            _metaMembers = [];
            _patterns[META_RULES_CONTAINER_NODE_ID] = { "children": 0 };

            setTimeout(function (){
                _client.updateTerritory(_territoryId, _patterns);
            }, 100);

        }
    };

    var _metaFriendlyName = function (name) {
        var ret = name,
            re,
            i;

        // Not allowed characters to replace.
        var input = "áéíóöőúüűÁÉÍÓÖŐÚÜŰ ";

        // Safe characters to replace to.
        var output = "aeiooouuuAEIOOOUUU_";

        // allowed characters
        var allowed = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_';

        i = input.length;
        while (i--) {
            re = new RegExp(input[i], "g");
            ret = ret.replace(re, output[i]);
        }

        i = ret.length;
        while (i--) {
            if (allowed.indexOf(ret[i]) === -1) {
                ret = ret.substr(0, i) + ret.substr(i + 1);
            }
        }

        return ret;
    };

    var _processMetaContainer = function () {
        var metaContainer = _client.getNode(META_RULES_CONTAINER_NODE_ID);

        //reset META info container
        _metaTypes = {};

        if (metaContainer) {
            //read the META rules out of the META container and generate
            var metaAspectSetMembers = metaContainer.getMemberIds(MetaEditorConstants.META_ASPECT_SET_NAME),
                diff,
                territoryChanged = false,
                len,
                nodeID,
                nodeName;

            if (metaAspectSetMembers && metaAspectSetMembers.length > 0) {
                //check deleted nodes
                diff = _.difference(_metaMembers, metaAspectSetMembers);
                len = diff.length;
                while (len--) {
                    if (diff[len] !== META_RULES_CONTAINER_NODE_ID) {
                        delete _patterns[diff[len]];
                        territoryChanged = true;
                    }
                }

                //check added nodes
                diff = _.difference(metaAspectSetMembers, _metaMembers);
                len = diff.length;
                while (len--) {
                    if (diff[len] !== META_RULES_CONTAINER_NODE_ID) {
                        _patterns[diff[len]] = { "children": 0 };
                        territoryChanged = true;
                    }
                }

                //save the new contained nodes
                _metaMembers = metaAspectSetMembers.slice(0);

                _metaTypes = {};

                //generate the ID - TYPE mapping
                len = _metaMembers.length;
                while (len--) {
                    nodeID = _metaMembers[len];
                    var metaMemberNode = _client.getNode(nodeID);

                    if (metaMemberNode) {
                        nodeName = _metaFriendlyName(metaMemberNode.getAttribute(nodePropertyNames.Attributes.name));

                        if (nodeName === undefined || nodeName === null || nodeName === "") {
                            _logger.error('META item "' + nodeID + '" has an invalid name of: ' + nodeName);
                        } else {
                            if (_metaTypes.hasOwnProperty(nodeName)) {
                                _logger.error('Duplicate name on META level: "' + nodeName + '"');
                                delete _metaTypes[nodeName];
                            } else {
                                _metaTypes[nodeName] = nodeID;
                            }
                        }
                    }
                }

                _logger.debug('_metaTypes: \n' + JSON.stringify(_metaTypes));

                //there was change in the territory
                if (territoryChanged === true) {
                    setTimeout(function (){
                        _client.updateTerritory(_territoryId, _patterns);
                    }, 10);
                }
            }
        }
    };

    var _initialize = function (c) {
        //if already initialized, just return
        if (_client) {
            return;
        }
        _client = c;

        _client.addEventListener(_client.events.PROJECT_OPENED, function (/*__project, projectName*/) {
            _reset();
        });

        _client.addEventListener(_client.events.PROJECT_CLOSED, function (/*__project*/) {
            _reset();
        });

        _client.addEventListener(_client.events.BRANCH_CHANGED, function (/*__project, branch*/) {
            _reset();
        });

        _territoryUI = new TerritoryUI();
        _initialize = undefined;
    };

    var _isMETAType = function (objID, metaTypeID) {
        var result = false;

        if (objID && metaTypeID) {
            result = _client.isTypeOf(objID, metaTypeID);
        }

        return result;
    };

    var _getMetaAspectMembers = function () {
        var members = [];

        for (var m in _metaTypes) {
            if (_metaTypes.hasOwnProperty(m)) {
                members.push(_metaTypes[m]);
            }
        }

        return members;
    };

    var _addEventListener = function (event, callback) {
        if (_territoryUI) {
            _territoryUI.addEventListener(event, callback);
        }
    };

    var _removeEventListener = function (event, callback) {
        if (_territoryUI) {
            _territoryUI.removeEventListener(event, callback);
        }
    };

    var _getMETAAspectTypes = function () {
        var result = {};
        _.extend(result, _metaTypes);

        return result;
    };

    var _getMETAAspectTypesSorted = function () {
        var result = {},
            typeNames = [],
            m;

        for (m in _metaTypes) {
            if (_metaTypes.hasOwnProperty(m)) {
                typeNames.push(m);
            }
        }

        typeNames.sort();

        for (m = 0; m < typeNames.length; m += 1) {
            result[typeNames[m]] = _metaTypes[typeNames[m]];
        }

        return result;
    };

    /*
    Returns the parent meta types of the given object ID in the order of inheritance.
     */
    var _getMETATypesOf = function (objID) {
        var result = [];

        for (var m in _metaTypes) {
            if (_metaTypes.hasOwnProperty(m)) {
                if (_isMETAType(objID, _metaTypes[m])) {
                    result.push(m);
                }
            }
        }

        // sort based on metatypes inheritance
        result.sort(function(a, b) {
            return  _isMETAType(_metaTypes[a], _metaTypes[b]) ? -1 : 1;
        });

        return result;
    };

    var _generateMETAAspectJavaScript = function () {
        var result = {};

        if (!_.isEmpty(_metaTypes)) {
            var projName = _client.getActiveProject();
            var content = METATemplateJS;
            var sortedMetaTypes = _getMETAAspectTypesSorted();
            var typeCheckMethodTemplate = 'var _is__METATYPE__ = function (objID) { return METAAspectHelper.isMETAType(objID, _metaTypes.__METATYPE__); };'
            var typeCheckMethods = '';
            var typeCheckMethodsMap = [];
            var typeCheckMethodNamePrefix = 'is';
            var typeCheckMethodsMapIndent = '\t\t\t';
            var metaAspectTypesMap = [];

            //generate each type checker method
            /*
             var _isXXX = function (objID) {
                return METAAspectHelper.isMETAType(objID, _metaTypes.XXX);
             };
             */
            for (var t in sortedMetaTypes) {
                if (sortedMetaTypes.hasOwnProperty(t)) {
                    typeCheckMethods += typeCheckMethodTemplate.replace(/__METATYPE__/g, t) + '\n\t';
                    typeCheckMethodsMap.push(typeCheckMethodNamePrefix + t + ": _" + typeCheckMethodNamePrefix + t);
                    metaAspectTypesMap.push('\'' + t + '\'' + ': ' + '\'' + sortedMetaTypes[t] + '\'');
                }
            }

            content = content.replace( /__PROJECT__/g, projName);
            content = content.replace(/__META_ASPECT_TYPES__/g, '{\n\t\t' + metaAspectTypesMap.join(',\n\t\t') + '\n\t}');
            content = content.replace(/__META_ASPECT_TYPE_CHECKING__/g, typeCheckMethods);
            content = content.replace(/__TYPE_CHECK_METHOD_MAP__/g, '{\n' + typeCheckMethodsMapIndent + typeCheckMethodsMap.join(',\n' + typeCheckMethodsMapIndent) + '\n\t\t}');

            result.fileName = projName + ".META.js";
            result.content = content;
        }

        return result;
    };

    //return utility functions
    return { initialize: _initialize,
            isMETAType: _isMETAType,
            getMetaAspectMembers: _getMetaAspectMembers,
            events: _events,
            addEventListener: _addEventListener,
            removeEventListener: _removeEventListener,
            getMETAAspectTypes: _getMETAAspectTypes,
            getMETAAspectTypesSorted: _getMETAAspectTypesSorted,
            getMETATypesOf: _getMETATypesOf,
            generateMETAAspectJavaScript: _generateMETAAspectJavaScript
        };
});<commit_msg>initialization fix<commit_after>/*
 * Copyright (C) 2013 Vanderbilt University, All rights reserved.
 *
 * Author: Robert Kereskenyi
 */

"use strict";

define(['jquery',
        'underscore',
        'js/Constants',
        'js/NodePropertyNames',
        'logManager',
        'js/Panels/MetaEditor/MetaEditorConstants',
        'eventDispatcher',
        'text!./METATemplate.js'], function (_jquery,
                                    _underscore,
                                    CONSTANTS,
                                    nodePropertyNames,
                                    logManager,
                                    MetaEditorConstants,
                                    EventDispatcher,
                                    METATemplateJS) {

    var META_RULES_CONTAINER_NODE_ID = MetaEditorConstants.META_ASPECT_CONTAINER_ID,
        _client,
        _territoryId,
        _territoryUI,
        TerritoryUI,
        _metaMembers,
        _patterns = {},
        _logger = logManager.create("METAAspectHelper"),
        _events = {'META_ASPECT_CHANGED': 'META_ASPECT_CHANGED'},
        _metaTypes;

    TerritoryUI = function () {
        $.extend(this, new EventDispatcher());
    };

    TerritoryUI.prototype.onOneEvent = function (/*events*/) {
        _processMetaContainer();

        this.dispatchEvent(_events.META_ASPECT_CHANGED);
    };

    var _reset = function () {
        _metaTypes = {};

        if (_territoryId) {
            _client.removeUI(_territoryId);
        }

        //there is an open project
        if (_client.getActiveProject()) {
            _territoryId = _client.addUI(_territoryUI, true);

            _patterns = {};
            _metaMembers = [];
            _patterns[META_RULES_CONTAINER_NODE_ID] = { "children": 0 };

            setTimeout(function (){
                _client.updateTerritory(_territoryId, _patterns);
            }, 100);

        }
    };

    var _metaFriendlyName = function (name) {
        var ret = name,
            re,
            i;

        // Not allowed characters to replace.
        var input = "áéíóöőúüűÁÉÍÓÖŐÚÜŰ ";

        // Safe characters to replace to.
        var output = "aeiooouuuAEIOOOUUU_";

        // allowed characters
        var allowed = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_';

        i = input.length;
        while (i--) {
            re = new RegExp(input[i], "g");
            ret = ret.replace(re, output[i]);
        }

        i = ret.length;
        while (i--) {
            if (allowed.indexOf(ret[i]) === -1) {
                ret = ret.substr(0, i) + ret.substr(i + 1);
            }
        }

        return ret;
    };

    var _processMetaContainer = function () {
        var metaContainer = _client.getNode(META_RULES_CONTAINER_NODE_ID);

        //reset META info container
        _metaTypes = {};

        if (metaContainer) {
            //read the META rules out of the META container and generate
            var metaAspectSetMembers = metaContainer.getMemberIds(MetaEditorConstants.META_ASPECT_SET_NAME),
                diff,
                territoryChanged = false,
                len,
                nodeID,
                nodeName;

            if (metaAspectSetMembers && metaAspectSetMembers.length > 0) {
                //check deleted nodes
                diff = _.difference(_metaMembers, metaAspectSetMembers);
                len = diff.length;
                while (len--) {
                    if (diff[len] !== META_RULES_CONTAINER_NODE_ID) {
                        delete _patterns[diff[len]];
                        territoryChanged = true;
                    }
                }

                //check added nodes
                diff = _.difference(metaAspectSetMembers, _metaMembers);
                len = diff.length;
                while (len--) {
                    if (diff[len] !== META_RULES_CONTAINER_NODE_ID) {
                        _patterns[diff[len]] = { "children": 0 };
                        territoryChanged = true;
                    }
                }

                //save the new contained nodes
                _metaMembers = metaAspectSetMembers.slice(0);

                _metaTypes = {};

                //generate the ID - TYPE mapping
                len = _metaMembers.length;
                while (len--) {
                    nodeID = _metaMembers[len];
                    var metaMemberNode = _client.getNode(nodeID);

                    if (metaMemberNode) {
                        nodeName = _metaFriendlyName(metaMemberNode.getAttribute(nodePropertyNames.Attributes.name));

                        if (nodeName === undefined || nodeName === null || nodeName === "") {
                            _logger.error('META item "' + nodeID + '" has an invalid name of: ' + nodeName);
                        } else {
                            if (_metaTypes.hasOwnProperty(nodeName)) {
                                _logger.error('Duplicate name on META level: "' + nodeName + '"');
                                delete _metaTypes[nodeName];
                            } else {
                                _metaTypes[nodeName] = nodeID;
                            }
                        }
                    }
                }

                _logger.debug('_metaTypes: \n' + JSON.stringify(_metaTypes));

                //there was change in the territory
                if (territoryChanged === true) {
                    setTimeout(function (){
                        _client.updateTerritory(_territoryId, _patterns);
                    }, 10);
                }
            }
        }
    };

    var _initialize = function (c) {
        //if already initialized, just return
        if (_client) {
            return;
        }
        _client = c;

        _client.addEventListener(_client.events.PROJECT_OPENED, function (/*__project, projectName*/) {
            _reset();
        });

        _client.addEventListener(_client.events.PROJECT_CLOSED, function (/*__project*/) {
            _reset();
        });

        _client.addEventListener(_client.events.BRANCH_CHANGED, function (/*__project, branch*/) {
            _reset();
        });

        _territoryUI = new TerritoryUI();
    };

    var _isMETAType = function (objID, metaTypeID) {
        var result = false;

        if (objID && metaTypeID) {
            result = _client.isTypeOf(objID, metaTypeID);
        }

        return result;
    };

    var _getMetaAspectMembers = function () {
        var members = [];

        for (var m in _metaTypes) {
            if (_metaTypes.hasOwnProperty(m)) {
                members.push(_metaTypes[m]);
            }
        }

        return members;
    };

    var _addEventListener = function (event, callback) {
        if (_territoryUI) {
            _territoryUI.addEventListener(event, callback);
        }
    };

    var _removeEventListener = function (event, callback) {
        if (_territoryUI) {
            _territoryUI.removeEventListener(event, callback);
        }
    };

    var _getMETAAspectTypes = function () {
        var result = {};
        _.extend(result, _metaTypes);

        return result;
    };

    var _getMETAAspectTypesSorted = function () {
        var result = {},
            typeNames = [],
            m;

        for (m in _metaTypes) {
            if (_metaTypes.hasOwnProperty(m)) {
                typeNames.push(m);
            }
        }

        typeNames.sort();

        for (m = 0; m < typeNames.length; m += 1) {
            result[typeNames[m]] = _metaTypes[typeNames[m]];
        }

        return result;
    };

    /*
    Returns the parent meta types of the given object ID in the order of inheritance.
     */
    var _getMETATypesOf = function (objID) {
        var result = [];

        for (var m in _metaTypes) {
            if (_metaTypes.hasOwnProperty(m)) {
                if (_isMETAType(objID, _metaTypes[m])) {
                    result.push(m);
                }
            }
        }

        // sort based on metatypes inheritance
        result.sort(function(a, b) {
            return  _isMETAType(_metaTypes[a], _metaTypes[b]) ? -1 : 1;
        });

        return result;
    };

    var _generateMETAAspectJavaScript = function () {
        var result = {};

        if (!_.isEmpty(_metaTypes)) {
            var projName = _client.getActiveProject();
            var content = METATemplateJS;
            var sortedMetaTypes = _getMETAAspectTypesSorted();
            var typeCheckMethodTemplate = 'var _is__METATYPE__ = function (objID) { return METAAspectHelper.isMETAType(objID, _metaTypes.__METATYPE__); };'
            var typeCheckMethods = '';
            var typeCheckMethodsMap = [];
            var typeCheckMethodNamePrefix = 'is';
            var typeCheckMethodsMapIndent = '\t\t\t';
            var metaAspectTypesMap = [];

            //generate each type checker method
            /*
             var _isXXX = function (objID) {
                return METAAspectHelper.isMETAType(objID, _metaTypes.XXX);
             };
             */
            for (var t in sortedMetaTypes) {
                if (sortedMetaTypes.hasOwnProperty(t)) {
                    typeCheckMethods += typeCheckMethodTemplate.replace(/__METATYPE__/g, t) + '\n\t';
                    typeCheckMethodsMap.push(typeCheckMethodNamePrefix + t + ": _" + typeCheckMethodNamePrefix + t);
                    metaAspectTypesMap.push('\'' + t + '\'' + ': ' + '\'' + sortedMetaTypes[t] + '\'');
                }
            }

            content = content.replace( /__PROJECT__/g, projName);
            content = content.replace(/__META_ASPECT_TYPES__/g, '{\n\t\t' + metaAspectTypesMap.join(',\n\t\t') + '\n\t}');
            content = content.replace(/__META_ASPECT_TYPE_CHECKING__/g, typeCheckMethods);
            content = content.replace(/__TYPE_CHECK_METHOD_MAP__/g, '{\n' + typeCheckMethodsMapIndent + typeCheckMethodsMap.join(',\n' + typeCheckMethodsMapIndent) + '\n\t\t}');

            result.fileName = projName + ".META.js";
            result.content = content;
        }

        return result;
    };

    //return utility functions
    return { initialize: _initialize,
            isMETAType: _isMETAType,
            getMetaAspectMembers: _getMetaAspectMembers,
            events: _events,
            addEventListener: _addEventListener,
            removeEventListener: _removeEventListener,
            getMETAAspectTypes: _getMETAAspectTypes,
            getMETAAspectTypesSorted: _getMETAAspectTypesSorted,
            getMETATypesOf: _getMETATypesOf,
            generateMETAAspectJavaScript: _generateMETAAspectJavaScript
        };
});<|endoftext|>


<commit_before>// frontpagejs
// Radio Front Page

import React from 'react';
// React-Router
import {
  Router,
  Route,
  IndexRoute,
  browserHistory,
  IndexLink,
} from 'react-router';
import { connect } from 'react-redux';
import ReactGA from 'react-ga';
import { Grid, Col } from 'react-bootstrap';

// Redux Components
import ShowsContent from './components/ShowsContent';
import EventList from './components/EventList';
import DJList from './components/DJList/DJList';
import ShowPage from './components/ShowPage';
import EventPage from './components/EventPage';
import DJPage from './components/DJPage';

// Non-Redux Components
import TriangleCanvas from './components/TriangleCanvas';
import FrontPageNavbar from './components/FrontPageNavbar';
import StreamBar from './components/StreamBar/StreamBar';
import SocialPanel from './components/SocialPanel';
import ShowInfo from './components/ShowInfo';
import WaterFallContent from './components/WaterFallContent';
import Error404Page from './components/Error404Page';
import StreamIssuesPage from './components/StreamIssuesPage';
import AboutPage from './components/AboutPage';
import PromoBanner from './components/PromoBanner';
// import SoccerUpdate from './components/SoccerUpdate';

// Common Components
import RectImage from '../common/RectImage';

import './frontpage.scss';

// Google analytics helper

ReactGA.initialize('UA-21406547-20');

function logPageView() {
  ReactGA.set({ page: window.location.pathname });
  ReactGA.pageview(window.location.pathname);
}

// Misc

// styling

// temp data
// const sampleFeaturedShow = {"title":"Pirate Radio","id":12,"day":"Mon","time":"10pm","djs":{"chris":"DJ Jamburglar"},"genre":"Psychedelic","blurb":"Life is a trip... Sail away to undiscovered psychic frontiers with underground psychedelic jams","public":true,"pages":[],"episodes":[]};

/**
Frontpage UI, including radio stream, navbar, and triangle background.
Expects children components for tab contents

@prop nowPlaying: show to display as live
@prop spotlight: show to display as spotlight
@prop children: components to display in content area
* */

// update social media links here
// img is the base name of the Font Awesome icon
// Move to a separate file later?
const socialMediaLinks = [
  {
    img: 'facebook',
    link: 'https://www.facebook.com/uclaradio',
  },
  {
    img: 'twitter',
    link: 'https://twitter.com/UCLAradio',
  },
  {
    img: 'instagram',
    link: 'https://www.instagram.com/uclaradio/',
  },
  {
    img: 'snapchat-ghost',
    link: 'https://www.snapchat.com/add/uclaradio',
  },
];

const FrontpageContent = React.createClass({
  render() {
    const showPlaying =
      this.props.nowPlaying && this.props.nowPlaying.title != null;
    return (

        {/* <TriangleCanvas xColors={theme.timezoneColorScheme()}> */}
        <TriangleCanvas xColors="Spectral">

            <Grid>
              <Col xs={12} md={3} className="frontpageCol">
                <IndexLink to="/" activeClassName="active">

                    <RectImage
                      maxWidth="350px"
                      src="/img/uclaradio-black.png"
                    />

                </IndexLink>
                <SocialPanel links={socialMediaLinks} size="2x" />
                <ShowInfo title="Current Show" show={this.props.nowPlaying} />
                {/* Show Spotlight */}
                <ShowInfo title="Spotlight" show={this.props.spotlight} />
              </Col>

              <Col xs={12} md={9} className="frontpageCol">
                {/* <SoccerUpdate /> */}
                {/* Show of the Month */}
                <PromoBanner />
                <FrontPageNavbar />
                {this.props.children}
              </Col>
            </Grid>

          <StreamBar
            currentShowTitle={showPlaying ? this.props.nowPlaying.title : null}
          />
        </TriangleCanvas>

    );
  },
});

/**
Redux container (wrapper) for FrontpageContent to provide props:
  nowPlaying, spotlight
* */

const mapStateToProps = state => {
  const props = {};

  // set nowPlaying & spotlight shows if found
  for (
    let showIndex = 0;
    showIndex < state.shows.shows.length;
    showIndex += 1
  ) {
    const show = state.shows.shows[showIndex];
    if (show.id === state.shows.nowPlayingID) {
      props.nowPlaying = show;
    }
    // note: only set spotlight show if different from current show
    if (
      show.id === state.shows.spotlightID &&
      show.id !== state.shows.nowPlayingID
    ) {
      props.spotlight = show;
    }
  }

  const spotlight = state.shows.shows.find(
    show => show.id == state.shows.spotlightID
  );
  if (spotlight && spotlight !== -1) {
    props.spotlight = spotlight;
  }

  return props;
};
const FrontpageContentContainer = connect(mapStateToProps)(FrontpageContent);

// react-router routes
// each path represents a page of our frontpage with a component
const routes = (
  <Route path="/" component={FrontpageContentContainer}>
    <IndexRoute component={WaterFallContent} />
    <Route path="/djs" component={DJList} />
    <Route path="/djs/:djName" component={DJPage} />
    <Route path="/events" component={EventList} />
    <Route path="/shows" components={ShowsContent} />
    <Route path="/shows/:showID" component={ShowPage} />
    <Route path="/events/:eventID" component={EventPage} />
    <Route path="/streamIssues" component={StreamIssuesPage} />
    <Route path="/about" component={AboutPage} />
    <Route path="*" component={Error404Page} />
  </Route>
);

/**
Wrapper component, allows to use react-router to switch pages
also sets some data in store

@prop updateNowPlaying: () => refresh now playing by requesting new data from server
@prop setSpotlightShowID: (showID) => update the spotlight to be a show with the provided showID
@prop updateShows: () => should fetch updated list of shows and update store
* */
const Frontpage = React.createClass({
  componentWillMount() {
    // refresh live show info now and every 30 seconds
    this.props.updateNowPlaying();
    this.interval = setInterval(this.props.updateNowPlaying, 30 * 1000);

    // update now playing and fetch initial shows data
    // 01/21/19 - "Half-Time"
    this.props.setSpotlightShowID(764);
    this.props.updateShows();
  },
  componentWillUnmount() {
    clearInterval(this.interval);
  },
  render() {
    return (
      <Router history={browserHistory} onUpdate={logPageView}>
        {routes}
      </Router>
    );
  },
});

export default Frontpage;
<commit_msg>W19 Show of the Week 4<commit_after>// frontpagejs
// Radio Front Page

import React from 'react';
// React-Router
import {
  Router,
  Route,
  IndexRoute,
  browserHistory,
  IndexLink,
} from 'react-router';
import { connect } from 'react-redux';
import ReactGA from 'react-ga';
import { Grid, Col } from 'react-bootstrap';

// Redux Components
import ShowsContent from './components/ShowsContent';
import EventList from './components/EventList';
import DJList from './components/DJList/DJList';
import ShowPage from './components/ShowPage';
import EventPage from './components/EventPage';
import DJPage from './components/DJPage';

// Non-Redux Components
import TriangleCanvas from './components/TriangleCanvas';
import FrontPageNavbar from './components/FrontPageNavbar';
import StreamBar from './components/StreamBar/StreamBar';
import SocialPanel from './components/SocialPanel';
import ShowInfo from './components/ShowInfo';
import WaterFallContent from './components/WaterFallContent';
import Error404Page from './components/Error404Page';
import StreamIssuesPage from './components/StreamIssuesPage';
import AboutPage from './components/AboutPage';
import PromoBanner from './components/PromoBanner';
// import SoccerUpdate from './components/SoccerUpdate';

// Common Components
import RectImage from '../common/RectImage';

import './frontpage.scss';

// Google analytics helper

ReactGA.initialize('UA-21406547-20');

function logPageView() {
  ReactGA.set({ page: window.location.pathname });
  ReactGA.pageview(window.location.pathname);
}

// Misc

// styling

// temp data
// const sampleFeaturedShow = {"title":"Pirate Radio","id":12,"day":"Mon","time":"10pm","djs":{"chris":"DJ Jamburglar"},"genre":"Psychedelic","blurb":"Life is a trip... Sail away to undiscovered psychic frontiers with underground psychedelic jams","public":true,"pages":[],"episodes":[]};

/**
Frontpage UI, including radio stream, navbar, and triangle background.
Expects children components for tab contents

@prop nowPlaying: show to display as live
@prop spotlight: show to display as spotlight
@prop children: components to display in content area
* */

// update social media links here
// img is the base name of the Font Awesome icon
// Move to a separate file later?
const socialMediaLinks = [
  {
    img: 'facebook',
    link: 'https://www.facebook.com/uclaradio',
  },
  {
    img: 'twitter',
    link: 'https://twitter.com/UCLAradio',
  },
  {
    img: 'instagram',
    link: 'https://www.instagram.com/uclaradio/',
  },
  {
    img: 'snapchat-ghost',
    link: 'https://www.snapchat.com/add/uclaradio',
  },
];

const FrontpageContent = React.createClass({
  render() {
    const showPlaying =
      this.props.nowPlaying && this.props.nowPlaying.title != null;
    return (

        {/* <TriangleCanvas xColors={theme.timezoneColorScheme()}> */}
        <TriangleCanvas xColors="Spectral">

            <Grid>
              <Col xs={12} md={3} className="frontpageCol">
                <IndexLink to="/" activeClassName="active">

                    <RectImage
                      maxWidth="350px"
                      src="/img/uclaradio-black.png"
                    />

                </IndexLink>
                <SocialPanel links={socialMediaLinks} size="2x" />
                <ShowInfo title="Current Show" show={this.props.nowPlaying} />
                {/* Show Spotlight */}
                <ShowInfo title="Spotlight" show={this.props.spotlight} />
              </Col>

              <Col xs={12} md={9} className="frontpageCol">
                {/* <SoccerUpdate /> */}
                {/* Show of the Month */}
                <PromoBanner />
                <FrontPageNavbar />
                {this.props.children}
              </Col>
            </Grid>

          <StreamBar
            currentShowTitle={showPlaying ? this.props.nowPlaying.title : null}
          />
        </TriangleCanvas>

    );
  },
});

/**
Redux container (wrapper) for FrontpageContent to provide props:
  nowPlaying, spotlight
* */

const mapStateToProps = state => {
  const props = {};

  // set nowPlaying & spotlight shows if found
  for (
    let showIndex = 0;
    showIndex < state.shows.shows.length;
    showIndex += 1
  ) {
    const show = state.shows.shows[showIndex];
    if (show.id === state.shows.nowPlayingID) {
      props.nowPlaying = show;
    }
    // note: only set spotlight show if different from current show
    if (
      show.id === state.shows.spotlightID &&
      show.id !== state.shows.nowPlayingID
    ) {
      props.spotlight = show;
    }
  }

  const spotlight = state.shows.shows.find(
    show => show.id == state.shows.spotlightID
  );
  if (spotlight && spotlight !== -1) {
    props.spotlight = spotlight;
  }

  return props;
};
const FrontpageContentContainer = connect(mapStateToProps)(FrontpageContent);

// react-router routes
// each path represents a page of our frontpage with a component
const routes = (
  <Route path="/" component={FrontpageContentContainer}>
    <IndexRoute component={WaterFallContent} />
    <Route path="/djs" component={DJList} />
    <Route path="/djs/:djName" component={DJPage} />
    <Route path="/events" component={EventList} />
    <Route path="/shows" components={ShowsContent} />
    <Route path="/shows/:showID" component={ShowPage} />
    <Route path="/events/:eventID" component={EventPage} />
    <Route path="/streamIssues" component={StreamIssuesPage} />
    <Route path="/about" component={AboutPage} />
    <Route path="*" component={Error404Page} />
  </Route>
);

/**
Wrapper component, allows to use react-router to switch pages
also sets some data in store

@prop updateNowPlaying: () => refresh now playing by requesting new data from server
@prop setSpotlightShowID: (showID) => update the spotlight to be a show with the provided showID
@prop updateShows: () => should fetch updated list of shows and update store
* */
const Frontpage = React.createClass({
  componentWillMount() {
    // refresh live show info now and every 30 seconds
    this.props.updateNowPlaying();
    this.interval = setInterval(this.props.updateNowPlaying, 30 * 1000);

    // update now playing and fetch initial shows data
    // 01/28/19 - "CMMND Radio"
    this.props.setSpotlightShowID(726);
    this.props.updateShows();
  },
  componentWillUnmount() {
    clearInterval(this.interval);
  },
  render() {
    return (
      <Router history={browserHistory} onUpdate={logPageView}>
        {routes}
      </Router>
    );
  },
});

export default Frontpage;
<|endoftext|>


<commit_before>Template.registrantDetails.helpers({
    'registrationTypeOptions': function () {
        // registration types used on the registration form
        return [
            {label: "Commuter (sleeping elsewhere)", value: "commuter"},
            {label: "Daily (staying overnight)", value: "daily"},
            {label: "Full Week (staying overnight all nights)", value: "weekly"}
        ];
    },
    /*
    Determine if registrant is school aged
    by checking age group
    return true if age group is child, youth, or teen
    */
    'schoolAgeGroup': function () {
        var ageGroup = ageGroupVar.get();

        if (ageGroup) {
            // look at the value of age group
            switch (ageGroup) {
                    // if child, youth or teen
                    // return true
                case 'child':
                    return true;
                    break;
                case 'youth':
                    return true;
                    break;
                case 'teen':
                    return true;
                    break;
                default:
                    return false;
                    break;
            };
        } else {
            return false;
        }
    }
});

Template.registrantDetails.events({
    'change #registration_type': function () {
        // clean up form values for accommodations and days
        // to make sure no erroneous values remain

        resetReactiveVars();

        // Clear the accommodations selection
        //$("#accommodations").val("");

        // Clear all day checkboxes
        $('input[name="days"]').each(function() {
            // make sure day is not checked
            this.checked = false;
        });
    },
    'change #age': function () {
        // Get the value of the age field
        var ageValue = $('#age').val();

        // Calculate the age group based on the age value
        var ageGroup = calculateAgeGroup(ageValue);

        // Reset the accommodations selection
        // as accommodations depend on age group
        $("#accommodations").val("");

        // Set the age group reactive variable
        // for price calculations
        ageGroupVar.set(ageGroup);
    }
});
<commit_msg>Add registrantAgeIsBelow method<commit_after>Template.registrantDetails.helpers({
    'registrationTypeOptions': function () {
        // registration types used on the registration form
        return [
            {label: "Commuter (sleeping elsewhere)", value: "commuter"},
            {label: "Daily (staying overnight)", value: "daily"},
            {label: "Full Week (staying overnight all nights)", value: "weekly"}
        ];
    },
    /*
    Determine if registrant is school aged
    by checking age group
    return true if age group is child, youth, or teen
    */
    'schoolAgeGroup': function () {
        var ageGroup = ageGroupVar.get();

        if (ageGroup) {
            // look at the value of age group
            switch (ageGroup) {
                    // if child, youth or teen
                    // return true
                case 'child':
                    return true;
                    break;
                case 'youth':
                    return true;
                    break;
                case 'teen':
                    return true;
                    break;
                default:
                    return false;
                    break;
            };
        } else {
            return false;
        }
    },
    "registrantAgeIsBelow": function (ageThreshold) {
      // Get current age value from form
      let age = AutoForm.getFieldValue("age")

      if (age) {
        // Compare current value versus desired age threshold
        return age < ageThreshold;
      }
    }
});

Template.registrantDetails.events({
    'change #registration_type': function () {
        // clean up form values for accommodations and days
        // to make sure no erroneous values remain

        resetReactiveVars();

        // Clear the accommodations selection
        //$("#accommodations").val("");

        // Clear all day checkboxes
        $('input[name="days"]').each(function() {
            // make sure day is not checked
            this.checked = false;
        });
    },
    'change #age': function () {
        // Get the value of the age field
        var ageValue = $('#age').val();

        // Calculate the age group based on the age value
        var ageGroup = calculateAgeGroup(ageValue);

        // Reset the accommodations selection
        // as accommodations depend on age group
        $("#accommodations").val("");

        // Set the age group reactive variable
        // for price calculations
        ageGroupVar.set(ageGroup);
    }
});
<|endoftext|>