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

async function getTaskInfo(keyString) {
    const queryURL = "/tasks/info?key=" + keyString;
    const request = new Request(queryURL, {method: "GET"});
    const response = await fetch(request);
    const info = await response.json();
    return info;
}

async function deleteTask(keyString) {
    const info = await getTaskInfo(keyString);
    if (info.status !== "OPEN") {
        window.alert("You can only delete an 'OPEN' task.")
    } else {
        if (confirm("Are you sure that you want to delete the task?")) {
            const queryURL = "/tasks?key=" + keyString;
            const request = new Request(queryURL, {method: "DELETE"});
            const response = await fetch(request);
            showNeedHelp();
        }
    }
}

async function editTask(keyString) {
    const info = await getTaskInfo(keyString);
    if (info.status !== "OPEN") {
        window.alert("You can only edit an 'OPEN' task.")
    } else {
        document.getElementById("edit-detail-input").value = info.detail;
        document.getElementById("edit-category-input").value = info.category;
        document.getElementById("edit-point-input").value = info.reward.toString();
        const id_input = document.getElementById("task-id-input");
        id_input.value = info.keyString;
        document.getElementById("editTaskModalWrapper").style.display = "block";
        showNeedHelp()
    }

async function editInfo() {
    const request = new Request("/account", {method: "GET"});
    const response = await fetch(request);
    const userInfo = await response.json();
    document.getElementById("edit-nickname-input").value = userInfo[0];
    document.getElementById("edit-address-input").value = userInfo[1];
    document.getElementById("edit-phone-number-input").value = userInfo[2];
    showInfoModal();
}

async function completeTask(keyString) {
    const info = await getTaskInfo(keyString);
    if (info.status !== "IN PROGRESS") {
        window.alert("You have already marked the task as complete.");
    } else if (info.owner === info.helper) {
        window.alert("You cannot complete a task published by yourself!");
    } else {
        if (confirm("Are you sure that you have already completed the task?")) {
            const queryURL = "/tasks/info?key=" + keyString + "&status=" + "COMPLETE: AWAIT VERIFICATION";
            const request = new Request(queryURL, {method: "POST"});
            const response = await fetch(request);
            showOfferHelp();
        }
    }
}

async function abandonTask(keyString) {
    const info = await getTaskInfo(keyString);
    if (info.status !== "IN PROGRESS") {
        window.alert("You have already marked the task as complete.");
    } else {
        if (confirm("Are you sure that you want to abandon the task?")) {
            const queryURL = "/tasks/info?key=" + keyString + "&status=" + "OPEN";
            const request = new Request(queryURL, {method: "POST"});
            const response = await fetch(request);
            showOfferHelp();
        }
    }
}

async function verifyTask(keyString) {
    const info = await getTaskInfo(keyString);
    if (info.status === "COMPLETE") {
        window.alert("You have already verified the task.");
    } else {
        if (confirm("Are you sure that you want to verify the task?")) {
            const queryURL = "/tasks/info?key=" + keyString + "&status=" + "COMPLETE";
            const request = new Request(queryURL, {method: "POST"});
            const response = await fetch(request);
            showNeedHelp();
        }
    }
}

async function disapproveTask(keyString) {
    const info = await getTaskInfo(keyString);
    if (info.status === "COMPLETE") {
        window.alert("You have already verified the task.");
    } else {
        if (confirm("Are you sure that you want to disapprove the task?")) {
            const queryURL = "/tasks/info?key=" + keyString + "&status=" + "IN PROGRESS";
            const request = new Request(queryURL, {method: "POST"});
            const response = await fetch(request);
            showNeedHelp();
        }
    }
}

function showNeedHelp() {
    document.getElementById("need-help").style.display = "table";
    document.getElementById("create").style.display = "block";
    document.getElementById("offer-help").style.display = "none";
    document.getElementById("await-verif").style.display = "table";
    document.getElementById("complete-task").style.display = "none";
    document.getElementById("need-help-button").style.backgroundColor = "#3e8e41";
    document.getElementById("offer-help-button").style.backgroundColor = "#4CAF50";
    displayNeedHelpTasks();
    displayNeedHelpCompleteTasks();
}

function showOfferHelp() {
    document.getElementById("need-help").style.display = "none";
    document.getElementById("create").style.display = "none";
    document.getElementById("offer-help").style.display = "table";
    document.getElementById("await-verif").style.display = "none";
    document.getElementById("complete-task").style.display = "table";
    document.getElementById("need-help-button").style.backgroundColor = "#4CAF50";
    document.getElementById("offer-help-button").style.backgroundColor = "#3e8e41";
    displayOfferHelpTasks();
    displayOfferHelpCompleteTasks();
}

function showModal() {
    var modal = document.getElementById("createTaskModalWrapper");
    modal.style.display = "block";
}

function showInfoModal() {
    var modal = document.getElementById("updateInfoModalWrapper");
    modal.style.display = "block";
}

function closeModal() {
    var modal = document.getElementById("createTaskModalWrapper");
    modal.style.display = "none";
}

function closeEditModal() {
    var modal = document.getElementById("editTaskModalWrapper");
    modal.style.display = "none";
}

function closeInfoModal() {
    var modal = document.getElementById("updateInfoModalWrapper");
    modal.style.display = "none";
}

// If the user clicks outside of the modal, closes the modal directly
window.onclick = function(event) {
    var modal = document.getElementById("createTaskModalWrapper");
    if (event.target == modal) {
        modal.style.display = "none";
    }
    var editModal = document.getElementById("editTaskModalWrapper");
    if (event.target == editModal) {
        editModal.style.display = "none";
    }
}

async function displayNeedHelpTasks() {
    const queryURL = "/mytasks?keyword=Owner&complete=False";
    const request = new Request(queryURL, {method: "GET"});
    const response = await fetch(request);
    const taskResponse = await response.json();
    const needHelpBody = document.getElementById("need-help-body");
    needHelpBody.innerHTML = "";
    for (var index = 0; index < taskResponse.length; index++) {
        var tr = document.createElement("tr");
        var task = taskResponse[index];
        var data = [task.detail, task.helper, task.status];
        for (var i = 0; i < data.length; i++) {
            var td = document.createElement("td");
            td.appendChild(document.createTextNode(data[i]));
            tr.appendChild(td);
        }
        const keyStringCopy = task.keyString.slice();
        var editTd = document.createElement("td");
        var editBtn = document.createElement("button");
        editBtn.className = "edit-task";
        editBtn.addEventListener("click", function () { editTask(keyStringCopy) });
        editBtn.innerHTML = (task.status === "OPEN") ? '':'';
        editTd.appendChild(editBtn);
        var deleteTd = document.createElement("td");
        var deleteBtn = document.createElement("button");
        deleteBtn.className = "delete-task";
        deleteBtn.addEventListener("click", function () { deleteTask(keyStringCopy) });
        deleteBtn.innerHTML = (task.status === "OPEN") ? '':'';
        deleteTd.appendChild(deleteBtn);
        tr.appendChild(editTd);
        tr.appendChild(deleteTd);
        needHelpBody.appendChild(tr);
    }
}

async function displayNeedHelpCompleteTasks() {
    const queryURL = "/mytasks?keyword=Owner&complete=True";
    const request = new Request(queryURL, {method: "GET"});
    const response = await fetch(request);
    const taskResponse = await response.json();
    const completeTaskBody = document.getElementById("await-verif-body");
    completeTaskBody.innerHTML = "";
    for (var index = 0; index < taskResponse.length; index++) {
        var tr = document.createElement("tr");
        var task = taskResponse[index];
        var data = [task.detail, task.helper, task.status];
        for (var i = 0; i < data.length; i++) {
            var td = document.createElement("td");
            td.appendChild(document.createTextNode(data[i]));
            tr.appendChild(td);
        }
        const keyStringCopy = task.keyString.slice();
        var verifyTd = document.createElement("td");
        var verifyBtn = document.createElement("button");
        verifyBtn.className = "verify-task";
        verifyBtn.addEventListener("click", function () { verifyTask(keyStringCopy) });
        verifyBtn.innerHTML = (task.status !== "COMPLETE") ? '':'';
        verifyTd.appendChild(verifyBtn);
        var disapproveTd = document.createElement("td");
        var disapproveBtn = document.createElement("button");
        disapproveBtn.className = "disapprove-task";
        disapproveBtn.addEventListener("click", function () { disapproveTask(keyStringCopy) });
        disapproveBtn.innerHTML = (task.status !== "COMPLETE") ? '':'';
        disapproveTd.appendChild(disapproveBtn);
        tr.appendChild(verifyTd);
        tr.appendChild(disapproveTd);
        completeTaskBody.appendChild(tr);
    }
}

async function displayOfferHelpTasks() {
    const queryURL = "/mytasks?keyword=Helper&complete=False";
    const request = new Request(queryURL, {method: "GET"});
    const response = await fetch(request);
    const taskResponse = await response.json();
    const offerHelpBody = document.getElementById("offer-help-body");
    offerHelpBody.innerHTML = "";
    for (var index = 0; index < taskResponse.length; index++) {
        var tr = document.createElement("tr");
        var task = taskResponse[index];
        var data = [task.detail, task.status, task.owner];
        for (var i = 0; i < data.length; i++) {
            var td = document.createElement("td");
            td.appendChild(document.createTextNode(data[i]));
            tr.appendChild(td);
        }
        const keyStringCopy = task.keyString.slice();
        var completeTd = document.createElement("td");
        var completeBtn = document.createElement("button");
        completeBtn.className = "complete-task";
        completeBtn.addEventListener("click", function () { completeTask(keyStringCopy) });
        completeBtn.innerHTML = (task.status === "IN PROGRESS") ? '':'';
        completeTd.appendChild(completeBtn);
        var abandonTd = document.createElement("td");
        var abandonBtn = document.createElement("button");
        abandonBtn.className = "abandon-task";
        abandonBtn.addEventListener("click", function () { abandonTask(keyStringCopy) });
        abandonBtn.innerHTML = (task.status === "IN PROGRESS") ? '':'';;
        abandonTd.appendChild(abandonBtn);
        tr.appendChild(completeTd);
        tr.appendChild(abandonTd);
        offerHelpBody.appendChild(tr);
    }
}

async function displayOfferHelpCompleteTasks() {
    const queryURL = "/mytasks?keyword=Helper&complete=True";
    const request = new Request(queryURL, {method: "GET"});
    const response = await fetch(request);
    const taskResponse = await response.json();
    const completeTaskBody = document.getElementById("complete-task-body");
    completeTaskBody.innerHTML = "";
    for (var index = 0; index < taskResponse.length; index++) {
        var tr = document.createElement("tr");
        var task = taskResponse[index];
        var data = [task.detail, task.status, task.owner, task.reward.toString()];
        for (var i = 0; i < data.length; i++) {
            var td = document.createElement("td");
            td.appendChild(document.createTextNode(data[i]));
            tr.appendChild(td);
        }
        completeTaskBody.appendChild(tr);
    }
}<commit_msg>add missing curly brace<commit_after>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

async function getTaskInfo(keyString) {
    const queryURL = "/tasks/info?key=" + keyString;
    const request = new Request(queryURL, {method: "GET"});
    const response = await fetch(request);
    const info = await response.json();
    return info;
}

async function deleteTask(keyString) {
    const info = await getTaskInfo(keyString);
    if (info.status !== "OPEN") {
        window.alert("You can only delete an 'OPEN' task.")
    } else {
        if (confirm("Are you sure that you want to delete the task?")) {
            const queryURL = "/tasks?key=" + keyString;
            const request = new Request(queryURL, {method: "DELETE"});
            const response = await fetch(request);
            showNeedHelp();
        }
    }
}

async function editTask(keyString) {
    const info = await getTaskInfo(keyString);
    if (info.status !== "OPEN") {
        window.alert("You can only edit an 'OPEN' task.")
    } else {
        document.getElementById("edit-detail-input").value = info.detail;
        document.getElementById("edit-category-input").value = info.category;
        document.getElementById("edit-point-input").value = info.reward.toString();
        const id_input = document.getElementById("task-id-input");
        id_input.value = info.keyString;
        document.getElementById("editTaskModalWrapper").style.display = "block";
        showNeedHelp()
    }
}

async function editInfo() {
    const request = new Request("/account", {method: "GET"});
    const response = await fetch(request);
    const userInfo = await response.json();
    document.getElementById("edit-nickname-input").value = userInfo[0];
    document.getElementById("edit-address-input").value = userInfo[1];
    document.getElementById("edit-phone-number-input").value = userInfo[2];
    showInfoModal();
}

async function completeTask(keyString) {
    const info = await getTaskInfo(keyString);
    if (info.status !== "IN PROGRESS") {
        window.alert("You have already marked the task as complete.");
    } else if (info.owner === info.helper) {
        window.alert("You cannot complete a task published by yourself!");
    } else {
        if (confirm("Are you sure that you have already completed the task?")) {
            const queryURL = "/tasks/info?key=" + keyString + "&status=" + "COMPLETE: AWAIT VERIFICATION";
            const request = new Request(queryURL, {method: "POST"});
            const response = await fetch(request);
            showOfferHelp();
        }
    }
}

async function abandonTask(keyString) {
    const info = await getTaskInfo(keyString);
    if (info.status !== "IN PROGRESS") {
        window.alert("You have already marked the task as complete.");
    } else {
        if (confirm("Are you sure that you want to abandon the task?")) {
            const queryURL = "/tasks/info?key=" + keyString + "&status=" + "OPEN";
            const request = new Request(queryURL, {method: "POST"});
            const response = await fetch(request);
            showOfferHelp();
        }
    }
}

async function verifyTask(keyString) {
    const info = await getTaskInfo(keyString);
    if (info.status === "COMPLETE") {
        window.alert("You have already verified the task.");
    } else {
        if (confirm("Are you sure that you want to verify the task?")) {
            const queryURL = "/tasks/info?key=" + keyString + "&status=" + "COMPLETE";
            const request = new Request(queryURL, {method: "POST"});
            const response = await fetch(request);
            showNeedHelp();
        }
    }
}

async function disapproveTask(keyString) {
    const info = await getTaskInfo(keyString);
    if (info.status === "COMPLETE") {
        window.alert("You have already verified the task.");
    } else {
        if (confirm("Are you sure that you want to disapprove the task?")) {
            const queryURL = "/tasks/info?key=" + keyString + "&status=" + "IN PROGRESS";
            const request = new Request(queryURL, {method: "POST"});
            const response = await fetch(request);
            showNeedHelp();
        }
    }
}

function showNeedHelp() {
    document.getElementById("need-help").style.display = "table";
    document.getElementById("create").style.display = "block";
    document.getElementById("offer-help").style.display = "none";
    document.getElementById("await-verif").style.display = "table";
    document.getElementById("complete-task").style.display = "none";
    document.getElementById("need-help-button").style.backgroundColor = "#3e8e41";
    document.getElementById("offer-help-button").style.backgroundColor = "#4CAF50";
    displayNeedHelpTasks();
    displayNeedHelpCompleteTasks();
}

function showOfferHelp() {
    document.getElementById("need-help").style.display = "none";
    document.getElementById("create").style.display = "none";
    document.getElementById("offer-help").style.display = "table";
    document.getElementById("await-verif").style.display = "none";
    document.getElementById("complete-task").style.display = "table";
    document.getElementById("need-help-button").style.backgroundColor = "#4CAF50";
    document.getElementById("offer-help-button").style.backgroundColor = "#3e8e41";
    displayOfferHelpTasks();
    displayOfferHelpCompleteTasks();
}

function showModal() {
    var modal = document.getElementById("createTaskModalWrapper");
    modal.style.display = "block";
}

function showInfoModal() {
    var modal = document.getElementById("updateInfoModalWrapper");
    modal.style.display = "block";
}

function closeModal() {
    var modal = document.getElementById("createTaskModalWrapper");
    modal.style.display = "none";
}

function closeEditModal() {
    var modal = document.getElementById("editTaskModalWrapper");
    modal.style.display = "none";
}

function closeInfoModal() {
    var modal = document.getElementById("updateInfoModalWrapper");
    modal.style.display = "none";
}

// If the user clicks outside of the modal, closes the modal directly
window.onclick = function(event) {
    var modal = document.getElementById("createTaskModalWrapper");
    if (event.target == modal) {
        modal.style.display = "none";
    }
    var editModal = document.getElementById("editTaskModalWrapper");
    if (event.target == editModal) {
        editModal.style.display = "none";
    }
}

async function displayNeedHelpTasks() {
    const queryURL = "/mytasks?keyword=Owner&complete=False";
    const request = new Request(queryURL, {method: "GET"});
    const response = await fetch(request);
    const taskResponse = await response.json();
    const needHelpBody = document.getElementById("need-help-body");
    needHelpBody.innerHTML = "";
    for (var index = 0; index < taskResponse.length; index++) {
        var tr = document.createElement("tr");
        var task = taskResponse[index];
        var data = [task.detail, task.helper, task.status];
        for (var i = 0; i < data.length; i++) {
            var td = document.createElement("td");
            td.appendChild(document.createTextNode(data[i]));
            tr.appendChild(td);
        }
        const keyStringCopy = task.keyString.slice();
        var editTd = document.createElement("td");
        var editBtn = document.createElement("button");
        editBtn.className = "edit-task";
        editBtn.addEventListener("click", function () { editTask(keyStringCopy) });
        editBtn.innerHTML = (task.status === "OPEN") ? '':'';
        editTd.appendChild(editBtn);
        var deleteTd = document.createElement("td");
        var deleteBtn = document.createElement("button");
        deleteBtn.className = "delete-task";
        deleteBtn.addEventListener("click", function () { deleteTask(keyStringCopy) });
        deleteBtn.innerHTML = (task.status === "OPEN") ? '':'';
        deleteTd.appendChild(deleteBtn);
        tr.appendChild(editTd);
        tr.appendChild(deleteTd);
        needHelpBody.appendChild(tr);
    }
}

async function displayNeedHelpCompleteTasks() {
    const queryURL = "/mytasks?keyword=Owner&complete=True";
    const request = new Request(queryURL, {method: "GET"});
    const response = await fetch(request);
    const taskResponse = await response.json();
    const completeTaskBody = document.getElementById("await-verif-body");
    completeTaskBody.innerHTML = "";
    for (var index = 0; index < taskResponse.length; index++) {
        var tr = document.createElement("tr");
        var task = taskResponse[index];
        var data = [task.detail, task.helper, task.status];
        for (var i = 0; i < data.length; i++) {
            var td = document.createElement("td");
            td.appendChild(document.createTextNode(data[i]));
            tr.appendChild(td);
        }
        const keyStringCopy = task.keyString.slice();
        var verifyTd = document.createElement("td");
        var verifyBtn = document.createElement("button");
        verifyBtn.className = "verify-task";
        verifyBtn.addEventListener("click", function () { verifyTask(keyStringCopy) });
        verifyBtn.innerHTML = (task.status !== "COMPLETE") ? '':'';
        verifyTd.appendChild(verifyBtn);
        var disapproveTd = document.createElement("td");
        var disapproveBtn = document.createElement("button");
        disapproveBtn.className = "disapprove-task";
        disapproveBtn.addEventListener("click", function () { disapproveTask(keyStringCopy) });
        disapproveBtn.innerHTML = (task.status !== "COMPLETE") ? '':'';
        disapproveTd.appendChild(disapproveBtn);
        tr.appendChild(verifyTd);
        tr.appendChild(disapproveTd);
        completeTaskBody.appendChild(tr);
    }
}

async function displayOfferHelpTasks() {
    const queryURL = "/mytasks?keyword=Helper&complete=False";
    const request = new Request(queryURL, {method: "GET"});
    const response = await fetch(request);
    const taskResponse = await response.json();
    const offerHelpBody = document.getElementById("offer-help-body");
    offerHelpBody.innerHTML = "";
    for (var index = 0; index < taskResponse.length; index++) {
        var tr = document.createElement("tr");
        var task = taskResponse[index];
        var data = [task.detail, task.status, task.owner];
        for (var i = 0; i < data.length; i++) {
            var td = document.createElement("td");
            td.appendChild(document.createTextNode(data[i]));
            tr.appendChild(td);
        }
        const keyStringCopy = task.keyString.slice();
        var completeTd = document.createElement("td");
        var completeBtn = document.createElement("button");
        completeBtn.className = "complete-task";
        completeBtn.addEventListener("click", function () { completeTask(keyStringCopy) });
        completeBtn.innerHTML = (task.status === "IN PROGRESS") ? '':'';
        completeTd.appendChild(completeBtn);
        var abandonTd = document.createElement("td");
        var abandonBtn = document.createElement("button");
        abandonBtn.className = "abandon-task";
        abandonBtn.addEventListener("click", function () { abandonTask(keyStringCopy) });
        abandonBtn.innerHTML = (task.status === "IN PROGRESS") ? '':'';;
        abandonTd.appendChild(abandonBtn);
        tr.appendChild(completeTd);
        tr.appendChild(abandonTd);
        offerHelpBody.appendChild(tr);
    }
}

async function displayOfferHelpCompleteTasks() {
    const queryURL = "/mytasks?keyword=Helper&complete=True";
    const request = new Request(queryURL, {method: "GET"});
    const response = await fetch(request);
    const taskResponse = await response.json();
    const completeTaskBody = document.getElementById("complete-task-body");
    completeTaskBody.innerHTML = "";
    for (var index = 0; index < taskResponse.length; index++) {
        var tr = document.createElement("tr");
        var task = taskResponse[index];
        var data = [task.detail, task.status, task.owner, task.reward.toString()];
        for (var i = 0; i < data.length; i++) {
            var td = document.createElement("td");
            td.appendChild(document.createTextNode(data[i]));
            tr.appendChild(td);
        }
        completeTaskBody.appendChild(tr);
    }
}<|endoftext|>


<commit_before>/*global console*/
var yetify = require('yetify'),
    config = require('getconfig'),
    uuid = require('node-uuid'),
    crypto = require('crypto'),
    port = parseInt(process.env.PORT || config.server.port, 10),
    express = require('express'),
    app = express(),
    app_server = require('http').createServer(app),
    io = require('socket.io')(app_server);

/*io.set('transports', ['websocket']);*/

app_server.listen(port);

app.use(express.static(__dirname + '/'));

if (config.logLevel) {
    // https://github.com/Automattic/socket.io/wiki/Configuring-Socket.IO
    io.set('log level', config.logLevel);
}
//setInterval(function(){console.log(io.sockets.adapter.rooms['mortar']);}, 3000);
function describeRoom(name) {
    var clients = io.nsps['/'].adapter.rooms[name];
    var result = {
        clients: {}
    };
    for(var i in clients) {
        result.clients[i] = io.nsps['/'].connected[i].resources;
    }
    return result;
}

function safeCb(cb) {
    if (typeof cb === 'function') {
        return cb;
    } else {
        return function () {};
    }
}

io.sockets.on('connection', function (client) {
    client.resources = {
        screen: false,
        video: true,
        audio: false
    };

    // pass a message to another id
    client.on('message', function (details) {
        if (!details) return;

        var otherClient = io.sockets.connected[details.to];
        if (!otherClient) return;

        details.from = client.id;
        otherClient.emit('message', details);
    });

    client.on('shareScreen', function () {
        client.resources.screen = true;
    });

    client.on('unshareScreen', function (type) {
        client.resources.screen = false;
        removeFeed('screen');
    });

    client.on('join', join);

    function removeFeed(type) {
        if (client.room) {
            io.sockets.in(client.room).emit('remove', {
                id: client.id,
                type: type
            });
            if (!type) {
                client.leave(client.room);
                client.room = undefined;
            }
        }
    }

    function join(name, cb) {
        // sanity check
        if (typeof name !== 'string') return;
        // leave any existing rooms
        removeFeed();
        client.join(name);
        client.room = name;
        safeCb(cb)(null, describeRoom(name));
    }

    // we don't want to pass "leave" directly because the
    // event type string of "socket end" gets passed too.
    client.on('disconnect', function () {
        removeFeed();
    });
    client.on('leave', function () {
        removeFeed();
    });

    client.on('create', function (name, cb) {
        if (arguments.length == 2) {
            cb = (typeof cb == 'function') ? cb : function () {};
            name = name || uuid();
        } else {
            cb = name;
            name = uuid();
        }
        // check if exists
        var nexs = true;
        if (typeof io.nsps['/'].adapter.rooms[name] !== 'undefined') {
            if(io.nsps['/'].adapter.rooms[name].length) {
               safeCb(cb)('taken');
               nexs = false;
            }
        }
        if(nexs) {
            join(name);
            safeCb(cb)(null, name);
        }
    });

    // tell client about stun and turn servers and generate nonces
    client.emit('stunservers', config.stunservers || []);

    // create shared secret nonces for TURN authentication
    // the process is described in draft-uberti-behave-turn-rest
    var credentials = [];
    config.turnservers.forEach(function (server) {
        var hmac = crypto.createHmac('sha1', server.secret);
        // default to 86400 seconds timeout unless specified
        var username = Math.floor(new Date().getTime() / 1000) + (server.expiry || 86400) + "";
        hmac.update(username);
        credentials.push({
            username: username,
            credential: hmac.digest('base64'),
            url: server.url
        });
    });
    client.emit('turnservers', credentials);
});

if (config.uid) process.setuid(config.uid);
console.log(yetify.logo() + ' -- signal master is running at: http://localhost:' + port);
<commit_msg>don't send his id for himself<commit_after>/*global console*/
var yetify = require('yetify'),
    config = require('getconfig'),
    uuid = require('node-uuid'),
    crypto = require('crypto'),
    port = parseInt(process.env.PORT || config.server.port, 10),
    express = require('express'),
    app = express(),
    app_server = require('http').createServer(app),
    io = require('socket.io')(app_server);

/*io.set('transports', ['websocket']);*/

app_server.listen(port);

app.use(express.static(__dirname + '/'));

if (config.logLevel) {
    // https://github.com/Automattic/socket.io/wiki/Configuring-Socket.IO
    io.set('log level', config.logLevel);
}
//setInterval(function(){console.log(io.sockets.adapter.rooms['mortar']);}, 3000);
function describeRoom(name) {
    var clients = io.nsps['/'].adapter.rooms[name];
    var result = {
        clients: {}
    };
    for(var i in clients) {
        result.clients[i] = io.nsps['/'].connected[i].resources;
    }
    return result;
}

function safeCb(cb) {
    if (typeof cb === 'function') {
        return cb;
    } else {
        return function () {};
    }
}

io.sockets.on('connection', function (client) {
    client.resources = {
        screen: false,
        video: true,
        audio: false
    };

    // pass a message to another id
    client.on('message', function (details) {
        if (!details) return;

        var otherClient = io.sockets.connected[details.to];
        if (!otherClient) return;

        details.from = client.id;
        otherClient.emit('message', details);
    });

    client.on('shareScreen', function () {
        client.resources.screen = true;
    });

    client.on('unshareScreen', function (type) {
        client.resources.screen = false;
        removeFeed('screen');
    });

    client.on('join', join);

    function removeFeed(type) {
        if (client.room) {
            io.sockets.in(client.room).emit('remove', {
                id: client.id,
                type: type
            });
            if (!type) {
                client.leave(client.room);
                client.room = undefined;
            }
        }
    }

    function join(name, cb) {
        // sanity check
        if (typeof name !== 'string') return;
        // leave any existing rooms
        removeFeed();
        safeCb(cb)(null, describeRoom(name));
        client.join(name);
        client.room = name;
    }

    // we don't want to pass "leave" directly because the
    // event type string of "socket end" gets passed too.
    client.on('disconnect', function () {
        removeFeed();
    });
    client.on('leave', function () {
        removeFeed();
    });

    client.on('create', function (name, cb) {
        if (arguments.length == 2) {
            cb = (typeof cb == 'function') ? cb : function () {};
            name = name || uuid();
        } else {
            cb = name;
            name = uuid();
        }
        // check if exists
        var nexs = true;
        if (typeof io.nsps['/'].adapter.rooms[name] !== 'undefined') {
            if(io.nsps['/'].adapter.rooms[name].length) {
               safeCb(cb)('taken');
               nexs = false;
            }
        }
        if(nexs) {
            join(name);
            safeCb(cb)(null, name);
        }
    });

    // tell client about stun and turn servers and generate nonces
    client.emit('stunservers', config.stunservers || []);

    // create shared secret nonces for TURN authentication
    // the process is described in draft-uberti-behave-turn-rest
    var credentials = [];
    config.turnservers.forEach(function (server) {
        var hmac = crypto.createHmac('sha1', server.secret);
        // default to 86400 seconds timeout unless specified
        var username = Math.floor(new Date().getTime() / 1000) + (server.expiry || 86400) + "";
        hmac.update(username);
        credentials.push({
            username: username,
            credential: hmac.digest('base64'),
            url: server.url
        });
    });
    client.emit('turnservers', credentials);
});

if (config.uid) process.setuid(config.uid);
console.log(yetify.logo() + ' -- signal master is running at: http://localhost:' + port);
<|endoftext|>


<commit_before>var app, express, io, server, uuid, ws, appPort;

express = require('express');
app = express();
ws = require('websocket.io');
uuid = require('node-uuid');
port = process.env.PORT || process.env.OPENSHIFT_NODEJS_PORT || 8080,
ip   = process.env.IP   || process.env.OPENSHIFT_NODEJS_IP || '0.0.0.0';

app.configure(function () {
    app.use(express.static(__dirname + '/page'));
});

app.set('port', process.env.PORT || 3000);

app.get('/:group', function(req, res) { //
    var _ref;
    return res.render('index.jade', {
        params: req.query,
        groupCount: ((_ref = io.clientsByGroup[req.params.group]) != null ? _ref.length : void 0) || 0
    });
});

server = app.listen(port, ip);

io = ws.attach(server);

io.clientsById || (io.clientsById = {});
io.clientsByGroup || (io.clientsByGroup = {});

io.on('connection', function(socket) {
    var group, _base;

    group = (socket.req.url !="/") ? /\/(.+)/.exec(socket.req.url)[1] : ":base";
    socket.id = uuid.v1();
    socket.group = group;

    if (!group) {
        socket.close();
        return;
    }

    (_base = io.clientsByGroup)[group] || (_base[group] = []);

    io.clientsByGroup[group].push(socket);
    io.clientsById[socket.id] = socket;

    socket.send(
        JSON.stringify({
            type: 'uuid',
            id: socket.id
        })
    );

    socket.send(
        JSON.stringify({
            type: 'node-debug',
            key: 'group',
            value: group
        })
    );

    return socket.on('message', function(data) {
        var msg, sock, i, length, _ref, results;
        msg = JSON.parse(data);

        switch (msg.type) {
            case 'offered':
            case 'candidate':
            case 'answered':
                _ref = io.clientsByGroup[socket.group];
                results = [];
                for (i = 0, length = _ref.length; i < length; i++) {
                  sock = _ref[i];
                    if (sock.id !== socket.id) {
                        results.push(sock.send(JSON.stringify(msg)));
                    } else {
                        results.push(void 0);
                    }
                }
                return results;
                break;
            case 'close':
                return socket.close();
        }
    });
});

module.exports = app;
<commit_msg>Triggering Heroku build<commit_after>var app, express, io, server, uuid, ws, appPort;

express = require('express');
app = express();
ws = require('websocket.io');
uuid = require('node-uuid');
port = process.env.PORT || process.env.OPENSHIFT_NODEJS_PORT || 8080,
ip   = process.env.IP   || process.env.OPENSHIFT_NODEJS_IP || '0.0.0.0';

app.configure(function () {
    app.use(express.static(__dirname + '/page'));
});

app.set('port', process.env.PORT || 3000);

app.get('/:group', function(req, res) { //
    var _ref;
    return res.render('index.jade', {
        params: req.query,
        groupCount: ((_ref = io.clientsByGroup[req.params.group]) != null ? _ref.length : void 0) || 0
    });
});

server = app.listen(port, ip);
io = ws.attach(server);

io.clientsById || (io.clientsById = {});
io.clientsByGroup || (io.clientsByGroup = {});

io.on('connection', function(socket) {
    var group, _base;

    group = (socket.req.url !="/") ? /\/(.+)/.exec(socket.req.url)[1] : ":base";
    socket.id = uuid.v1();
    socket.group = group;

    if (!group) {
        socket.close();
        return;
    }

    (_base = io.clientsByGroup)[group] || (_base[group] = []);

    io.clientsByGroup[group].push(socket);
    io.clientsById[socket.id] = socket;

    socket.send(
        JSON.stringify({
            type: 'uuid',
            id: socket.id
        })
    );

    socket.send(
        JSON.stringify({
            type: 'node-debug',
            key: 'group',
            value: group
        })
    );

    return socket.on('message', function(data) {
        var msg, sock, i, length, _ref, results;
        msg = JSON.parse(data);

        switch (msg.type) {
            case 'offered':
            case 'candidate':
            case 'answered':
                _ref = io.clientsByGroup[socket.group];
                results = [];
                for (i = 0, length = _ref.length; i < length; i++) {
                  sock = _ref[i];
                    if (sock.id !== socket.id) {
                        results.push(sock.send(JSON.stringify(msg)));
                    } else {
                        results.push(void 0);
                    }
                }
                return results;
                break;
            case 'close':
                return socket.close();
        }
    });
});

module.exports = app;
<|endoftext|>


<commit_before>(function(){
    'use strict';

    angular
    .module('lolTot.core')
    .factory('interceptor', interceptor);

    function interceptor($q, $injector){

        return {
            responseError: function(res){
                var $mdToast = $injector.get('$mdToast');

                var messages = {
                    0: 'Servicio no disponible, report RITO',
                    401: 'Acceso denegado, report Galleto',
                    404: 'El recurso solicitado ha entrado en sigilo',
                    500: 'Se produjo un error en el servidor',
                    503: 'Servicio no disponible :('
                };

                var dontNotify = res.config.dontNotify;

                if(!dontNotify && messages[res.status]){
                    $mdToast.show(
                        $mdToast.simple()
                        .content(messages[res.status])
                        .hideDelay(3000)
                    );
                }

                return $q.reject(res);
            }
        };
    }

})();
<commit_msg>new 0 error<commit_after>(function(){
    'use strict';

    angular
    .module('lolTot.core')
    .factory('interceptor', interceptor);

    function interceptor($q, $injector){

        return {
            responseError: function(res){
                var $mdToast = $injector.get('$mdToast');

                var messages = {
                    0: 'Servicio no disponible, report rito',
                    401: 'Acceso denegado, report Galleto',
                    404: 'El recurso solicitado ha entrado en sigilo',
                    500: 'Se produjo un error en el servidor',
                    503: 'Servicio no disponible :('
                };

                var dontNotify = res.config.dontNotify;

                if(!dontNotify && messages[res.status]){
                    $mdToast.show(
                        $mdToast.simple()
                        .content(messages[res.status])
                        .hideDelay(3000)
                    );
                }

                return $q.reject(res);
            }
        };
    }

})();
<|endoftext|>


<commit_before>describe('V 1.4 Activities and Assessments', function() {

  var event_payloads, interactions;
  var auditDataDict, auditSource, auditIsAsync;

  function checkAuditValues(expectedData, expectedSource, expectedAsync) {
    expect(auditDataDict).toBe(JSON.stringify(expectedData));
    expect(auditSource).toBe(expectedSource);
    expect(auditIsAsync).toBe(expectedAsync);
  }

  beforeEach(function() {
    jasmine.getFixtures().fixturesPath = 'base/';
    loadFixtures(
      'tests/unit/javascript_tests/assets_lib_activity_generic/fixture.html');
    event_payloads = JSON.parse(
      readFixtures('tests/unit/common/event_payloads.json'));
    interactions = eval('(' +
      readFixtures('tests/unit/javascript_tests/assets_lib_activity_generic/interactions.js') +
      ')');

    // Mock global variables used by activity-generic
    window.trans = {};
    window.assessmentGlobals = {};
    window.transientStudent = false;

    // Enable post events
    window.gcbCanPostTagEvents = true;
    window.gcbCanPostPageEvents = true;
    window.gcbCanPostEvents = true;

    // Reset tag so that test order doesn't matter
    window.globallyUniqueTag = 0;

    // Clear audit data
    auditDataDict = '';
    auditSource = '';
    auditIsAsync = '';

    // Mock the function used for callbacks by all event emitters
    window.gcbAudit = function (data_dict, source, is_async) {
      auditDataDict = JSON.stringify(data_dict);
      auditSource = source;
      auditIsAsync = is_async;
    };
  });

  it('can generate events for multiple choice activity', function() {
    var activity = interactions.multiple_choice_activity;
    var expectedEvent = event_payloads.multiple_choice_activity;
    window.renderActivity(activity, $('#activityContents'));

    // Select the first choice and click submit
    $('#q1-0').click();
    $('#submit_1').click();

    checkAuditValues(expectedEvent.event_data, expectedEvent.event_source,
                     expectedEvent.event_async);
  });

  it('can generate events for multiple choice group activity', function() {
    var activity = interactions.multiple_choice_group_activity;
    var expectedEvent = event_payloads.multiple_choice_group_activity;
    window.renderActivity(activity, $('#activityContents'));

    // Select the first choice for question 1, the second for question 2, and
    // click submit
    $('#q1-0-0').click();
    $('#q2-1-1').click();
    $('#submit_3').click();

    checkAuditValues(expectedEvent.event_data, expectedEvent.event_source,
                     expectedEvent.event_async);
  });

  it('can generate events for freetext activity', function() {
    var activity = interactions.free_text_activity;
    var expectedEvent = event_payloads.free_text_activity;
    window.renderActivity(activity, $('#activityContents'));

    // Enter a correct answer and click submit
    $('#input_1').val("42");
    $('#submit_1').click();

    checkAuditValues(expectedEvent.event_data, expectedEvent.event_source,
                     expectedEvent.event_async);
  });

  it('can generate events for mixed assessment', function() {
    var assessment = interactions.mixed_assessment;
    var expectedEvent = event_payloads.mixed_assessment;

    window.renderAssessment(assessment, $('#assessmentContents'));

    // Enter correct answers for all four question and click submit
    $('#q0-0').click();
    $('#q1').val("Rectus");
    $('#q2').val("match");
    $('#q3').val("42.0");
    $('#checkAnswersBtn').click();

    checkAuditValues(expectedEvent.event_data, expectedEvent.event_source,
                     expectedEvent.event_async);
  });
});
<commit_msg>Adding location information to events_payloads, handling the additions in tests.js 	Change on 2013/08/13 by emichael <emichael@google.com> ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=50807031<commit_after>describe('V 1.4 Activities and Assessments', function() {

  var event_payloads, interactions;
  var auditDataDict, auditSource, auditIsAsync;

  function checkAuditValues(expectedData, expectedSource, expectedAsync,
                            windowLocation) {
    // This addition to the data dict mocks the corresponding action in gcbAudit
    auditDataDict['location'] = windowLocation;

    expect(auditDataDict).toEqual(expectedData);
    expect(auditSource).toBe(expectedSource);
    expect(auditIsAsync).toBe(expectedAsync);
  }

  beforeEach(function() {
    jasmine.getFixtures().fixturesPath = 'base/';
    loadFixtures(
      'tests/unit/javascript_tests/assets_lib_activity_generic/fixture.html');
    event_payloads = JSON.parse(
      readFixtures('tests/unit/common/event_payloads.json'));
    interactions = eval('(' +
      readFixtures('tests/unit/javascript_tests/assets_lib_activity_generic/interactions.js') +
      ')');

    // Mock global variables used by activity-generic
    window.trans = {};
    window.assessmentGlobals = {};
    window.transientStudent = false;

    // Enable post events
    window.gcbCanPostTagEvents = true;
    window.gcbCanPostPageEvents = true;
    window.gcbCanPostEvents = true;

    // Reset tag so that test order doesn't matter
    window.globallyUniqueTag = 0;

    // Clear audit data
    auditDataDict = '';
    auditSource = '';
    auditIsAsync = '';

    // Mock the function used for callbacks by all event emitters
    window.gcbAudit = function (data_dict, source, is_async) {
      auditDataDict = data_dict;
      auditSource = source;
      auditIsAsync = is_async;
    };
  });

  it('can generate events for multiple choice activity', function() {
    var activity = interactions.multiple_choice_activity;
    var expectedEvent = event_payloads.multiple_choice_activity;
    window.renderActivity(activity, $('#activityContents'));

    // Select the first choice and click submit
    $('#q1-0').click();
    $('#submit_1').click();

    checkAuditValues(expectedEvent.event_data, expectedEvent.event_source,
                     expectedEvent.event_async,
                     expectedEvent.event_data.location);
  });

  it('can generate events for multiple choice group activity', function() {
    var activity = interactions.multiple_choice_group_activity;
    var expectedEvent = event_payloads.multiple_choice_group_activity;
    window.renderActivity(activity, $('#activityContents'));

    // Select the first choice for question 1, the second for question 2, and
    // click submit
    $('#q1-0-0').click();
    $('#q2-1-1').click();
    $('#submit_3').click();

    checkAuditValues(expectedEvent.event_data, expectedEvent.event_source,
                     expectedEvent.event_async,
                     expectedEvent.event_data.location);
  });

  it('can generate events for freetext activity', function() {
    var activity = interactions.free_text_activity;
    var expectedEvent = event_payloads.free_text_activity;
    window.renderActivity(activity, $('#activityContents'));

    // Enter a correct answer and click submit
    $('#input_1').val("42");
    $('#submit_1').click();

    checkAuditValues(expectedEvent.event_data, expectedEvent.event_source,
                     expectedEvent.event_async,
                     expectedEvent.event_data.location);
  });

  it('can generate events for mixed assessment', function() {
    var assessment = interactions.mixed_assessment;
    var expectedEvent = event_payloads.mixed_assessment;
    window.renderAssessment(assessment, $('#assessmentContents'));

    // Enter correct answers for all four question and click submit
    $('#q0-0').click();
    $('#q1').val("Rectus");
    $('#q2').val("match");
    $('#q3').val("42.0");
    $('#checkAnswersBtn').click();

    checkAuditValues(expectedEvent.event_data, expectedEvent.event_source,
                     expectedEvent.event_async,
                     expectedEvent.event_data.location);
  });
});
<|endoftext|>


<commit_before>import fs from 'fs-extra'
import archiver from 'archiver'
import {remote} from 'electron'
import tabStore from '@/store/modules/tabs.js'
import hotStore from '@/store/modules/hots.js'
import {extractNameFromFile} from '@/store/tabStoreUtilities.js'
const Dialog = remote.dialog

export function createZipFile(json) {
  Dialog.showSaveDialog({
    filters: [
      {
        name: '*',
        extensions: ['zip']
      }
    ]
  }, function(filename) {
    if (filename === undefined) {
      return
    }
    generateDataPackage(filename, json)
  })
}

function generateDataPackage(filename, json) {
  let output = fs.createWriteStream(filename)
  let archive = archiver('zip', {
    zlib: {
      level: 9
    } // Sets the compression level.
  })
  output.on('close', () => {
    console.log(archive.pointer() + ' total bytes')
    console.log('archiver has been finalized and the output file descriptor has closed.')
  }).on('end', () => {
    console.log('Data has been drained')
  })
  archive.on('warning', function(err) {
    if (err.code === 'ENOENT') {
      // log warning
    } else {
      // throw error
      throw err
    }
  }).on('error', function(err) {
    throw err
  })
  archive.pipe(output)
  zipJson(archive, json)
  zipResources(archive)
  zipProvenanceProperties(archive)
  archive.finalize()
}

function zipJson(archive, json) {
  archive.append(json, { name: 'datapackage.json' })
}

function zipResources(archive) {
  for (let filename of tabStore.getters.getTabFilenames(tabStore.state)) {
    let name = extractNameFromFile(filename)
    archive.append(fs.createReadStream(filename), { name: name, prefix: 'data' })
  }
}

function zipProvenanceProperties(archive) {
  let provenance = hotStore.state.provenanceProperties.markdown
  archive.append(provenance, { name: 'Readme.md' })
}
<commit_msg>OCC-61: corrected logic to keep extension for resource path intact on zip.<commit_after>import fs from 'fs-extra'
import path from 'path'
import archiver from 'archiver'
import {remote} from 'electron'
import tabStore from '@/store/modules/tabs.js'
import hotStore from '@/store/modules/hots.js'
import {extractNameFromFile} from '@/store/tabStoreUtilities.js'
const Dialog = remote.dialog

export function createZipFile(json) {
  Dialog.showSaveDialog({
    filters: [
      {
        name: '*',
        extensions: ['zip']
      }
    ]
  }, function(filename) {
    if (filename === undefined) {
      return
    }
    generateDataPackage(filename, json)
  })
}

function generateDataPackage(filename, json) {
  let output = fs.createWriteStream(filename)
  let archive = archiver('zip', {
    zlib: {
      level: 9
    } // Sets the compression level.
  })
  output.on('close', () => {
    console.log(archive.pointer() + ' total bytes')
    console.log('archiver has been finalized and the output file descriptor has closed.')
  }).on('end', () => {
    console.log('Data has been drained')
  })
  archive.on('warning', function(err) {
    if (err.code === 'ENOENT') {
      // log warning
    } else {
      // throw error
      throw err
    }
  }).on('error', function(err) {
    throw err
  })
  archive.pipe(output)
  zipJson(archive, json)
  zipResources(archive)
  zipProvenanceProperties(archive)
  archive.finalize()
}

function zipJson(archive, json) {
  archive.append(json, { name: 'datapackage.json' })
}

function zipResources(archive) {
  for (let filename of tabStore.getters.getTabFilenames(tabStore.state)) {
    let name = path.basename(filename)
    archive.append(fs.createReadStream(filename), { name: name, prefix: 'data' })
  }
}

function zipProvenanceProperties(archive) {
  let provenance = hotStore.state.provenanceProperties.markdown
  archive.append(provenance, { name: 'Readme.md' })
}
<|endoftext|>


<commit_before>var charts = require("./charts.js"),
        express = require('express'),
        supportedChartLibs = ["highcharts"];

// handle command line args
var args = require('commander');
args
        .option('--debug', 'Debug')
        .option('-p, --port <port>', 'Port to listen', 3000)
        .version('0.0.1');
args.parse(process.argv);

process.on('uncaughtException', function (e) {
    console.error(e.message);
    console.error(e.stack);
});

var app = express.createServer(express.bodyParser());
if (args.debug) {
    app.use(express.logger());
}

function handleChartReq(req, res) {
    if (args.debug) {
        req.start_time = new Date().getTime();
    }
    var chartLib = req.params.chartLib;
    var chartOptions = req.params.chartOptions || req.body.chartOptions;

    if (!chartLib || !chartOptions || supportedChartLibs.indexOf(chartLib) < 0) {
        res.statusCode = 404;
        return res.end();
    }

    var resultSvgCallback = function (err, svg) {
        if (err || !svg) {
            res.statusCode = 500;
            res.end("Error occurred: " + err);
        } else {
            if (args.debug) {
                console.log("Chart generation takes: " + (new Date().getTime() - req.start_time) / 1000 + "ms")
            }
            res.writeHead(200, {'Content-Type':'image/svg+xml'});
            res.end(svg);
        }
    };

    try {
        chartOptions = JSON.parse(chartOptions);
    } catch (e) {
        return resultSvgCallback()
    }

    // default chart
    if (!chartOptions || !chartOptions.series) {
        chartOptions = {
            chart:{
                renderTo:'container',
                type:'line',
                marginRight:130,
                marginBottom:25
            },
            title:{
                text:'Monthly Average Temperature',
                x:-20 //center
            },
            subtitle:{
                text:'Source: WorldClimate.com',
                x:-20
            },
            credits:{
                text:"Buglite"
            },
            xAxis:{
                categories:['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                    'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
            },
            yAxis:{
                title:{
                    text:'Temperature (°C)'
                },
                plotLines:[
                    {
                        value:0,
                        width:1,
                        color:'#808080'
                    }
                ]
            },
            legend:{
                layout:'vertical',
                align:'right',
                verticalAlign:'top',
                x:-10,
                y:100,
                borderWidth:0
            },
            series:[
                {
                    name:'Tokyo',
                    data:[7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
                },
                {
                    name:'New York',
                    data:[-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5]
                },
                {
                    name:'Berlin',
                    data:[-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0]
                },
                {
                    name:'London',
                    data:[3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8]
                }
            ]
        };
    }

    if ("highcharts" == chartLib) {
        return charts.renderHighcharts(chartOptions, resultSvgCallback);
    } else {
        res.statusCode = 404;
        return res.end("Unsupported chart lib");
    }
}

app.get('/chart/:chartLib/:chartOptions', handleChartReq);
app.post("/chart/:chartLib", handleChartReq);

//todo extract port to args
app.listen(3000);
<commit_msg>logging improved<commit_after>var charts = require("./charts.js"),
        express = require('express'),
        supportedChartLibs = ["highcharts"];

// handle command line args
var args = require('commander');
args
        .option('--debug', 'Debug')
        .option('-p, --port <port>', 'Port to listen', 3000)
        .version('0.0.1');
args.parse(process.argv);

process.on('uncaughtException', function (e) {
    console.error(e.message);
    console.error(e.stack);
});

var app = express.createServer(express.bodyParser());
if (args.debug) {
    app.use(express.logger());
}

function handleChartReq(req, res) {
    if (args.debug) {
        req.start_time = new Date().getTime();
    }
    var chartLib = req.params.chartLib;
    var chartOptions = req.params.chartOptions || req.body.chartOptions;

    if (!chartLib || !chartOptions || supportedChartLibs.indexOf(chartLib) < 0) {
        res.statusCode = 404;
        return res.end();
    }

    var resultSvgCallback = function (err, svg) {
        if (err || !svg) {
            res.statusCode = 500;
            res.end("Error occurred: " + err);
        } else {
            if (args.debug) {
                console.log("Chart generation takes: " + (new Date().getTime() - req.start_time) / 1000 + "ms")
            }
            res.writeHead(200, {'Content-Type':'image/svg+xml'});
            res.end(svg);
        }
    };

    try {
        chartOptions = JSON.parse(chartOptions);
    } catch (e) {
        return resultSvgCallback()
    }

    // default chart
    if (!chartOptions || !chartOptions.series) {
        chartOptions = {
            chart:{
                renderTo:'container',
                type:'line',
                marginRight:130,
                marginBottom:25
            },
            title:{
                text:'Monthly Average Temperature',
                x:-20 //center
            },
            subtitle:{
                text:'Source: WorldClimate.com',
                x:-20
            },
            credits:{
                text:"Buglite"
            },
            xAxis:{
                categories:['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                    'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
            },
            yAxis:{
                title:{
                    text:'Temperature (°C)'
                },
                plotLines:[
                    {
                        value:0,
                        width:1,
                        color:'#808080'
                    }
                ]
            },
            legend:{
                layout:'vertical',
                align:'right',
                verticalAlign:'top',
                x:-10,
                y:100,
                borderWidth:0
            },
            series:[
                {
                    name:'Tokyo',
                    data:[7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
                },
                {
                    name:'New York',
                    data:[-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5]
                },
                {
                    name:'Berlin',
                    data:[-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0]
                },
                {
                    name:'London',
                    data:[3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8]
                }
            ]
        };
    }

    if ("highcharts" == chartLib) {
        return charts.renderHighcharts(chartOptions, resultSvgCallback);
    } else {
        res.statusCode = 404;
        return res.end("Unsupported chart lib");
    }
}

app.get('/chart/:chartLib/:chartOptions', handleChartReq);
app.post("/chart/:chartLib", handleChartReq);

console.log("node-charts listen on port " + args.port);
app.listen(args.port);
<|endoftext|>


<commit_before>
// notes:
// use SAS for auth
// support stream and auto-resume
// implement starting a file that was started before
// implement checking for an existing file in the container

var express = require("express");
var bodyParser = require("body-parser");
var wasb = require("azure-storage");
var fs = require("fs");
var base64 = require("base64-stream");
var stream = require("stream");

var app = express();
app.use(express.static("client"));

// the current upload queue
var pending = {
    list: [],

    add: function(container, name) {

        var service = wasb.createBlobService("2e2115eastus", "1tnb/X2r4VZNMyKOHmM4bJfollRsF1jId2pVAhTitdmszP4MH7kc39pm97ijhHtteRY5EzuDnkIBBz8tP/2CSQ==");
        // create container if necessary
        var writer = service.createWriteStreamToBlockBlob(container, name, function(error, result, response) {
            if (!error) {
                console.log("transferred");
            } else {
                console.log("failed - " + error);
            }
        });

        writer.on("close", function() {
            console.log("close");
        });

        writer.on("finish", function() {
            console.log("finished");
        });

        var file = {
           container: container,
           name: name,
           sequence: 0,
           writer: writer
        };

        this.list.push(file);
        return file;
    },

    remove: function(container, name) {
        for (var i = 0; i < this.list.length; i++) {
            if (this.list[i].container == container && this.list[i].name == name) {
                this.list.splice(i, 1);
                return;
            }
        }
    },

    find: function(container, name) {
        for (var i = 0; i < this.list.length; i++) {
            if (this.list[i].container == container && this.list[i].name == name) return this.list[i];
        }
        return null;
    }

};

// hello
app.get("/hello", function(req, res) {
   res.send("hello");
});

// home page
app.get("/", function(req, res) {
    res.redirect("/index.htm");
});

// upload all or part of a file
app.post("/upload", function(req, res) {
    if (req.query.container && req.query.name && req.query.cmd && req.query.seq) {
        var file = pending.find(req.query.container, req.query.name);
        var decoder = base64.decode();
        switch(req.query.cmd) {
            case "complete":
                if (!file) {
                    file = pending.add(req.query.container, req.query.name);
                    req.pipe(decoder).pipe(file.writer);
                    pending.remove(req.query.container, req.query.name);
                    res.status(200).end();
                } else {
                    res.status(500).send("the file already exists.");
                }
                break;
            case "begin":
                if (!file) {
                    file = pending.add(req.query.container, req.query.name);
                    req.pipe(decoder).pipe(file.writer, { end: false });
                    file.sequence++;
                    res.status(200).end();
                } else {
                    res.status(500).send("the file already exists.");
                }
                break;
            case "continue":
                if (file.sequence == req.query.seq) {
                    req.pipe(decoder).pipe(file.writer, { end: false });
                    file.sequence++;
                    res.status(200).end();
                } else {
                    res.status(500).send("expected sequence " + file.sequence + " but received " + req.query.seq + ".");
                }
                break;
            case "end":
                if (file.sequence == req.query.seq) {
                    req.pipe(decoder).pipe(file.writer);
                    pending.remove(req.query.container, req.query.name);
                    res.status(200).end();
                } else {
                    res.status(500).send("expected sequence " + file.sequence + " but received " + req.query.seq + ".");
                }
                break;
            case "abort":
                pending.remove(req.query.container, req.query.name);
                res.status(200).end();
        }
    } else {
        res.status(500).send("you must include all query string parameters.");
    }
});

// start the server
var port = process.env.port || 3000;
app.listen(port, function() {
   console.log("listening on port " + port + "...");
});<commit_msg>allow catch-up<commit_after>
// notes:
// use SAS for auth
// support stream and auto-resume
// implement starting a file that was started before
// implement checking for an existing file in the container

var express = require("express");
var bodyParser = require("body-parser");
var wasb = require("azure-storage");
var fs = require("fs");
var base64 = require("base64-stream");
var stream = require("stream");

var app = express();
app.use(express.static("client"));

// the current upload queue
var pending = {
    list: [],

    add: function(container, name) {

        var service = wasb.createBlobService("2e2115eastus", "1tnb/X2r4VZNMyKOHmM4bJfollRsF1jId2pVAhTitdmszP4MH7kc39pm97ijhHtteRY5EzuDnkIBBz8tP/2CSQ==");
        // create container if necessary
        var writer = service.createWriteStreamToBlockBlob(container, name, function(error, result, response) {
            if (!error) {
                console.log("transferred");
            } else {
                console.log("failed - " + error);
            }
        });

        writer.on("close", function() {
            console.log("close");
        });

        writer.on("finish", function() {
            console.log("finished");
        });

        var file = {
           container: container,
           name: name,
           sequence: 0,
           writer: writer
        };

        this.list.push(file);
        return file;
    },

    remove: function(container, name) {
        for (var i = 0; i < this.list.length; i++) {
            if (this.list[i].container == container && this.list[i].name == name) {
                this.list.splice(i, 1);
                return;
            }
        }
    },

    find: function(container, name) {
        for (var i = 0; i < this.list.length; i++) {
            if (this.list[i].container == container && this.list[i].name == name) return this.list[i];
        }
        return null;
    }

};

// hello
app.get("/hello", function(req, res) {
   res.send("hello");
});

// home page
app.get("/", function(req, res) {
    res.redirect("/index.htm");
});

// upload all or part of a file
app.post("/upload", function(req, res) {
    if (req.query.container && req.query.name && req.query.cmd && req.query.seq) {
        var file = pending.find(req.query.container, req.query.name);
        var decoder = base64.decode();
        switch(req.query.cmd) {
            case "complete":
                if (!file) {
                    file = pending.add(req.query.container, req.query.name);
                    req.pipe(decoder).pipe(file.writer);
                    pending.remove(req.query.container, req.query.name);
                    res.status(200).end();
                } else {
                    res.status(500).send("the file already exists.");
                }
                break;
            case "begin":
                if (!file) {
                    file = pending.add(req.query.container, req.query.name);
                    req.pipe(decoder).pipe(file.writer, { end: false });
                    file.sequence++;
                    res.status(200).end();
                } else {
                    res.status(500).send("the file already exists.");
                }
                break;
            case "continue":
                if (file.sequence == req.query.seq) {
                    req.pipe(decoder).pipe(file.writer, { end: false });
                    file.sequence++;
                    res.status(200).end();
                } else if (req.query.seq < file.sequence) {
                    // the request sequence can be lower if it didn't get confirmation of a commit, let it catch up
                    res.status(200).end();
                } else {
                    res.status(500).send("expected sequence " + file.sequence + " but received " + req.query.seq + ".");
                }
                break;
            case "end":
                if (file.sequence == req.query.seq) {
                    req.pipe(decoder).pipe(file.writer);
                    pending.remove(req.query.container, req.query.name);
                    res.status(200).end();
                } else if (req.query.seq < file.sequence) {
                    // the request sequence can be lower if it didn't get confirmation of a commit, let it catch up
                    res.status(200).end();
                } else {
                    res.status(500).send("expected sequence " + file.sequence + " but received " + req.query.seq + ".");
                }
                break;
            case "abort":
                pending.remove(req.query.container, req.query.name);
                res.status(200).end();
        }
    } else {
        res.status(500).send("you must include all query string parameters.");
    }
});

// start the server
var port = process.env.port || 3000;
app.listen(port, function() {
   console.log("listening on port " + port + "...");
});<|endoftext|>


<commit_before>import { createSelector } from 'reselect';

import { selectSpecificEntityState } from './index';
import { getFormInputConfig } from '../../utilities/formInputConfigs';
import { UIDatabase } from '../../database';

export const selectEditingVaccinePrescriptionId = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { creating } = VaccinePrescriptionState;
  const { id } = creating;
  return id;
};

export const selectEditingVaccinePrescription = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { creating } = VaccinePrescriptionState;
  return creating;
};

export const selectPatientSearchFormConfig = createSelector([], () =>
  getFormInputConfig('searchVaccinePatient')
);

export const selectVaccines = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { vaccines } = VaccinePrescriptionState;
  return vaccines;
};

export const selectSelectedVaccines = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { selectedVaccines } = VaccinePrescriptionState;

  return selectedVaccines;
};

export const selectSelectedBatches = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { selectedBatches } = VaccinePrescriptionState;

  return selectedBatches;
};

