<commit_before>// Internal modules
var path = require("path");
var fs = require("fs");

// NPM modules
var request = require("request");
var lunr = require("lunr");
var rimraf = require("rimraf");
var mkdirp = require("mkdirp");
var router = require("express").Router();
var showdown  = require("showdown");
var converter = new showdown.Converter();
var fs2obj = require('fs2obj');

// Project modules
var config = require("../lib/config");

// Define base folder for dcos/examples repo
var dcosExamplesFolder = path.join(__dirname, "../", "dcos-examples");

// Clean dcos/examples repo folder
rimraf.sync(dcosExamplesFolder);

// Global git object
var git = {};

// Create cache object for the dcos/example packages
var exampleCache = {};

// Placeholder for the pull interval
var pullInterval = {};

// Placeholder for the repository interval
var repositoryInterval = {};

// Create clean folder for dcos/examples repo
mkdirp(dcosExamplesFolder, function (err) {
    if (err) {
        console.error(err);
        process.exit(1);
    } else {
        console.log("Created folder for repo dcos/examples");
        // Instantiate git
        git = require('simple-git')(dcosExamplesFolder);
        console.log("Instantiated git");
        // Clone the repo
        git.clone("https://github.com/dcos/examples.git", dcosExamplesFolder, {}, function (err, result) {
            if (err) {
                console.log(err);
                process.exit(1);
            } else {
                console.log("Successfully cloned dcos/example repository");
                // Fill the examplesCache with the rendered results of the markdown files
                fillExamples();
                console.log("Generated and cached HTML from the dcos/example repository");
                // Load the repository initially
                loadRepository();
                console.log("Initially loaded the DC/OS repository information");
                // Set the periodical "git pull" as interval, every 5 minutes
                pullInterval = setInterval(function () {
                    var startTime = new Date().getTime();
                    git.pull("origin", "master", function(err, result) {
                        var endTime = new Date().getTime();
                        if (err) {
                            console.log("Pull from origin/master failed in " + (endTime-startTime) + "ms");
                            console.log(err);
                            //process.exit(1);
                        } else {
                            console.log("Successfully pulled from origin/master in " + (endTime-startTime) + "ms");
                            // Fill the examplesCache with the rendered results of the markdown files
                            fillExamples();
                            console.log("Updated and cached HTML from the dcos/example repository");
                        }
                    });
                }, config.application.refresh.examples);
                console.log("Started dcos/example pull interval (" + (config.application.refresh.examples/1000) + " secs)!");
                // Set periodical for repository refresh as interval
                repositoryInterval = setInterval(loadRepository, config.application.refresh.universe);
                console.log("Started load repository interval (" + (config.application.refresh.universe/1000) + " secs)!");
            }
        });
    }
});