export const selectSortedVaccines = createSelector([selectVaccines], vaccines => {
  const sortedVaccines = vaccines.sorted('name');

  // Split the items by quantity - showing out-of-stock items at the end of the list.
  const vaccinesWithStock = sortedVaccines.filtered('ANY batches.numberOfPacks > 0').slice();
  const vaccinesWithoutStock = sortedVaccines.filtered('ALL batches.numberOfPacks == 0').slice();

  return [...vaccinesWithStock, ...vaccinesWithoutStock];
});

export const selectSelectedRows = createSelector([selectSelectedVaccines], vaccines =>
  vaccines.reduce((acc, vaccine) => ({ ...acc, [vaccine?.id]: true }), {})
);

export const selectSelectedBatchRows = createSelector([selectSelectedBatches], batches =>
  batches.reduce((acc, itemBatch) => ({ ...acc, [itemBatch?.id]: true }), {})
);

export const selectHasVaccines = () => {
  const vaccines = UIDatabase.objects('Vaccine');
  return vaccines.length > 0;
};

export const selectHasRefused = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { hasRefused } = VaccinePrescriptionState;
  return hasRefused;
};

export const selectSelectedVaccinator = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { vaccinator } = VaccinePrescriptionState;
  return vaccinator;
};

export const selectHaveVaccineStock = () =>
  UIDatabase.objects('Vaccine').filtered(
    'subquery(batches, $batches, $batches.numberOfPacks > 0 ).@count > 0'
  ).length > 0;

export const selectFoundBonusDose = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { bonusDose } = VaccinePrescriptionState;
  return bonusDose;
};

export const selectHistoryIsOpen = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { historyIsOpen } = VaccinePrescriptionState;
  return historyIsOpen;
};

export const selectSelectedSupplementalData = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { supplementalData } = VaccinePrescriptionState;

  return supplementalData;
};

export const selectSupplementalDataIsValid = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { isSupplementalDataValid } = VaccinePrescriptionState;

  return isSupplementalDataValid;
};

export const selectLastSupplementalData = () => {
  const inQuery = UIDatabase.objects('Transaction')
    .filtered("type == 'customer_invoice' AND customData != null")
    .map(({ id }) => `transaction.id == "${id}"`)
    .join(' OR ');
  const fullQuery = `(${inQuery}) AND itemBatch.item.isVaccine == true`;
  const result = inQuery
    ? UIDatabase.objects('TransactionBatch')
        .filtered(fullQuery)
        .sorted('transaction.entryDate', true)
        .slice()
    : [];

  return result.length ? JSON.parse(result[0].transaction.customData) : null;
};
<commit_msg>Dodging eslint :laughing:<commit_after>import { createSelector } from 'reselect';

import { selectSpecificEntityState } from './index';
import { getFormInputConfig } from '../../utilities/formInputConfigs';
import { UIDatabase } from '../../database';