function fillExamples() {

    // Read the folder/file structure
    var folderStructure = fs2obj(dcosExamplesFolder + "/1.8");

    // RegExp for finding anchor links in the markdown files
    var relativeLinkRegExp = /\(#(.*?)\)/g; // Matches "(#my-test-link)" as "my-test-link"

    // Reset exampleCache
    exampleCache = {};

    // Iterate over items
    folderStructure.items.forEach(function (item) {
        // Use folders
        if (item.type === "folder") {
            var packageName = item.name.toLowerCase();
            // Set baseUrl
            var baseUrl = "https://raw.githubusercontent.com/dcos/examples/master/" + packageName + "/1.8/";
            // Read README.md contents
            var exampleContents = fs.readFileSync(dcosExamplesFolder + "/" + packageName + "/1.8/README.md", "utf8").toString();
            // Get relative links
            var relativeLinks = exampleContents.match(relativeLinkRegExp);
            // Check if anchor links found
            if (relativeLinks && relativeLinks.length > 0) {
                // Handle relative links -> Replace with full link including the anchor
                relativeLinks.forEach(function (relativeLink) {
                    var bareLink = relativeLink.replace("(", "").replace(")", "").replace(/-/g, "");
                    var replaceRelativeLink = "(/#/package/" + packageName + "/docs" + bareLink + ")";
                    exampleContents = exampleContents.replace(relativeLink, replaceRelativeLink)
                });
            }
            // Convert to HTML and replace image sources
            var htmlCode = converter.makeHtml(exampleContents).replace(/img\//g, baseUrl + "/img/"); // Replace relative URL with absolute URL

            // There is an example for this package
            exampleCache[packageName] = {
                renderedHtml: htmlCode,
                enabled: true
            };
        }
    });

}

// Sample call to DC/OS universe
// curl -X GET -L -H "user-agent: dcos/1.8" -H "accept: application/vnd.dcos.universe.repo+json;charset=utf-8;version=v3" "https://universe.mesosphere.com/repo"

// Set request options
var options = {
    "headers": {
        "user-agent": "dcos/1.8",
        "accept": "application/vnd.dcos.universe.repo+json;charset=utf-8;version=v3"
    },
    "uri": "https://universe.mesosphere.com/repo",
    "method": "GET"
};

// Create packages singleton
var packages = {
    index: lunr(function () {
        this.field("name");
        this.field("tags", {boost: 10});
        this.field("description");
        this.field("releaseVersion");
        this.ref("name")
    }),
    map: {},
    list: []
};

//
var resetPackages = function () {
    packages.index = lunr(function () {
        this.field("name");
        this.field("tags", {boost: 10});
        this.field("description");
        this.field("releaseVersion");
        this.ref("name")
    });
    // Reset other properties
    packages.list.length = 0;
    packages.map = {};
};

function generateSortFn(prop, reverse) {
    return function (a, b) {
        if (a[prop] < b[prop]) return reverse ? 1 : -1;
        if (a[prop] > b[prop]) return reverse ? -1 : 1;
        return 0;
    };
}

var loadRepository = function () {
    request(options, function (error, response, body) {
        if (!error && response.statusCode == 200) {

            var universeResponse = JSON.parse(body);

            // Reset package singleton
            resetPackages();

            // Create temporary array
            var tempPackagesArray = [];

            // Iterate over the packages/package versions
            universeResponse.packages.forEach(function (packageObj) {

                // Initialize the package if it doesn't exist yet
                if (!packages.map.hasOwnProperty(packageObj.name)) {
                    packages.map[packageObj.name] = {
                        versions: {},
                        releaseVersions: {},
                        latest: null,
                        latestVersion: -1
                    }
                }

                var imagesObj = {};
                var screenshots = {};

                // Replace plain http image urls with https urls, to get rid of mixed-content warnings
                // Workaround for excluding erroneous packages"dynatrace", "sysdig-cloud" -> Remove once they're fixed
                if (packageObj.resource && packageObj.resource.images && Object.getOwnPropertyNames(packageObj.resource.images).length > 0 && ["dynatrace", "sysdig-cloud"].indexOf(packageObj.name) === -1) {
                    if (packageObj.resource.images.screenshots) {
                        screenshots = packageObj.resource.images.screenshots;
                        delete packageObj.resource.images.screenshots;
                    }
                    Object.getOwnPropertyNames(packageObj.resource.images).forEach(function (imageType) {
                        imagesObj[imageType] = packageObj.resource.images[imageType].replace(/^http:\/\//i, 'https://');
                    });
                } else {
                    // Assign placeholder images in the correct dimensions
                    imagesObj = {
                        "icon-small": "https://placehold.it/48x48&text=" + packageObj.name,
                        "icon-medium": "https://placehold.it/96x96&text=" + packageObj.name,
                        "icon-large": "https://placehold.it/256x256&text=" + packageObj.name
                    }
                }

                // Create smaller packageObj
                var smallPackageObj = {
                    id: packageObj.name + "-" + packageObj.releaseVersion,
                    name: packageObj.name,
                    description: packageObj.description,
                    tags: packageObj.tags,
                    version: packageObj.version,
                    releaseVersion: packageObj.releaseVersion,
                    packagingVersion: packageObj.packagingVersion,
                    minDcosReleaseVersion: packageObj.minDcosReleaseVersion,
                    maintainer: packageObj.maintainer || null,
                    website: packageObj.website || null,
                    scm: packageObj.scm || null,
                    isFramework: packageObj.framework || false,
                    preInstallNotes: packageObj.preInstallNotes || null,
                    postInstallNotes: packageObj.postInstallNotes || null,
                    postUninstallNotes: packageObj.postUninstallNotes || null,
                    licenses: packageObj.licenses || null,
                    images: imagesObj,
                    screenshots: screenshots || null,
                    hasExample : ((exampleCache[packageObj.name] && exampleCache[packageObj.name].hasOwnProperty("enabled")) ? exampleCache[packageObj.name].enabled : false)
                };

                // Create version map entry
                packages.map[packageObj.name].releaseVersions[packageObj.releaseVersion.toString()] = smallPackageObj;
                packages.map[packageObj.name].versions[packageObj.version.toString()] = smallPackageObj;

                // Check if it's the latest release version, if so sure the version number
                if (packages.map[packageObj.name].latestVersion < packageObj.releaseVersion) {
                    // Set the latestVersion
                    packages.map[packageObj.name].latestVersion = packageObj.releaseVersion;
                    // Set the packageObj as current latest
                    packages.map[packageObj.name].latest = smallPackageObj;
                }

            });

            // Get latest versions per package, and store them (for search)
            Object.getOwnPropertyNames(packages.map).forEach(function (packageName) {
                // Get current package
                var latestPackageVersion = packages.map[packageName].latest;
                // Add to tempPackagesArray
                tempPackagesArray.push(latestPackageVersion);
                // Index the current package
                packages.index.add({
                    name: latestPackageVersion.name,
                    description: latestPackageVersion.description,
                    tags: latestPackageVersion.tags,
                    releaseVersion: latestPackageVersion.releaseVersion
                });
            });

            // Store the array as pac
            packages.list = tempPackagesArray.sort(generateSortFn("name", false));

        }
    });
};

router.get("/search", function(req, res) {

    var searchString = req.query.q;

    var searchResult = packages.index.search(searchString);

    var resultArray = [];

    searchResult.forEach(function (searchResult) {
        resultArray.push(packages.map[searchResult.ref].latest);
    });

    res.json({ results: resultArray });

});

router.get("/packages", function(req, res) {

    res.json(packages.list);

});

router.get("/package/:packageName/docs", function(req, res) {

    if (packages.map[req.params.packageName]) {

        // Check if there there's already a renderedHtml property
        if (exampleCache.hasOwnProperty(req.params.packageName) && exampleCache[req.params.packageName].renderedHtml) {

            // Send renderedHtml
            res.send(exampleCache[req.params.packageName].renderedHtml);

        } else {
            res.status(404).json({ error: "No rendered example found for " + req.params.packageName });
        }

    } else {
        res.status(404).json({ error: "No matching package found!" });
    }

});

router.get("/package/:packageName/version/:packageVersion", function(req, res) {

    if (packages.map[req.params.packageName]) {

        if (req.params.packageVersion === "latest") {
            res.json(packages.map[req.params.packageName].latest)
        } else {
            if (packages.map[req.params.packageName].versions.hasOwnProperty(req.params.packageVersion)) {
                res.json(packages.map[req.params.packageName].versions[req.params.packageVersion])
            } else {
                res.status(404).json({ error: "No matching package version found!" });
            }
        }

    } else {
        res.status(404).json({ error: "No matching package found!" });
    }

});

router.get("/package/:packageName/releaseVersion/:packageReleaseVersion", function(req, res) {

    if (packages.map[req.params.packageName]) {

        if (req.params.packageReleaseVersion === "latest") {
            res.json(packages.map[req.params.packageName].latest)
        } else {
            if (packages.map[req.params.packageName].releaseVersions.hasOwnProperty(req.params.packageReleaseVersion)) {
                res.json(packages.map[req.params.packageName].releaseVersions[req.params.packageReleaseVersion])
            } else {
                res.status(404).json({ error: "No matching package version found!" });
            }
        }

    } else {
        res.status(404).json({ error: "No matching package found!" });
    }

});

router.get("/package/:packageName/versions", function(req, res) {

    if (packages.map[req.params.packageName]) {

        res.json({
            name: req.params.packageName,
            versions: Object.getOwnPropertyNames(packages.map[req.params.packageName].versions).sort()
        });

    } else {
        res.json({ error: "No matching package found!" });
    }

});

router.get("/package/:packageName/releaseVersions", function(req, res) {

    if (packages.map[req.params.packageName]) {

        res.json({
            name: req.params.packageName,
            releaseVersions: Object.getOwnPropertyNames(packages.map[req.params.packageName].releaseVersions).sort()
        });

    } else {
        res.json({ error: "No matching package found!" });
    }

});

router.get("/health", function(req, res) {

    res.send("OK");

});

module.exports = router;<commit_msg>Fixed path for the examples, after repo restructuring<commit_after>// Internal modules
var path = require("path");
var fs = require("fs");

// NPM modules
var request = require("request");
var lunr = require("lunr");
var rimraf = require("rimraf");
var mkdirp = require("mkdirp");
var router = require("express").Router();
var showdown  = require("showdown");
var converter = new showdown.Converter();
var fs2obj = require('fs2obj');

// Project modules
var config = require("../lib/config");

// Define base folder for dcos/examples repo
var dcosExamplesFolder = path.join(__dirname, "../", "dcos-examples");

// Clean dcos/examples repo folder
rimraf.sync(dcosExamplesFolder);

// Global git object
var git = {};

// Create cache object for the dcos/example packages
var exampleCache = {};

// Placeholder for the pull interval
var pullInterval = {};

// Placeholder for the repository interval
var repositoryInterval = {};

// Create clean folder for dcos/examples repo
mkdirp(dcosExamplesFolder, function (err) {
    if (err) {
        console.error(err);
        process.exit(1);
    } else {
        console.log("Created folder for repo dcos/examples");
        // Instantiate git
        git = require('simple-git')(dcosExamplesFolder);
        console.log("Instantiated git");
        // Clone the repo
        git.clone("https://github.com/dcos/examples.git", dcosExamplesFolder, {}, function (err, result) {
            if (err) {
                console.log(err);
                process.exit(1);
            } else {
                console.log("Successfully cloned dcos/example repository");
                // Fill the examplesCache with the rendered results of the markdown files
                fillExamples();
                console.log("Generated and cached HTML from the dcos/example repository");
                // Load the repository initially
                loadRepository();
                console.log("Initially loaded the DC/OS repository information");
                // Set the periodical "git pull" as interval, every 5 minutes
                pullInterval = setInterval(function () {
                    var startTime = new Date().getTime();
                    git.pull("origin", "master", function(err, result) {
                        var endTime = new Date().getTime();
                        if (err) {
                            console.log("Pull from origin/master failed in " + (endTime-startTime) + "ms");
                            console.log(err);
                            //process.exit(1);
                        } else {
                            console.log("Successfully pulled from origin/master in " + (endTime-startTime) + "ms");
                            // Fill the examplesCache with the rendered results of the markdown files
                            fillExamples();
                            console.log("Updated and cached HTML from the dcos/example repository");
                        }
                    });
                }, config.application.refresh.examples);
                console.log("Started dcos/example pull interval (" + (config.application.refresh.examples/1000) + " secs)!");
                // Set periodical for repository refresh as interval
                repositoryInterval = setInterval(loadRepository, config.application.refresh.universe);
                console.log("Started load repository interval (" + (config.application.refresh.universe/1000) + " secs)!");
            }
        });
    }
});

function fillExamples() {

    // Read the folder/file structure
    var folderStructure = fs2obj(dcosExamplesFolder);

    // RegExp for finding anchor links in the markdown files
    var relativeLinkRegExp = /\(#(.*?)\)/g; // Matches "(#my-test-link)" as "my-test-link"

    // Reset exampleCache
    exampleCache = {};

    // Iterate over items
    folderStructure.items.forEach(function (item) {
        // Use folders
        if (item.type === "folder" && item.name !== "1.8") {
            var packageName = item.name.toLowerCase();
            // Set baseUrl
            var baseUrl = "https://raw.githubusercontent.com/dcos/examples/master/" + packageName + "/";
            // Example version
            var exampleVersion = null;
            // Check if 1.9 example exists
            if (fs.existsSync(dcosExamplesFolder + "/" + packageName + "/1.9/README.md")) {
                exampleVersion = "1.9";
            } else if (fs.existsSync(dcosExamplesFolder + "/" + packageName + "/1.8/README.md")) {
                exampleVersion = "1.8";
            }
            // Check if we have a valid example
            if (exampleVersion) {
                // Read README.md contents
                var exampleContents = fs.readFileSync(dcosExamplesFolder + "/" + packageName + "/" + exampleVersion + "/README.md", "utf8").toString();
                // Get relative links
                var relativeLinks = exampleContents.match(relativeLinkRegExp);
                // Check if anchor links found
                if (relativeLinks && relativeLinks.length > 0) {
                    // Handle relative links -> Replace with full link including the anchor
                    relativeLinks.forEach(function (relativeLink) {
                        var bareLink = relativeLink.replace("(", "").replace(")", "").replace(/-/g, "");
                        var replaceRelativeLink = "(/#/package/" + packageName + "/docs" + bareLink + ")";
                        exampleContents = exampleContents.replace(relativeLink, replaceRelativeLink)
                    });
                }
                // Convert to HTML and replace image sources
                var htmlCode = converter.makeHtml(exampleContents).replace(/img\//g, baseUrl + "/" + exampleVersion + "/img/"); // Replace relative URL with absolute URL

                // There is an example for this package
                exampleCache[packageName] = {
                    renderedHtml: htmlCode,
                    enabled: true
                };
            }
        }
    });

}

// Sample call to DC/OS universe
// curl -X GET -L -H "user-agent: dcos/1.8" -H "accept: application/vnd.dcos.universe.repo+json;charset=utf-8;version=v3" "https://universe.mesosphere.com/repo"

// Set request options
var options = {
    "headers": {
        "user-agent": "dcos/1.8",
        "accept": "application/vnd.dcos.universe.repo+json;charset=utf-8;version=v3"
    },
    "uri": "https://universe.mesosphere.com/repo",
    "method": "GET"
};

// Create packages singleton
var packages = {
    index: lunr(function () {
        this.field("name");
        this.field("tags", {boost: 10});
        this.field("description");
        this.field("releaseVersion");
        this.ref("name")
    }),
    map: {},
    list: []
};

// Tags
var tags = {};

// Reset packages function
var resetPackages = function () {
    packages.index = lunr(function () {
        this.field("name");
        this.field("tags", {boost: 10});
        this.field("description");
        this.field("releaseVersion");
        this.ref("name")
    });
    // Reset other properties
    packages.list.length = 0;
    packages.map = {};
};

// Reset tags function
var resetTags = function () {
    tags = {};
};

function generateSortFn(prop, reverse) {
    return function (a, b) {
        if (a[prop] < b[prop]) return reverse ? 1 : -1;
        if (a[prop] > b[prop]) return reverse ? -1 : 1;
        return 0;
    };
}

var loadRepository = function () {
    request(options, function (error, response, body) {
        if (!error && response.statusCode == 200) {

            var universeResponse = JSON.parse(body);

            // Reset package singleton
            resetPackages();

            // Reset tags singleton
            resetTags();

            // Create temporary array
            var tempPackagesArray = [];

            // Iterate over the packages/package versions
            universeResponse.packages.forEach(function (packageObj) {

                // Initialize the package if it doesn't exist yet
                if (!packages.map.hasOwnProperty(packageObj.name)) {
                    packages.map[packageObj.name] = {
                        versions: {},
                        releaseVersions: {},
                        latest: null,
                        latestVersion: -1
                    }
                }

                var imagesObj = {};
                var screenshots = {};

                // Replace plain http image urls with https urls, to get rid of mixed-content warnings
                // Workaround for excluding erroneous packages"dynatrace", "sysdig-cloud" -> Remove once they're fixed
                if (packageObj.resource && packageObj.resource.images && Object.getOwnPropertyNames(packageObj.resource.images).length > 0 && ["dynatrace", "sysdig-cloud"].indexOf(packageObj.name) === -1) {
                    if (packageObj.resource.images.screenshots) {
                        screenshots = packageObj.resource.images.screenshots;
                        delete packageObj.resource.images.screenshots;
                    }
                    Object.getOwnPropertyNames(packageObj.resource.images).forEach(function (imageType) {
                        imagesObj[imageType] = packageObj.resource.images[imageType].replace(/^http:\/\//i, 'https://');
                    });
                } else {
                    // Assign placeholder images in the correct dimensions
                    imagesObj = {
                        "icon-small": "https://placehold.it/48x48&text=" + packageObj.name,
                        "icon-medium": "https://placehold.it/96x96&text=" + packageObj.name,
                        "icon-large": "https://placehold.it/256x256&text=" + packageObj.name
                    }
                }

                // Create smaller packageObj
                var smallPackageObj = {
                    id: packageObj.name + "-" + packageObj.releaseVersion,
                    name: packageObj.name,
                    description: packageObj.description,
                    tags: packageObj.tags,
                    version: packageObj.version,
                    releaseVersion: packageObj.releaseVersion,
                    packagingVersion: packageObj.packagingVersion,
                    minDcosReleaseVersion: packageObj.minDcosReleaseVersion,
                    maintainer: packageObj.maintainer || null,
                    website: packageObj.website || null,
                    scm: packageObj.scm || null,
                    isFramework: packageObj.framework || false,
                    preInstallNotes: packageObj.preInstallNotes || null,
                    postInstallNotes: packageObj.postInstallNotes || null,
                    postUninstallNotes: packageObj.postUninstallNotes || null,
                    licenses: packageObj.licenses || null,
                    images: imagesObj,
                    screenshots: screenshots || null,
                    hasExample : ((exampleCache[packageObj.name] && exampleCache[packageObj.name].hasOwnProperty("enabled")) ? exampleCache[packageObj.name].enabled : false)
                };

                // Create version map entry
                packages.map[packageObj.name].releaseVersions[packageObj.releaseVersion.toString()] = smallPackageObj;
                packages.map[packageObj.name].versions[packageObj.version.toString()] = smallPackageObj;

                // Check if it's the latest release version, if so sure the version number
                if (packages.map[packageObj.name].latestVersion < packageObj.releaseVersion) {
                    // Set the latestVersion
                    packages.map[packageObj.name].latestVersion = packageObj.releaseVersion;
                    // Set the packageObj as current latest
                    packages.map[packageObj.name].latest = smallPackageObj;
                }

            });

            // Get latest versions per package, and store them (for search)
            Object.getOwnPropertyNames(packages.map).forEach(function (packageName) {
                // Get current package
                var latestPackageVersion = packages.map[packageName].latest;
                // Add to tempPackagesArray
                tempPackagesArray.push(latestPackageVersion);
                // Index the current package
                packages.index.add({
                    name: latestPackageVersion.name,
                    description: latestPackageVersion.description,
                    tags: latestPackageVersion.tags,
                    releaseVersion: latestPackageVersion.releaseVersion
                });
                // Add tags
                if (latestPackageVersion.tags && Array.isArray(latestPackageVersion.tags)) {
                    latestPackageVersion.tags.forEach(function (tag) {
                        if (!tags.hasOwnProperty(tag.toLowerCase())) {
                            tags[tag.toLowerCase()] = {
                                count: 0,
                                packages: []
                            };
                        }
                        tags[tag.toLowerCase()].count++;
                        tags[tag.toLowerCase()].packages.push(latestPackageVersion.name);
                    });
                }
            });
            console.log(JSON.stringify(tags));

            // Store the array as pac
            packages.list = tempPackagesArray.sort(generateSortFn("name", false));

        }
    });
};

router.get("/search", function(req, res) {

    var searchString = req.query.q;

    var searchResult = packages.index.search(searchString);

    var resultArray = [];

    searchResult.forEach(function (searchResult) {
        resultArray.push(packages.map[searchResult.ref].latest);
    });

    res.json({ results: resultArray });

});

router.get("/packages", function(req, res) {

    res.json(packages.list);

});

router.get("/package/:packageName/docs", function(req, res) {

    if (packages.map[req.params.packageName]) {

        // Check if there there's already a renderedHtml property
        if (exampleCache.hasOwnProperty(req.params.packageName) && exampleCache[req.params.packageName].renderedHtml) {

            // Send renderedHtml
            res.send(exampleCache[req.params.packageName].renderedHtml);

        } else {
            res.status(404).json({ error: "No rendered example found for " + req.params.packageName });
        }

    } else {
        res.status(404).json({ error: "No matching package found!" });
    }

});

router.get("/package/:packageName/version/:packageVersion", function(req, res) {

    if (packages.map[req.params.packageName]) {

        if (req.params.packageVersion === "latest") {
            res.json(packages.map[req.params.packageName].latest)
        } else {
            if (packages.map[req.params.packageName].versions.hasOwnProperty(req.params.packageVersion)) {
                res.json(packages.map[req.params.packageName].versions[req.params.packageVersion])
            } else {
                res.status(404).json({ error: "No matching package version found!" });
            }
        }

    } else {
        res.status(404).json({ error: "No matching package found!" });
    }

});

router.get("/package/:packageName/releaseVersion/:packageReleaseVersion", function(req, res) {

    if (packages.map[req.params.packageName]) {

        if (req.params.packageReleaseVersion === "latest") {
            res.json(packages.map[req.params.packageName].latest)
        } else {
            if (packages.map[req.params.packageName].releaseVersions.hasOwnProperty(req.params.packageReleaseVersion)) {
                res.json(packages.map[req.params.packageName].releaseVersions[req.params.packageReleaseVersion])
            } else {
                res.status(404).json({ error: "No matching package version found!" });
            }
        }

    } else {
        res.status(404).json({ error: "No matching package found!" });
    }

});

router.get("/package/:packageName/versions", function(req, res) {

    if (packages.map[req.params.packageName]) {

        res.json({
            name: req.params.packageName,
            versions: Object.getOwnPropertyNames(packages.map[req.params.packageName].versions).sort()
        });

    } else {
        res.json({ error: "No matching package found!" });
    }

});

router.get("/package/:packageName/releaseVersions", function(req, res) {

    if (packages.map[req.params.packageName]) {

        res.json({
            name: req.params.packageName,
            releaseVersions: Object.getOwnPropertyNames(packages.map[req.params.packageName].releaseVersions).sort()
        });

    } else {
        res.json({ error: "No matching package found!" });
    }

});

router.get("/health", function(req, res) {

    res.send("OK");

});

router.get("/tags", function(req, res) {

    res.json(tags);

});

module.exports = router;<|endoftext|>


<commit_before>'use strict';

var express = require('express'),
    path = require('path'),
    router = express.Router(),
    unqlite = require('unqlite'),
    correio = require('../lib/correio'),
    db = new unqlite.Database(path.join(__dirname, '../db/cep.db')),
    cepRegex = /^(\d{5})\-?(\d{3})$/;

var closeDB = function(next) {
    db.close(function(err) {
        if (err)
            console.log('db.close', err);
    });
}

var respostaFinal = function(res, data, success) {
    success = success || false;
    data['success'] = success;
    res.send(data);
}

router.get('/', function(req, res) {
    res.send('
Como usar: /cep/09715-295 ou /cep/09715295
');
});

router.get('/:cep', function(req, res, next) {
    var rawcep,
        cep;

    cep = req.params.cep;
    if (cepRegex.test(cep)) {
        rawcep = cep.split('-').join('');

        // Abre conexao com o banco
        db.open(unqlite.OPEN_CREATE, function(err) {
            if (err) {
                closeDB();
                next(err);
            } else {
                // Localiza o cep
                db.fetch(rawcep, function(err, k, v) {
                    // Se não achou então...
                    if (err) {
                        console.log('db.fetch', err);
                        // Consulta no correio...
                        correio(rawcep, function(err, data) {
                            // Se achou então grava no banco...
                            if (data) {
                                db.store(rawcep, JSON.stringify(data), function(err, k, v) {
                                    if (err)
                                        console.log('db.store', err);
                                    else
                                        console.log('db.store - gravou', k);

                                    closeDB();
                                    respostaFinal(res, data, true);
                                });
                            // senão a consulta #fail
                            } else {
                                respostaFinal(res, {
                                    "msg": "cep não encontrado"
                                });
                            }
                        });
                    // achou!!
                    } else {
                        console.log('achou no banco...');
                        closeDB();
                        respostaFinal(res, JSON.parse(v), true);
                    }
                });
            }
        });
    } else {
        respostaFinal(res, {
            "msg": "cep inválido"
        });
    }
});

module.exports = router;<commit_msg>fix open and close db<commit_after>'use strict';

var express = require('express'),
    path = require('path'),
    router = express.Router(),
    unqlite = require('unqlite'),
    correio = require('../lib/correio'),
    cepRegex = /^(\d{5})\-?(\d{3})$/;

var DB = unqlite.Database,
    dbFile = path.join(__dirname, '../db/cep.db');

var closeDB = function(db) {
    db.close(function(err) {
        if (err)
            console.log('db.close', err);
        else
            console.log('db.close', 'fechadoo...');
    });
}

var respostaFinal = function(res, data, success) {
    success = success || false;
    data['success'] = success;
    res.send(data);
}

router.get('/', function(req, res) {
    res.send('
Como usar: /cep/09715-295 ou /cep/09715295
');
});

router.get('/:cep', function(req, res, next) {
    console.log('-------------------');

    var rawcep,
        cep,
        db;

    cep = req.params.cep;
    if (cepRegex.test(cep)) {

        rawcep = cep.split('-').join('');

        // Abre conexao com o banco
        db = new DB(dbFile);
        db.open(unqlite.OPEN_CREATE, function(err) {
            if (err) {
                closeDB(db);
                next(new Error('unqlite open'));
            } else {
                console.log('db.open', 'abriuuu...');
                // Localiza o cep no banco
                db.fetch(rawcep, function(err, k, v) {
                    // Se não achou então...
                    if (err) {
                        console.log('db.fetch', err);
                        // Consulta no correio...
                        correio(rawcep, function(err, data) {
                            // Se achou então grava no banco...
                            if (data) {
                                db.store(rawcep, JSON.stringify(data), function(err, k, v) {
                                    if (err)
                                        console.log('db.store', err);
                                    else
                                        console.log('db.store - gravou', k);

                                    closeDB(db);
                                    respostaFinal(res, data, true);
                                });
                            // senão a consulta #fail
                            } else {
                                closeDB(db);
                                respostaFinal(res, {
                                    "msg": "cep não encontrado"
                                });
                            }
                        });
                    // achou!!
                    } else {
                        console.log('achou no banco...');
                        closeDB(db);
                        respostaFinal(res, JSON.parse(v), true);
                    }
                });
            }
        });
    } else {
        respostaFinal(res, {
            "msg": "cep inválido"
        });
    }
});

module.exports = router;<|endoftext|>


<commit_before>'use strict';

const { Router } = require('express');
const { Subscriber } = require('../models');

const SUBSCRIBE_COMMAND = 'subscribe';
const UNSUBSCRIBE_COMMAND = 'unsubscribe';

const MESSAGE_INVALID_COMMAND = `Hi!
Thanks for messaging us! Valid commands are:
- subscribe
- unsubscribe
We will then keep you up-to-date!
`;

const MESSAGE_THANKS_SUBSCRIBING = `Thanks for subscribing!
We will keep you up-to-date!
If you want to stop receiving messages write 'unsubscribe'.
`;

const MESSAGE_UNSUBSCRIBING = `Sorry to see you leave!
If you want to start receiving messages again, just write:
'subscribe'!
`;

class Sms {
  incomingNews(req, res, next) {
    let { Body, From, To } = req.body;

    if (this.isSubscribeCommand(Body) || this.isUnsubscribeCommand(Body)) {
      Subscriber.upsert({
        phoneNumber: From,
        subscribed: this.isSubscribeCommand(Body)
      }).then(sub => {
        res.type('text/plain');
        if (this.isSubscribeCommand(Body)) {
          res.send(MESSAGE_THANKS_SUBSCRIBING);
        } else {
          res.send(MESSAGE_UNSUBSCRIBING);
        }
      });
    } else {
      res.type('text/plain').send(MESSAGE_INVALID_COMMAND);
    }
  }

  isSubscribeCommand(message) {
    let cleanedUpMessage = message.toLowerCase().trim();
    return cleanedUpMessage === SUBSCRIBE_COMMAND;
  }

  isUnsubscribeCommand(message) {
    let cleanedUpMessage = message.toLowerCase().trim();
    return cleanedUpMessage === UNSUBSCRIBE_COMMAND;
  }
}

const sms = new Sms();
const SmsRouter = Router();
SmsRouter.get('/', sms.get);
SmsRouter.post('/', sms.create);

module.exports = { Sms, SmsRouter };<commit_msg>Fixed issue router<commit_after>'use strict';

const { Router } = require('express');
const { Subscriber } = require('../models');

const SUBSCRIBE_COMMAND = 'subscribe';
const UNSUBSCRIBE_COMMAND = 'unsubscribe';

const MESSAGE_INVALID_COMMAND = `Hi!
Thanks for messaging us! Valid commands are:
- subscribe
- unsubscribe
We will then keep you up-to-date!
`;

const MESSAGE_THANKS_SUBSCRIBING = `Thanks for subscribing!
We will keep you up-to-date!
If you want to stop receiving messages write 'unsubscribe'.
`;

const MESSAGE_UNSUBSCRIBING = `Sorry to see you leave!
If you want to start receiving messages again, just write:
'subscribe'!
`;

class Sms {
  incomingNews(req, res, next) {
    let { Body, From, To } = req.body;

    if (this.isSubscribeCommand(Body) || this.isUnsubscribeCommand(Body)) {
      Subscriber.upsert({
        phoneNumber: From,
        subscribed: this.isSubscribeCommand(Body)
      }).then(sub => {
        res.type('text/plain');
        if (this.isSubscribeCommand(Body)) {
          res.send(MESSAGE_THANKS_SUBSCRIBING);
        } else {
          res.send(MESSAGE_UNSUBSCRIBING);
        }
      });
    } else {
      res.type('text/plain').send(MESSAGE_INVALID_COMMAND);
    }
  }

  isSubscribeCommand(message) {
    let cleanedUpMessage = message.toLowerCase().trim();
    return cleanedUpMessage === SUBSCRIBE_COMMAND;
  }

  isUnsubscribeCommand(message) {
    let cleanedUpMessage = message.toLowerCase().trim();
    return cleanedUpMessage === UNSUBSCRIBE_COMMAND;
  }
}

const sms = new Sms();
const SmsRouter = Router();
SmsRouter.post('/', sms.incomingNews);

module.exports = { Sms, SmsRouter };<|endoftext|>


<commit_before>a7f9abbd-2e9d-11e5-b9cb-a45e60cdfd11<commit_msg>Final commit :sunglasses:<commit_after>println('Hello world')<|endoftext|>


<commit_before>// routes/web.js
//
// Spurtin' out pumpy goodness all over your browser window
//
// Copyright 2011-2012, StatusNet Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var Activity = require('../model/activity').Activity,
    User = require('../model/user').User,
    databank = require('databank'),
    Step = require('step'),
    _ = require('underscore'),
    mw = require('../lib/middleware'),
    maybeAuth = mw.maybeAuth,
    reqUser = mw.reqUser,
    mustAuth = mw.mustAuth,
    sameUser = mw.sameUser,
    noUser = mw.noUser,
    checkCredentials = mw.checkCredentials,
    NoSuchThingError = databank.NoSuchThingError;

var initApp = function(app) {

    app.get('/', maybeAuth, showMain);

    app.post('/main/login', noUser, handleLogin);
    app.post('/main/logout', mustAuth, handleLogout);

    app.get('/main/settings', mustAuth, showSettings);

    app.get('/:nickname', maybeAuth, reqUser, showStream);
    app.get('/:nickname/inbox', mustAuth, reqUser, sameUser, showInbox);
    app.get('/:nickname/activity/:uuid', maybeAuth, reqUser, showActivity);
};

var showSettings = function(req, res, next) {
    res.render("settings", {title: "Settings",
			    nav: res.partial("nav-loggedin", req.remoteUser),
			    user: req.remoteUser});
};

var showMain = function(req, res, next) {
    res.render("main", {title: "Welcome",
			nav: res.partial((req.remoteUser) ? "nav-loggedin" : "nav-anonymous", req.remoteUser),
			user: req.remoteUser});
};

var handleLogin = function(req, res, next) {
    Step(
        function () {
            checkCredentials(req.body.nickname, req.body.password, this);
        },
        function(err, user) {
	    if (err) throw err;
	    if (!user) {
		// done here
                next(new Error("Not authorized"));
	    } else {
		user.expand(this);
	    }
	},
	function(err, user) {
            if (err) {
                next(err);
	    } else {
                req.session.nickname = user.nickname;
                user.sanitize();
                res.json(user);
            }
        }
    );
};

var handleLogout = function(req, res, next) {
    delete req.session.nickname;
    res.json("OK");
};

var showActivity = function(req, res, next) {
    var uuid = req.params.uuid,
        user = req.user;

    Step(
        function() {
            Activity.search({'uuid': req.params.uuid}, this);
        },
        function(err, activities) {
            if (err) throw err;
            if (activities.length === 0) {
                throw new NoSuchThingError('activity', uuid);
            }
            if (activities.length > 1) {
                throw new Error("Too many activities with ID = " + req.params.uuid);
            }
            activities[0].expand(this);
        },
        function(err, activity) {
            if (err) {
                next(err);
            } else {
                res.render("activity", {title: "Welcome",
			                nav: res.partial((req.remoteUser) ? "nav-loggedin" : "nav-anonymous",
                                                         req.remoteUser),
			                user: req.remoteUser,
                                        activity: activity});
            }
        }
    );
};

var showInbox = function(req, res, next) {

    Step(
        function() {
            req.user.getInbox(0, 20, this);
        },
        function(err, activities) {
            if (err) {
                next(err);
            } else {
                res.render("inbox", {title: "Inbox",
			             nav: res.partial((req.remoteUser) ? "nav-loggedin" : "nav-anonymous",
                                                      req.remoteUser),
			             user: req.remoteUser,
                                     activities: activities});
            }
        }
    );
};

var showStream = function(req, res, next) {
    var pump = this;

    Step(
        function() {
            req.user.getStream(0, 20, this);
        },
        function(err, activities) {
            if (err) {
                next(err);
            } else {
                res.render("user", {title: req.user.nickname,
			            nav: res.partial((req.remoteUser) ? "nav-loggedin" : "nav-anonymous",
                                                     req.remoteUser),
			            user: req.remoteUser,
                                    actor: req.user.profile,
                                    activities: activities});
            }
        }
    );
};
<commit_msg>untabify<commit_after>// routes/web.js
//
// Spurtin' out pumpy goodness all over your browser window
//
// Copyright 2011-2012, StatusNet Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var Activity = require('../model/activity').Activity,
    User = require('../model/user').User,
    databank = require('databank'),
    Step = require('step'),
    _ = require('underscore'),
    mw = require('../lib/middleware'),
    maybeAuth = mw.maybeAuth,
    reqUser = mw.reqUser,
    mustAuth = mw.mustAuth,
    sameUser = mw.sameUser,
    noUser = mw.noUser,
    checkCredentials = mw.checkCredentials,
    NoSuchThingError = databank.NoSuchThingError;

var initApp = function(app) {

    app.get('/', maybeAuth, showMain);

    app.post('/main/login', noUser, handleLogin);
    app.post('/main/logout', mustAuth, handleLogout);

    app.get('/main/settings', mustAuth, showSettings);

    app.get('/:nickname', maybeAuth, reqUser, showStream);
    app.get('/:nickname/inbox', mustAuth, reqUser, sameUser, showInbox);
    app.get('/:nickname/activity/:uuid', maybeAuth, reqUser, showActivity);
};

var showSettings = function(req, res, next) {
    res.render("settings", {title: "Settings",
                            nav: res.partial("nav-loggedin", req.remoteUser),
                            user: req.remoteUser});
};

var showMain = function(req, res, next) {
    res.render("main", {title: "Welcome",
                        nav: res.partial((req.remoteUser) ? "nav-loggedin" : "nav-anonymous", req.remoteUser),
                        user: req.remoteUser});
};

var handleLogin = function(req, res, next) {
    Step(
        function () {
            checkCredentials(req.body.nickname, req.body.password, this);
        },
        function(err, user) {
            if (err) throw err;
            if (!user) {
                // done here
                next(new Error("Not authorized"));
            } else {
                user.expand(this);
            }
        },
        function(err, user) {
            if (err) {
                next(err);
            } else {
                req.session.nickname = user.nickname;
                user.sanitize();
                res.json(user);
            }
        }
    );
};

var handleLogout = function(req, res, next) {
    delete req.session.nickname;
    res.json("OK");
};

var showActivity = function(req, res, next) {
    var uuid = req.params.uuid,
        user = req.user;

    Step(
        function() {
            Activity.search({'uuid': req.params.uuid}, this);
        },
        function(err, activities) {
            if (err) throw err;
            if (activities.length === 0) {
                throw new NoSuchThingError('activity', uuid);
            }
            if (activities.length > 1) {
                throw new Error("Too many activities with ID = " + req.params.uuid);
            }
            activities[0].expand(this);
        },
        function(err, activity) {
            if (err) {
                next(err);
            } else {
                res.render("activity", {title: "Welcome",
                                        nav: res.partial((req.remoteUser) ? "nav-loggedin" : "nav-anonymous",
                                                         req.remoteUser),
                                        user: req.remoteUser,
                                        activity: activity});
            }
        }
    );
};

var showInbox = function(req, res, next) {

    Step(
        function() {
            req.user.getInbox(0, 20, this);
        },
        function(err, activities) {
            if (err) {
                next(err);
            } else {
                res.render("inbox", {title: "Inbox",
                                     nav: res.partial((req.remoteUser) ? "nav-loggedin" : "nav-anonymous",
                                                      req.remoteUser),
                                     user: req.remoteUser,
                                     activities: activities});
            }
        }
    );
};

var showStream = function(req, res, next) {
    var pump = this;

    Step(
        function() {
            req.user.getStream(0, 20, this);
        },
        function(err, activities) {
            if (err) {
                next(err);
            } else {
                res.render("user", {title: req.user.nickname,
                                    nav: res.partial((req.remoteUser) ? "nav-loggedin" : "nav-anonymous",
                                                     req.remoteUser),
                                    user: req.remoteUser,
                                    actor: req.user.profile,
                                    activities: activities});
            }
        }
    );
};
<|endoftext|>


<commit_before>/**
 * /assets/linker/js/board.js
 *
 * @file Basic global functions which are attached to document ready event.
 * @author Tarmo Leppänen <tarmo.leppanen@protacon.com>
 */

/**
 * Initialize all necessary javascript on document ready event.
 */
jQuery(document).ready(function() {
    // Global bootbox settings
    bootbox.setDefaults({
        animate: false
    });

    // Global tooltip event
    initTooltips(jQuery(document));
});
<commit_msg>Added global AJAX settings, basically just for error handling.<commit_after>/**
 * /assets/linker/js/board.js
 *
 * @file Basic global functions which are attached to document ready event.
 * @author Tarmo Leppänen <tarmo.leppanen@protacon.com>
 */

/**
 * Initialize all necessary javascript on document ready event.
 */
jQuery(document).ready(function() {
    // Global AJAX setup
    jQuery.ajaxSetup({
        error: function(jqXhr, textStatus, error) {
            handleAjaxError(jqXhr, textStatus, error);
        },
        type: "post"
    });

    // Global bootbox settings
    bootbox.setDefaults({
        animate: false
    });

    // Global tooltip event
    initTooltips(jQuery(document));
});
<|endoftext|>


<commit_before>/**
 * This renders a rant with it's comments in a modal.
 * It can render rant and comments in a single or double columns
 * based on the width of the window
 */

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import ItemCard from './item_card';
import Loading from '../utilities/loading';
import rantscript from '../../consts/rantscript';
import Comments from '../comments/comments';
import PostComment from '../comments/comment_post';
import { ITEM } from '../../consts/types';

class Item extends Component {
  constructor() {
    super();
    this.state = {
      item: null,
      maxCol: 1,
    };
  }
  /**
   * It receives a rant id via props.
   * Uses that to fetch the rant (or collab)
   *
   * @memberof Item
   */
  componentWillMount() {
    this.fetchitem();
  }
  componentDidMount() {
    this.handleResize();
    this.listener = () => {
      this.handleResize();
    };
    window.addEventListener('resize', this.listener);
  }
  shouldComponentUpdate(nextProps, nextState) {
    if (this.state.item === nextState.item) {
      return false;
    }
    return true;
  }
  componentWillUnmount() {
    window.removeEventListener('resize', this.listener);
  }
  handleOnClick(e) {
    if (e.target.className === 'itemcard_container') {
      this.props.close();
    }
  }
  /**
   * This component can render single or double column
   * That is determined by how much width it has
   *
   * @memberof Item
   */
  handleResize() {
    const { theme } = this.props;
    const middleContainer = document.getElementById('item_container');
    let maxCol = 1;
    if (middleContainer) {
      const middleWidth = middleContainer.offsetWidth;
      const nextColumnWidth = parseInt(theme.column.width, 10) + 50;
      maxCol = Math.floor(middleWidth / nextColumnWidth);
    }
    if (this.state.maxCol !== maxCol) {
      this.setState({ maxCol });
    }
  }
  /**
   * Uses rantscript to fetch a rant or collab
   * This is called again when a comment is added.
   * If a comment is added, the comment column is scrolled to bottom
   *
   * @param {boolean} [scrollToBottom=false] If it should scroll to bottom
   * @memberof Item
   */
  fetchitem(scrollToBottom = false) {
    const { cardItem, auth, fetchNotifs } = this.props;
    let authToken = null;
    if (auth.user) {
      authToken = auth.user.authToken;
    }
    rantscript
      .rant(cardItem.id, authToken)
      .then((res) => {
        fetchNotifs();
        const item = res;
        this.setState({ item });
        if (typeof cardItem.data.commentID !== 'undefined') {
          const relatedComment = document.getElementById(cardItem.data.commentID);
          if (relatedComment) {
            relatedComment.scrollIntoView();
          }
          return;
        }
        if (scrollToBottom) {
          setTimeout(() => {
            const commentsContainer = document.getElementsByClassName('comments_container')[0];
            commentsContainer.scrollTop = commentsContainer.scrollHeight;
          }, 500);
        }
      })
      .catch((err) => {
        console.log(err);
      });
  }
  /**
   * This is a prop for comments component.
   * This just calls the addMention of post comment
   *
   * @param {string} value
   * @memberof Item
   */
  addMention(value) {
    this.postComment.addMention(value);
  }
  onEdit(id, value, isRant = false) {
    if (isRant) {
      this.props.open(ITEM.POST_RANT.NAME, id);
      return;
    }
    this.postComment.edit(id, value);
  }
  getItemCard() {
    const { item } = this.state;
    const { theme, vote, cardItem, auth, open, showToast } = this.props;
    return (
      <ItemCard
        modal
        item={item.rant}
        key={item.rant.id}
        theme={theme}
        vote={vote}
        itemType={cardItem.type}
        auth={auth}
        open={open}
        showToast={showToast}
        fetchitem={() => this.fetchitem()}
        onEdit={(id, value) => this.onEdit(id, value, true)}
      />
    );
  }
  getComments() {
    const { item } = this.state;
    const { theme, vote, auth, open, showToast } = this.props;
    return (
      <Comments
        comments={item.comments}
        theme={theme}
        vote={vote}
        auth={auth}
        open={open}
        showToast={showToast}
        addMention={value => this.addMention(value)}
        fetchitem={() => this.fetchitem()}
        onEdit={(id, value) => this.onEdit(id, value)}
      />
    );
  }
  getPostComment() {
    const { item } = this.state;
    const { theme, auth } = this.props;
    return (
      <PostComment
        comments={item.comments}
        theme={theme}
        auth={auth}
        id={item.rant.id}
        originalPoster={item.rant.user_username}
        fetch={() => this.fetchitem(true)}
        ref={(node) => { this.postComment = node; }}
      />
    );
  }
  renderMutliCol() {
    return (

          {this.getItemCard()}

          {this.getComments()}
          {this.getPostComment()}

    );
  }
  renderSingleColumn() {
    return (

 { this.compactCol = node; }}
      >
        {this.getItemCard()}
        {this.getComments()}
        {this.getPostComment()}

    );
  }
  render() {
    if (!this.state.item) {
      return (

          <Loading />

      );
    }
    return (

 this.handleOnClick(e)}
      >
        { this.state.maxCol === 1 ? this.renderSingleColumn()
          : this.renderMutliCol()
        }

    );
  }
}

Item.propTypes = {
  theme: PropTypes.object.isRequired,
  vote: PropTypes.func.isRequired,
  cardItem: PropTypes.object.isRequired,
  auth: PropTypes.object.isRequired,
  close: PropTypes.func.isRequired,
  open: PropTypes.func.isRequired,
  showToast: PropTypes.func.isRequired,
  fetchNotifs: PropTypes.func.isRequired,
};

export default Item;
<commit_msg>testing new item_fetch<commit_after>/**
 * This renders a rant with it's comments in a modal.
 * It can render rant and comments in a single or double columns
 * based on the width of the window
 */

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import ItemCard from './item_card';
import Loading from '../utilities/loading';
import rantscript from '../../consts/rantscript';
import Comments from '../comments/comments';
import PostComment from '../comments/comment_post';
import { ITEM } from '../../consts/types';

let reload = null;

class Item extends Component {
  constructor() {
    super();
    this.state = {
      item: null,
      maxCol: 1,
    };
  }
  /**
   * It receives a rant id via props.
   * Uses that to fetch the rant (or collab)
   *
   * @memberof Item
   */
  componentWillMount() {
    this.fetchitem();
    reload = setInterval(() => {
      if (!this.state.item) {
        this.fetchitem();
      }
    }, 2000);
  }
  componentDidMount() {
    this.handleResize();
    this.listener = () => {
      this.handleResize();
    };
    window.addEventListener('resize', this.listener);
  }
  shouldComponentUpdate(nextProps, nextState) {
    if (this.state.item === nextState.item) {
      return false;
    }
    return true;
  }
  componentWillUnmount() {
    window.removeEventListener('resize', this.listener);
  }
  handleOnClick(e) {
    if (e.target.className === 'itemcard_container') {
      this.props.close();
    }
  }
  /**
   * This component can render single or double column
   * That is determined by how much width it has
   *
   * @memberof Item
   */
  handleResize() {
    const { theme } = this.props;
    const middleContainer = document.getElementById('item_container');
    let maxCol = 1;
    if (middleContainer) {
      const middleWidth = middleContainer.offsetWidth;
      const nextColumnWidth = parseInt(theme.column.width, 10) + 50;
      maxCol = Math.floor(middleWidth / nextColumnWidth);
    }
    if (this.state.maxCol !== maxCol) {
      this.setState({ maxCol });
    }
  }
  /**
   * Uses rantscript to fetch a rant or collab
   * This is called again when a comment is added.
   * If a comment is added, the comment column is scrolled to bottom
   *
   * @param {boolean} [scrollToBottom=false] If it should scroll to bottom
   * @memberof Item
   */
  fetchitem(scrollToBottom = false) {
    const { cardItem, auth, fetchNotifs } = this.props;
    let authToken = null;
    if (auth.user) {
      authToken = auth.user.authToken;
    }
    rantscript
      .rant(cardItem.id, authToken)
      .then((res) => {
        window.clearInterval(reload);
        fetchNotifs();
        const item = res;
        this.setState({ item });
        if (typeof cardItem.data.commentID !== 'undefined') {
          const relatedComment = document.getElementById(cardItem.data.commentID);
          if (relatedComment) {
            relatedComment.scrollIntoView();
          }
          return;
        }
        if (scrollToBottom) {
          setTimeout(() => {
            const commentsContainer = document.getElementsByClassName('comments_container')[0];
            commentsContainer.scrollTop = commentsContainer.scrollHeight;
          }, 500);
        }
      })
      .catch(() => {
        //
      });
  }
  /**
   * This is a prop for comments component.
   * This just calls the addMention of post comment
   *
   * @param {string} value
   * @memberof Item
   */
  addMention(value) {
    this.postComment.addMention(value);
  }
  onEdit(id, value, isRant = false) {
    if (isRant) {
      this.props.open(ITEM.POST_RANT.NAME, id);
      return;
    }
    this.postComment.edit(id, value);
  }
  getItemCard() {
    const { item } = this.state;
    const { theme, vote, cardItem, auth, open, showToast } = this.props;
    return (
      <ItemCard
        modal
        item={item.rant}
        key={item.rant.id}
        theme={theme}
        vote={vote}
        itemType={cardItem.type}
        auth={auth}
        open={open}
        showToast={showToast}
        fetchitem={() => this.fetchitem()}
        onEdit={(id, value) => this.onEdit(id, value, true)}
      />
    );
  }
  getComments() {
    const { item } = this.state;
    const { theme, vote, auth, open, showToast } = this.props;
    return (
      <Comments
        comments={item.comments}
        theme={theme}
        vote={vote}
        auth={auth}
        open={open}
        showToast={showToast}
        addMention={value => this.addMention(value)}
        fetchitem={() => this.fetchitem()}
        onEdit={(id, value) => this.onEdit(id, value)}
      />
    );
  }
  getPostComment() {
    const { item } = this.state;
    const { theme, auth } = this.props;
    return (
      <PostComment
        comments={item.comments}
        theme={theme}
        auth={auth}
        id={item.rant.id}
        originalPoster={item.rant.user_username}
        fetch={() => this.fetchitem(true)}
        ref={(node) => { this.postComment = node; }}
      />
    );
  }
  renderMutliCol() {
    return (

          {this.getItemCard()}

          {this.getComments()}
          {this.getPostComment()}

    );
  }
  renderSingleColumn() {
    return (

 { this.compactCol = node; }}
      >
        {this.getItemCard()}
        {this.getComments()}
        {this.getPostComment()}

    );
  }
  render() {
    if (!this.state.item) {
      return (

          <Loading />

      );
    }
    return (

 this.handleOnClick(e)}
      >
        { this.state.maxCol === 1 ? this.renderSingleColumn()
          : this.renderMutliCol()
        }

    );
  }
}

Item.propTypes = {
  theme: PropTypes.object.isRequired,
  vote: PropTypes.func.isRequired,
  cardItem: PropTypes.object.isRequired,
  auth: PropTypes.object.isRequired,
  close: PropTypes.func.isRequired,
  open: PropTypes.func.isRequired,
  showToast: PropTypes.func.isRequired,
  fetchNotifs: PropTypes.func.isRequired,
};

export default Item;
<|endoftext|>


<commit_before>/*jslint eqeq: true, indent: 2, node: true, plusplus: true, regexp: true, unparam: true, vars: true, nomen: true */
'use strict';

var Schema = require('mongoose').Schema;

/**
 * The article schema.
 */
var PostSchema = new Schema({
  type: {type: Number, 'default': 0},
  author: String,
  catalog: {type: String, ref: 'Catalog'},
  tags: [String],
  title: String,
  content: String,
  date: {type: Date, 'default': Date.now}
});

var statics = PostSchema.statics;

statics.listLatestPosts = function (param, cb) {
  var q = this.find();
  if (param) {
    if (param.start) {
      q.skip(param.start);
    }
    if (param.limit) {
      q.limit(param.limit);
    }
  }
  q.sort({date: 'desc'});
  if (cb) {
    return q.exec(cb);
  } else {
    return q;
  }
};

module.exports = PostSchema;
<commit_msg>Add tag-related functions.<commit_after>/*jslint eqeq: true, indent: 2, node: true, plusplus: true, regexp: true, unparam: true, vars: true, nomen: true */
'use strict';

var Schema = require('mongoose').Schema;

/**
 * The article schema.
 */
var PostSchema = new Schema({
  type: {type: Number, 'default': 0},
  author: String,
  catalog: {type: String, ref: 'Catalog'},
  tags: [String],
  title: String,
  content: String,
  date: {type: Date, 'default': Date.now}
});

var statics = PostSchema.statics;

/**
 * List latest posts by a range.
 *
 * @param {start: .., limit:..} structure.
 * @param cb the optional callback
 * @return mongoose#Query if cb is not specified.
 */
statics.listLatestPosts = function (param, cb) {
  var q = this.find();
  if (param) {
    if (param.start) {
      q.skip(param.start);
    }
    if (param.limit) {
      q.limit(param.limit);
    }
  }
  q.sort({date: 'desc'});
  if (cb) {
    return q.exec(cb);
  } else {
    return q;
  }
};

/**
 * List posts by a specific tag(s).
 *
 * @param tags the list of tags or a single tag.
 * @param param the {start: .., limit: ..} structure.
 * @return mongoose#Query
 */
statics.listByTags = function (tags, param, cb) {
  if (typeof tags == 'string') {
    tags = [tags];
  }
  var q = this.find({tags: {$all: tags}});
  if (param) {
    if (param.start) {
      q.skip(param.start);
    }
    if (param.limit) {
      q.limit(param.limit);
    }
  }
  q.sort({date: 'desc'});
  if (cb) {
    return q.exec(cb);
  } else {
    return q;
  }
};

/**
 * List posts of a user by a specific tag(s).
 *
 * @param user the name of user.
 * @param tags the list of tags or a single tag.
 * @param param the {start: .., limit: ..} structure.
 * @return mongoose#Query
 */
statics.listByUserTags = function (user, tags, param, cb) {
  if (typeof tags == 'string') {
    tags = [tags];
  }
  var q = this.find({tags: {$all: tags}, author: user});
  if (param) {
    if (param.start) {
      q.skip(param.start);
    }
    if (param.limit) {
      q.limit(param.limit);
    }
  }
  q.sort({date: 'desc'});
  if (cb) {
    return q.exec(cb);
  } else {
    return q;
  }
};

module.exports = PostSchema;
<|endoftext|>


<commit_before>(function () {
var factory = function (Hash, Nacl, Scrypt/*, Util, Cred, nThen */) {
    var Invite = {};

    Invite.deriveSeeds = function (seed) {
        // take the hash of the provided seed
        var u8_seed = Nacl.hash(Nacl.util.decodeBase64(seed));

        // hash the first half again for scrypt's input
        var subseed1 = Nacl.hash(u8_seed.subarray(0, 32));
        // hash the remainder for the invite content
        var subseed2 = Nacl.hash(u8_seed.subarray(32));

        return {
            scrypt: Nacl.util.encodeBase64(subseed1),
            preview: Nacl.util.encodeBase64(subseed2),
        };
    };

    Invite.derivePreviewHash = function (seeds) {
        return '#/2/invite/view/' +
            Nacl.util.encodeBase64(seeds.preview.slice(0, 18)).replace('/', '-')
            + '/';
    };

    Invite.derivePreviewSecrets = function (seeds) {
        return Hash.getSecrets('pad', Invite.derivePreviewHash(seeds));
    };

    Invite.deriveSalt = function (password, instance_salt) {
        return (password || '') + (instance_salt || '');
    };

    // seed => bytes64
    Invite.deriveBytes = function (scrypt_seed, salt, cb) {
        Scrypt(scrypt_seed,
            salt,
            8, // memoryCost (n)
            1024, // block size parameter (r)
            192, // dkLen
            200, // interruptStep
            cb,
            'base64'); // format, could be 'base64'
    };

    Invite.getPreviewContent = function (seeds, cb) {
        var secrets = Invite.derivePreviewSecrets(seeds);
        secrets = secrets;
        cb("NOT_IMPLEMENTED"); // XXX cryptget
    };

    // XXX remember to pin invites...
    Invite.setPreviewContent = function (seeds, cb) {
        cb = cb;
    };

    return Invite;
};
    if (typeof(module) !== 'undefined' && module.exports) {
        module.exports = factory(
            require("../common-hash"),
            require("tweetnacl/nacl-fast"),
            require("scrypt-async")
        );
    } else if ((typeof(define) !== 'undefined' && define !== null) && (define.amd !== null)) {
        define([
            '/common/common-hash.js',
            '/bower_components/tweetnacl/nacl-fast.min.js',
            '/bower_components/scrypt_async/scrypt-async.min.js',
        ], function (Hash /*, Nacl, Scrypt */) {
            return factory(Hash, window.nacl, window.Scrypt);
        });
    }
}());
<commit_msg>Cryptget in common/invitation<commit_after>(function () {
var factory = function (Hash, Crypt, Nacl, Scrypt/*, Util, Cred, nThen */) {
    var Invite = {};

    Invite.deriveSeeds = function (seed) {
        // take the hash of the provided seed
        var u8_seed = Nacl.hash(Nacl.util.decodeBase64(seed));

        // hash the first half again for scrypt's input
        var subseed1 = Nacl.hash(u8_seed.subarray(0, 32));
        // hash the remainder for the invite content
        var subseed2 = Nacl.hash(u8_seed.subarray(32));

        return {
            scrypt: Nacl.util.encodeBase64(subseed1),
            preview: Nacl.util.encodeBase64(subseed2),
        };
    };

    Invite.derivePreviewHash = function (seeds) {
        return '#/2/invite/view/' +
            Nacl.util.encodeBase64(seeds.preview.slice(0, 18)).replace('/', '-')
            + '/';
    };

    Invite.derivePreviewSecrets = function (seeds) {
        return Hash.getSecrets('pad', Invite.derivePreviewHash(seeds));
    };

    Invite.deriveSalt = function (password, instance_salt) {
        return (password || '') + (instance_salt || '');
    };

    // seed => bytes64
    Invite.deriveBytes = function (scrypt_seed, salt, cb) {
        Scrypt(scrypt_seed,
            salt,
            8, // memoryCost (n)
            1024, // block size parameter (r)
            192, // dkLen
            200, // interruptStep
            cb,
            'base64'); // format, could be 'base64'
    };

    Invite.getPreviewContent = function (seeds, cb) {
        /*
        var secrets = Invite.derivePreviewSecrets(seeds);
        secrets = secrets;
        */
        var hash = Invite.derivePreviewHash(seeds);
        Crypt.get(hash, function (err, val) {
            if (err) { return void cb(err); }
            try {
                cb(void 0, JSON.parse(val));
            } catch (e) {
                console.error(e);
                cb(e);
            }
        });
//        cb("NOT_IMPLEMENTED"); // XXX cryptget
    };

    // XXX remember to pin invites...
    Invite.setPreviewContent = function (seeds, cb) {
        var hash = Invite.derivePreviewHash(seeds);
        Crypt.put(hash, '', function (err) { // value?
            cb(err);
        });
        //cb = cb;
    };

    return Invite;
};
    if (typeof(module) !== 'undefined' && module.exports) {
        module.exports = factory(
            require("../common-hash"),
            require("../cryptget"), // XXX npm cryptget?
            require("tweetnacl/nacl-fast"),
            require("scrypt-async")
        );
    } else if ((typeof(define) !== 'undefined' && define !== null) && (define.amd !== null)) {
        define([
            '/common/common-hash.js',
            '/common/cryptget.js',
            '/bower_components/tweetnacl/nacl-fast.min.js',
            '/bower_components/scrypt_async/scrypt-async.min.js',
        ], function (Hash, Crypt /*, Nacl, Scrypt */) {
            return factory(Hash, Crypt, window.nacl, window.Scrypt);
        });
    }
}());
<|endoftext|>


<commit_before>var mongoose = require('mongoose'),
  Schema = mongoose.Schema,
  ObjectId = Schema.Types.ObjectId;

var user = new Schema({
  _id: String,
  name: String,
  email: String,
  office: String,
  phone: String,
  mobile: String,
  roles: [String],
  lastVisitedOn: Date,
  forms: [ObjectId],
  travelers: [ObjectId],
  subscribe: {
    type: Boolean,
    default: false
  }
});

var group = new Schema({
  _id: String,
  name: String,
  forms: [ObjectId],
  travelers: [ObjectId]
});

var User = mongoose.model('User', user);
module.exports = {
  User: User
};
<commit_msg>export group in model<commit_after>var mongoose = require('mongoose'),
  Schema = mongoose.Schema,
  ObjectId = Schema.Types.ObjectId;

var user = new Schema({
  _id: String,
  name: String,
  email: String,
  office: String,
  phone: String,
  mobile: String,
  roles: [String],
  lastVisitedOn: Date,
  forms: [ObjectId],
  travelers: [ObjectId],
  subscribe: {
    type: Boolean,
    default: false
  }
});

var group = new Schema({
  _id: String,
  name: String,
  forms: [ObjectId],
  travelers: [ObjectId]
});

var User = mongoose.model('User', user);
var Group = mongoose.model('Group', group);
module.exports = {
  User: User,
  Group: Group
};
<|endoftext|>


<commit_before>'use strict';
var JsonUtil = require("./shared/JsonUtil");
var services = angular.module('firenodejs.services');

services.factory('camera-service', ['$http',
    function($http) {
        var available = null;
        var service = {
            isAvailable: function() {
                return available === true;
            },
            model: {
                selected:"default",
                aspect:"1:1",
            },
            changeCount: 0,
            reticle: {
                opacity: 1,
                color: "fuchsia"
            },
            crosshair: {
                opacity: 1,
                color: "fuchsia"
            },
            image: {
                height: 150,
            },
            index: function(externalIndex) {
                return externalIndex * 1000 + service.changeCount;
            },
            getSyncJson: function() {
                return service.model;
            },
            updateAspect: function() {
                var aspectW = service.model.width == null ? 640 : service.model.width;
                var aspectH = service.model.height == null ? 480 : service.model.height;
                service.image.width = service.image.height * aspectW / aspectH;
                service.image.style = "width:" + service.image.width + "px !important; height:" + service.image.height + "px !important";
            },
            onResize: function() {
                if (service.image.height === 100) {
                    service.image.height = 200;
                } else if (service.image.height === 200) {
                    service.image.height = 300;
                } else {
                    service.image.height = 100;
                }
                service.updateAspect();
            },
            onReticle: function() {
                if (service.reticle.opacity) {
                    service.reticle.opacity = 0;
                } else if (service.crosshair.opacity) {
                    service.crosshair.opacity = 0;
                } else {
                    service.reticle.opacity = 1;
                    service.crosshair.opacity = 1;
                }
            },
            onChange: function() {
                available = null;
                service.changeCount++;
                console.log("camera changed:", service.model.selected);
                $.ajax({
                    url: "/camera/" + service.model.selected + "/model",
                    success: function(data) {
                        available = data && data.available;
                        JsonUtil.applyJson(service.model, data);
                    },
                    error: function(jqXHR, ex) {
                        available = false;
                    }
                });
            }
        };
        service.onResize();
        service.onChange();
        $.ajax({
            url: "/camera/default/image.jpg",
            success: function(data) {
                available = true;
                console.log("camera available:", available);
            },
            error: function(jqXHR, ex) {
                available = false;
                console.warn("camera unavailable:", jqXHR, ex);
            }
        });
        return service;
    }
]);
<commit_msg>aspect<commit_after>'use strict';
var JsonUtil = require("./shared/JsonUtil");
var services = angular.module('firenodejs.services');

services.factory('camera-service', ['$http',
    function($http) {
        var available = null;
        var service = {
            isAvailable: function() {
                return available === true;
            },
            model: {
                selected:"default",
            },
            changeCount: 0,
            reticle: {
                opacity: 1,
                color: "fuchsia"
            },
            crosshair: {
                opacity: 1,
                color: "fuchsia"
            },
            image: {
                height: 150,
            },
            index: function(externalIndex) {
                return externalIndex * 1000 + service.changeCount;
            },
            getSyncJson: function() {
                return service.model;
            },
            updateAspect: function() {
                var aspectW = service.model.width == null ? 640 : service.model.width;
                var aspectH = service.model.height == null ? 480 : service.model.height;
                service.image.width = service.image.height * aspectW / aspectH;
                service.image.style = "width:" + service.image.width + "px !important; height:" + service.image.height + "px !important";
            },
            onResize: function() {
                if (service.image.height === 100) {
                    service.image.height = 200;
                } else if (service.image.height === 200) {
                    service.image.height = 300;
                } else {
                    service.image.height = 100;
                }
                service.updateAspect();
            },
            onReticle: function() {
                if (service.reticle.opacity) {
                    service.reticle.opacity = 0;
                } else if (service.crosshair.opacity) {
                    service.crosshair.opacity = 0;
                } else {
                    service.reticle.opacity = 1;
                    service.crosshair.opacity = 1;
                }
            },
            onChange: function() {
                available = null;
                service.changeCount++;
                console.log("camera changed:", service.model.selected);
                $.ajax({
                    url: "/camera/" + service.model.selected + "/model",
                    success: function(data) {
                        available = data && data.available;
                        JsonUtil.applyJson(service.model, data);
                        service.updateAspect();
                    },
                    error: function(jqXHR, ex) {
                        available = false;
                    }
                });
            }
        };
        service.onResize();
        service.onChange();
        $.ajax({
            url: "/camera/default/image.jpg",
            success: function(data) {
                available = true;
                console.log("camera available:", available);
            },
            error: function(jqXHR, ex) {
                available = false;
                console.warn("camera unavailable:", jqXHR, ex);
            }
        });
        return service;
    }
]);
<|endoftext|>