export const selectEditingVaccinePrescriptionId = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { creating } = VaccinePrescriptionState;
  const { id } = creating;
  return id;
};

export const selectEditingVaccinePrescription = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { creating } = VaccinePrescriptionState;
  return creating;
};

export const selectPatientSearchFormConfig = createSelector([], () =>
  getFormInputConfig('searchVaccinePatient')
);

export const selectVaccines = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { vaccines } = VaccinePrescriptionState;
  return vaccines;
};

export const selectSelectedVaccines = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { selectedVaccines } = VaccinePrescriptionState;

  return selectedVaccines;
};

export const selectSelectedBatches = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { selectedBatches } = VaccinePrescriptionState;

  return selectedBatches;
};

export const selectSortedVaccines = createSelector([selectVaccines], vaccines => {
  const sortedVaccines = vaccines.sorted('name');

  // Split the items by quantity - showing out-of-stock items at the end of the list.
  const vaccinesWithStock = sortedVaccines.filtered('ANY batches.numberOfPacks > 0').slice();
  const vaccinesWithoutStock = sortedVaccines.filtered('ALL batches.numberOfPacks == 0').slice();

  return [...vaccinesWithStock, ...vaccinesWithoutStock];
});

export const selectSelectedRows = createSelector([selectSelectedVaccines], vaccines =>
  vaccines.reduce((acc, vaccine) => ({ ...acc, [vaccine?.id]: true }), {})
);

export const selectSelectedBatchRows = createSelector([selectSelectedBatches], batches =>
  batches.reduce((acc, itemBatch) => ({ ...acc, [itemBatch?.id]: true }), {})
);

export const selectHasVaccines = () => {
  const vaccines = UIDatabase.objects('Vaccine');
  return vaccines.length > 0;
};

export const selectHasRefused = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { hasRefused } = VaccinePrescriptionState;
  return hasRefused;
};

export const selectSelectedVaccinator = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { vaccinator } = VaccinePrescriptionState;
  return vaccinator;
};

export const selectHaveVaccineStock = () =>
  UIDatabase.objects('Vaccine').filtered(
    'subquery(batches, $batches, $batches.numberOfPacks > 0 ).@count > 0'
  ).length > 0;

export const selectFoundBonusDose = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { bonusDose } = VaccinePrescriptionState;
  return bonusDose;
};

export const selectHistoryIsOpen = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { historyIsOpen } = VaccinePrescriptionState;
  return historyIsOpen;
};

export const selectSelectedSupplementalData = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { supplementalData } = VaccinePrescriptionState;

  return supplementalData;
};

export const selectSupplementalDataIsValid = state => {
  const VaccinePrescriptionState = selectSpecificEntityState(state, 'vaccinePrescription');
  const { isSupplementalDataValid } = VaccinePrescriptionState;

  return isSupplementalDataValid;
};

export const selectLastSupplementalData = () => {
  const inQuery = UIDatabase.objects('Transaction')
    .filtered("type == 'customer_invoice' AND customData != null")
    .map(({ id }) => `transaction.id == "${id}"`)
    .join(' OR ');
  const fullQuery = `(${inQuery}) AND itemBatch.item.isVaccine == true`;

  if (inQuery) {
    const result = UIDatabase.objects('TransactionBatch')
      .filtered(fullQuery)
      .sorted('transaction.entryDate', true)
      .slice();
    return result.length ? JSON.parse(result[0].transaction.customData) : null;
  }

  return null;
};
<|endoftext|>


<commit_before>'use strict'

var conf = require('./server/config')
var opbeat = require('opbeat').start(conf.opbeat)
var path = require('path')
var express = require('express')

var app = express()

app.use(function (req, res, next) {
  console.log(req.method, req.url)
  next()
})
app.use(require('body-parser').json())
app.use(express.static('client/build'))
app.use('/api', require('./server/routes'))
app.get('*', function (req, res) {
  res.sendFile(path.resolve(__dirname, 'client/build', 'index.html'))
})
app.use(opbeat.middleware.express())

var server = app.listen(conf.server.port, function () {
  var port = server.address().port
  console.log('server is listening on port', port)
})
<commit_msg>Don't log incoming HTTP requests in production<commit_after>'use strict'

var conf = require('./server/config')
var opbeat = require('opbeat').start(conf.opbeat)
var path = require('path')
var express = require('express')

var app = express()

if (conf.env !== 'production') {
  app.use(function (req, res, next) {
    console.log(req.method, req.url)
    next()
  })
}

app.use(require('body-parser').json())
app.use(express.static('client/build'))
app.use('/api', require('./server/routes'))
app.get('*', function (req, res) {
  res.sendFile(path.resolve(__dirname, 'client/build', 'index.html'))
})
app.use(opbeat.middleware.express())

var server = app.listen(conf.server.port, function () {
  var port = server.address().port
  console.log('server is listening on port', port)
})
<|endoftext|>


<commit_before>jQuery.noConflict();

jQuery(function($) {

	// Datepicker
	$('.js-cuztom-datepicker').each(function(){
		$(this).datepicker({ dateFormat: $(this).data('date-format') });
	});

	// Timepicker
	$('.js-cuztom-timepicker').each(function(){
		$(this).timepicker({ timeFormat: $(this).data('time-format') });
	});

	// Datetime
	$('.js-cuztom-datetimepicker').each(function(){
		$(this).datetimepicker({
			timeFormat: $(this).data('time-format'),
			dateFormat: $(this).data('date-format')
		});
	});

	// Colorpicker
	$('.js-cuztom-colorpicker').miniColors();

	// Tabs
	$('.js-cuztom-tabs').tabs();

	// Slider
	$( ".js-slider" ).slider();

	// Accordion
	$('.js-cuztom-accordion').accordion();

	// Sortable
	$('.js-cuztom-sortable').sortable();

	// Remove sortable
	$('.cuztom').on( 'click', '.js-cuztom-remove-sortable', function()
	{
		var that 		= $( this ),
			field 		= that.closest('.js-cuztom-sortable-item'),
			wrap 		= that.closest('.js-cuztom-sortable'),
			fields 		= $( '.js-cuztom-sortable-item', wrap ).length;

		if( fields > 1 ) { field.remove(); }
		if( fields == 2 ){ $( '.js-cuztom-sortable-item', wrap ).find('.js-cuztom-remove-sortable').remove(); }
	});

	// Add sortable
	$('.cuztom').on( 'click', '.js-cuztom-add-sortable', function()
	{
		var that		= $( this ),
			parent 		= that.closest( '.cuztom-td, .cuztom' ),
			wrap 		= $( '.js-cuztom-sortable', parent ),
			is_bundle	= wrap.data( 'cuztom-sortable-type') == 'bundle' ? true : false,
			last 		= $( '.js-cuztom-sortable-item:last', wrap ),
			handle 		= '

',
			remover 	= '

',
			new_item 	= last.clone( true );

		// Set new bundle array key
		if( is_bundle )
		{
			new_item.find('.cuztom-input').each( function() {
				$(this).attr('name', function( i, val ) { return val.replace( /\[(\d+)\]/, function( match, n ) { return "[" + ( Number(n) + 1 ) + "]"; }); })
			});
		}

		// Reset data
		new_item.find('.cuztom-input, textarea, select, .cuztom-hidden').val('').removeAttr('selected');
		new_item.find('.js-cuztom-remove-media').remove();
		new_item.find('.cuztom-preview').html('');

		// Add the new item
		new_item.appendTo( wrap );

		// Add new handler and remover if necessary
		$('.js-cuztom-sortable-item', parent).each(function( index, item ) {
			if( $('.js-cuztom-handle-sortable', item ).length == 0 ) { $(item).prepend( handle ); }
			if( $('.js-cuztom-remove-sortable', item ).length == 0 ) { $(item).append( remover ); }
		});

		return false;
	});

	// Ajax save
	$('.cuztom-td').on( 'click', '.js-cuztom-ajax-save', function()
	{
		var that		= $(this),
			parent		= that.closest('.cuztom-td'),
			cuztom 		= parent.closest('.cuztom'),
			input 		= $('.cuztom-input', parent),
			id_name 	= input.attr('id'),
			value		= input.val(),

			// Need better handling
			meta_type 	= cuztom.data('meta-type'),
			id 			= cuztom.data('id');

		var data = {
			action: 	'cuztom_field_ajax_save',
			cuztom: 	{
				value: 		value,
				id_name: 	id_name,

				// Need better handling
				meta_type:  meta_type,
				id: 		id
			}
		};

		$.post( Cuztom.ajax_url, data, function(r) {
			var border_color = input.css('border-color');
			input.animate({ borderColor: '#60b334' }, 200, function(){ input.animate({ borderColor: border_color }); });
		});

		return false;
	});

	// Remove current attached image
	$('.cuztom-td').on( 'click', '.js-cuztom-remove-media', function()
	{
		var that 	= $( this ),
			td 		= that.closest('.cuztom-td');

		$( '.cuztom-preview', td ).html('');
		$( '.cuztom-hidden', td ).val('');

		that.hide();

		return false;
	});

	// Upload image
	$('.cuztom-td').on( 'click', '.js-cuztom-upload', function()
	{
		var that	= $(this),
			type 	= that.data('cuztom-media-type'),
			parent	= that.closest('.cuztom-td'),
			hidden 	= $( '.cuztom-hidden', parent ),
			preview = $( '.cuztom-preview', parent );

		if( Cuztom.wp_version >= '3.5' )
		{
			var	_original_send_attachment = wp.media.editor.send.attachment;
				_cuztom = true;

			wp.media.editor.send.attachment = function(props, attachment)
			{
				if( _cuztom )
		    	{
		    		if( type == 'image' )
		    		{
		    			var thumbnail = attachment.sizes.medium ? attachment.sizes.medium : attachment.sizes.full;

		    			preview.html('')
		    			hidden.val(attachment.id);
		    		}
		    		else
		    		{
		    			preview.html('' + attachment.name + '' );
		    			hidden.val(attachment.url);
		    		}

		    		_cuztom = false;
		    	}
		    	else
		    	{
		    		return _original_send_attachment.apply( this, [props, attachment] );
		      	};
		    }

		    wp.media.editor.open();
		}
		else
		{
			var uploadID 	= hidden,
		    	spanID 		= preview;

		    var	_original_send_to_editor = window.send_to_editor;

			tb_show( '', 'media-upload.php?post_id=0&type=image&TB_iframe=true' );

			window.send_to_editor = function( html )
			{
				if( type == 'image' )
				{
					// Add image source to the hidden field
				    img 	= $(html).find('img');
				    imgID 	= html.match(/wp-image-(\d+)/g)[0].split('-')[2];

				    uploadID.val( imgID );

					// Add the image to the preview
					html 	= $(html).find('img');
				    spanID.html( html );
				}
				else
				{
					url		= $(html).attr('href');
					uploadID.val( url );

					anchor	= $(html).find('img').attr('title');
					html	= $('' + anchor + '' );
					spanID.html( html );
				}

				// Close Wordpress media popup
				tb_remove();

				// Reset default function
				window.send_to_editor = _original_send_to_editor;
			}
		}

		// Add remove button
		$('.js-cuztom-remove-media', parent).remove();
		that.after('' + ( type == 'image' ? Cuztom.remove_image : Cuztom.remove_file ) + ' ');

		return false;
	});

});<commit_msg>Update id when adding bundle<commit_after>jQuery.noConflict();

jQuery(function($) {

	// Datepicker
	$('.js-cuztom-datepicker').each(function(){
		$(this).datepicker({ dateFormat: $(this).data('date-format') });
	});

	// Timepicker
	$('.js-cuztom-timepicker').each(function(){
		$(this).timepicker({ timeFormat: $(this).data('time-format') });
	});

	// Datetime
	$('.js-cuztom-datetimepicker').each(function(){
		$(this).datetimepicker({
			timeFormat: $(this).data('time-format'),
			dateFormat: $(this).data('date-format')
		});
	});

	// Colorpicker
	$('.js-cuztom-colorpicker').miniColors();

	// Tabs
	$('.js-cuztom-tabs').tabs();

	// Slider
	$( ".js-slider" ).slider();

	// Accordion
	$('.js-cuztom-accordion').accordion();

	// Sortable
	$('.js-cuztom-sortable').sortable();

	// Remove sortable
	$('.cuztom').on( 'click', '.js-cuztom-remove-sortable', function()
	{
		var that 		= $( this ),
			field 		= that.closest('.js-cuztom-sortable-item'),
			wrap 		= that.closest('.js-cuztom-sortable'),
			fields 		= $( '.js-cuztom-sortable-item', wrap ).length;

		if( fields > 1 ) { field.remove(); }
		if( fields == 2 ){ $( '.js-cuztom-sortable-item', wrap ).find('.js-cuztom-remove-sortable').remove(); }
	});

	// Add sortable
	$('.cuztom').on( 'click', '.js-cuztom-add-sortable', function()
	{
		var that		= $( this ),
			parent 		= that.closest( '.cuztom-td, .cuztom' ),
			wrap 		= $( '.js-cuztom-sortable', parent ),
			is_bundle	= wrap.data( 'cuztom-sortable-type') == 'bundle' ? true : false,
			last 		= $( '.js-cuztom-sortable-item:last', wrap ),
			handle 		= '

',
			remover 	= '

',
			new_item 	= last.clone( true );

		// Set new bundle array key
		if( is_bundle )
		{
			new_item.find('.cuztom-input').each( function() {
				$(this).attr('name', function( i, val ) { return val.replace( /\[(\d+)\]/, function( match, n ) { return "[" + ( Number(n) + 1 ) + "]"; }); })
				$(this).attr('id', function( i, val ) { return val.replace( /\_(\d+)/, function( match, n ) { return "_" + ( Number(n) + 1 ); }); })
			});
		}

		// Reset data
		new_item.find('.cuztom-input, textarea, select, .cuztom-hidden').val('').removeAttr('selected');
		new_item.find('.js-cuztom-remove-media').remove();
		new_item.find('.cuztom-preview').html('');

		// Add the new item
		new_item.appendTo( wrap );

		// Add new handler and remover if necessary
		$('.js-cuztom-sortable-item', parent).each(function( index, item ) {
			if( $('.js-cuztom-handle-sortable', item ).length == 0 ) { $(item).prepend( handle ); }
			if( $('.js-cuztom-remove-sortable', item ).length == 0 ) { $(item).append( remover ); }
		});

		return false;
	});

	// Ajax save
	$('.cuztom-td').on( 'click', '.js-cuztom-ajax-save', function()
	{
		var that		= $(this),
			parent		= that.closest('.cuztom-td'),
			cuztom 		= parent.closest('.cuztom'),
			input 		= $('.cuztom-input', parent),
			id_name 	= input.attr('id'),
			value		= input.val(),

			// Need better handling
			meta_type 	= cuztom.data('meta-type'),
			id 			= cuztom.data('id');

		var data = {
			action: 	'cuztom_field_ajax_save',
			cuztom: 	{
				value: 		value,
				id_name: 	id_name,

				// Need better handling
				meta_type:  meta_type,
				id: 		id
			}
		};

		$.post( Cuztom.ajax_url, data, function(r) {
			var border_color = input.css('border-color');
			input.animate({ borderColor: '#60b334' }, 200, function(){ input.animate({ borderColor: border_color }); });
		});

		return false;
	});

	// Remove current attached image
	$('.cuztom-td').on( 'click', '.js-cuztom-remove-media', function()
	{
		var that 	= $( this ),
			td 		= that.closest('.cuztom-td');

		$( '.cuztom-preview', td ).html('');
		$( '.cuztom-hidden', td ).val('');

		that.hide();

		return false;
	});

	// Upload image
	$('.cuztom-td').on( 'click', '.js-cuztom-upload', function()
	{
		var that	= $(this),
			type 	= that.data('cuztom-media-type'),
			parent	= that.closest('.cuztom-td'),
			hidden 	= $( '.cuztom-hidden', parent ),
			preview = $( '.cuztom-preview', parent );

		if( Cuztom.wp_version >= '3.5' )
		{
			var	_original_send_attachment = wp.media.editor.send.attachment;
				_cuztom = true;

			wp.media.editor.send.attachment = function(props, attachment)
			{
				if( _cuztom )
		    	{
		    		if( type == 'image' )
		    		{
		    			var thumbnail = attachment.sizes.medium ? attachment.sizes.medium : attachment.sizes.full;

		    			preview.html('')
		    			hidden.val(attachment.id);
		    		}
		    		else
		    		{
		    			preview.html('' + attachment.name + '' );
		    			hidden.val(attachment.url);
		    		}

		    		_cuztom = false;
		    	}
		    	else
		    	{
		    		return _original_send_attachment.apply( this, [props, attachment] );
		      	};
		    }

		    wp.media.editor.open();
		}
		else
		{
			var uploadID 	= hidden,
		    	spanID 		= preview;

		    var	_original_send_to_editor = window.send_to_editor;

			tb_show( '', 'media-upload.php?post_id=0&type=image&TB_iframe=true' );

			window.send_to_editor = function( html )
			{
				if( type == 'image' )
				{
					// Add image source to the hidden field
				    img 	= $(html).find('img');
				    imgID 	= html.match(/wp-image-(\d+)/g)[0].split('-')[2];

				    uploadID.val( imgID );

					// Add the image to the preview
					html 	= $(html).find('img');
				    spanID.html( html );
				}
				else
				{
					url		= $(html).attr('href');
					uploadID.val( url );

					anchor	= $(html).find('img').attr('title');
					html	= $('' + anchor + '' );
					spanID.html( html );
				}

				// Close Wordpress media popup
				tb_remove();

				// Reset default function
				window.send_to_editor = _original_send_to_editor;
			}
		}

		// Add remove button
		$('.js-cuztom-remove-media', parent).remove();
		that.after('' + ( type == 'image' ? Cuztom.remove_image : Cuztom.remove_file ) + ' ');

		return false;
	});

});<|endoftext|>