<commit_before>/**
 * Copyright (c) 2016 Samsung Electronics, Inc.,
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
"use strict";

const database = require("../util/database");
const log = require('../util/logging');
const route = require('./route');
const project = require('./project');
const server = require('./server');
const http = require('http');
const fs = require('fs');
const Promise = require('bluebird');
const rp = require('request-promise');
const mysql = require("mysql");
const _ = require("lodash");

exports.getAll = function(req, res) {
    const activeServerList = _.filter(server.getServerListInternal(), {'active': true});
    let allRows = [];
    let promises = [];

    Promise.map(activeServerList, (server) => {
        promises.push(new Promise((resolve) => {
            const userListUrl = `http://${server.hostIP}:${server.portNumber}/api/v2/user-list`;
            rp(userListUrl)
                .then((data) => {
                    const rows = JSON.parse('' + data).rows;
                    if (rows) {
                        rows.forEach((row) => {
                            allRows.push({
                                projectName: server.projectName,
                                userId: row.userId
                            });
                        });
                    }
                    resolve();
                })
                .catch((err) => {
                    log.error(`Failed to get user list for pid ${server.pid} : ${err}`);
                    resolve();
                });
        }));
    });

    Promise.all(promises)
        .then(() => {
            allRows = _.sortBy(allRows, 'projectName');
            res.send({status:'ok', rows: allRows});
        })
        .catch((err) => {
            log.error(err);
            res.send({status:"fail", errorMessage: err.message});
        });
};

function processReturnedData(data) {
    return data.replace(/((\])|(\[))/g,'').replace(/(^\s*)|(\s*$)/g,'');
}

function loadUserInfo(userId, userInfoUrl, userInfoList) {
    return rp(userInfoUrl + userId)
        .then((data) => {
            data = processReturnedData(data);
            if (!data || !validateUserInfoJson(data, userId)) {
                log.error('Not found user data: ' + userId);
                userInfoList.push({'userId':userId});
            } else {
                const infoJson = JSON.parse('' + data);
                userInfoList.push({
                    'userId':userId,
                    'name':infoJson.cn,
                    'department':infoJson.department,
                    'title':infoJson.title,
                    'employeeNumber':infoJson.employeenumber});
            }
        })
        .catch((err) => {
            log.error(err);
            userInfoList.push({'userId':userId});
        });
}

exports.getMoreInfoByUserIdList = function(req, res) {
    const configText = fs.readFileSync("./config.json", 'utf8');
    const configJson = JSON.parse(configText);
    const userInfoUrl = configJson.userInfoUrl;
    const userIdList = req.params.userIdList.split(",");

    let userInfoList = [];
    let promises = [];
    userIdList.forEach((userId) => {
        promises.push(loadUserInfo(userId, userInfoUrl, userInfoList));
    });

    Promise.all(promises)
        .then(() => {
            res.send({status:'ok', rows: userInfoList});
        })
        .catch((err) => {
            log.error(err);
            res.send({status:"fail", errorMessage: err.message});
        });
};

function validateUserInfoJson(data, userid) {
    if(data.indexOf("\"userid\":\"" + userid + "\"") < 0) {
        log.error('Incorrect result from user info server');
        return false;
    }
    return true;
}

exports.getUserCountByProjectName = function(req, res) {
    const projectServer = _.find(server.getServerListInternal(), {'projectName': req.params.projectName});
    const userCountUrl = `http://${projectServer.hostIP}:${projectServer.portNumber}/api/v2/user-count`;
    rp(userCountUrl)
        .then((data) => {
            const parsedData = JSON.parse('' + data);
            res.send({status:'ok', value: parsedData.value});
        })
        .catch((err) => {
            log.error(`Failed to get user count for pid ${projectServer.pid} : ${err}`);
            res.send({status:"fail", errorMessage: err.message});
        });
};

function loadUserStatusList() {
    const sql = "SELECT userId, dexterYn FROM DexterUserList";
    return database.exec(sql)
        .then((rows) => {
            return rows;
        })
        .catch((err) => {
            log.error(err);
            return [];
        });
}

function loadUserList() {
    const activeServerList = _.filter(server.getServerListInternal(), {'active': true});
    let allRows = [];
    let promises = [];

    return Promise.map(activeServerList, (server) => {
        promises.push(new Promise((resolve) => {
            const userListUrl = `http://${server.hostIP}:${server.portNumber}/api/v2/user-list`;
            rp(userListUrl)
                .then((data) => {
                    const rows = JSON.parse('' + data).rows;
                    if (rows) {
                        allRows = _.union(allRows, rows);
                    }
                    resolve();
                })
                .catch((err) => {
                    log.error(`Failed to get user list for pid ${server.pid} : ${err}`);
                    resolve();
                });
        }));

        return Promise.all(promises)
            .then(() => {
                allRows = _.uniq(allRows, (row) => {
                    return row.userId;
                });
                return allRows;
            })
            .catch((err) => {
                log.error(err);
                return [];
            });
    });
}

function updateUserStatusList() {
    let promises = [];
    let userStatusList = [];
    let userList = [];

    promises.push(new Promise((resolve, reject) => {
        loadUserStatusList()
            .then((rows) => {
                userStatusList = rows;
                resolve();
            })
            .catch((err) => {
                log.error(err);
                reject();
            })
    }));
    promises.push(new Promise((resolve, reject) => {
        loadUserList()
            .then((rows) => {
                userList = rows;
                resolve();
            })
            .catch((err) => {
                log.error(err);
                reject();
            })
    }));

    return Promise.all(promises)
        .then(() => {
            return Promise.map(userStatusList, (row) => {
                if (_.findIndex(userList, (user) => user.userId == row.userId) >= 0) {
                    row.dexterYn = 'Y';
                } else if (row.dexterYn == 'Y') {
                    row.dexterYn = 'N';
                } else {
                    return;
                }

                const sql =
                    `UPDATE DexterUserList
                     SET dexterYn='${row.dexterYn}', reason='', ide='', language=''
                     WHERE userId='${row.userId}'`;
                return database.exec(sql)
                    .catch((err) => {
                        log.error('Failed to set dexterYn : ' + err);
                    });
            });
        });
}

function loadAndCreateUserStatusTable() {
    const sql = `SELECT DexterUserList.userLab AS groupName,
                        COUNT(DexterUserList.userId) AS allDeveloperCount,
                        installedDeveloperCount,
                        nonTargetDeveloperCount
                 FROM DexterUserList
                 LEFT JOIN (SELECT userLab, COUNT(DUL1.userId) AS installedDeveloperCount
                            FROM DexterUserList AS DUL1
                            WHERE DUL1.dexterYn='y'
                            GROUP BY DUL1.userLab) AS d1
                 ON DexterUserList.userLab = d1.userLab
                 LEFT JOIN (SELECT userLab, COUNT(DUL2.userId) AS nonTargetDeveloperCount
                            FROM DexterUserList AS DUL2
                            WHERE DUL2.dexterYn='u'
                            GROUP BY DUL2.userLab) AS d2
                 ON DexterUserList.userLab = d2.userLab
                 GROUP BY DexterUserList.userLab`;
    return database.exec(sql)
        .then((rows) => {
            rows.forEach((row) => {
                row.targetDeveloperCount = getTargetDeveloperCount(row);
                row.installationRatio = getInstallationRatio(row);
            });
            return rows;
        });
}

function getTargetDeveloperCount(row) {
    return row.allDeveloperCount - row.nonTargetDeveloperCount;
}

function getInstallationRatio(row) {
    return (row.installedDeveloperCount / row.targetDeveloperCount * 100).toFixed(1);
}

exports.getUserStatus = function(req, res) {
    updateUserStatusList()
        .then(loadAndCreateUserStatusTable)
        .then((userStatusTable) => {
            res.send({status:'ok', rows: userStatusTable});
        })
        .catch((err) => {
            res.send({status:"fail", errorMessage: err.message});
        });
};

exports.getUserStatusInternal = function() {
    return updateUserStatusList()
        .then(loadAndCreateUserStatusTable)
        .then((userStatusTable) => {
            return userStatusTable;
        })
        .catch((err) => {
            log.error(`Failed to get user status : ${err}`);
            return [];
        });
};<commit_msg>[dexter-monitor] Fix bug in 'loadUserList' function<commit_after>/**
 * Copyright (c) 2016 Samsung Electronics, Inc.,
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
"use strict";

const database = require("../util/database");
const log = require('../util/logging');
const route = require('./route');
const project = require('./project');
const server = require('./server');
const http = require('http');
const fs = require('fs');
const Promise = require('bluebird');
const rp = require('request-promise');
const mysql = require("mysql");
const _ = require("lodash");

exports.getAll = function(req, res) {
    const activeServerList = _.filter(server.getServerListInternal(), {'active': true});
    let allRows = [];
    let promises = [];

    Promise.map(activeServerList, (server) => {
        promises.push(new Promise((resolve) => {
            const userListUrl = `http://${server.hostIP}:${server.portNumber}/api/v2/user-list`;
            rp(userListUrl)
                .then((data) => {
                    const rows = JSON.parse('' + data).rows;
                    if (rows) {
                        rows.forEach((row) => {
                            allRows.push({
                                projectName: server.projectName,
                                userId: row.userId
                            });
                        });
                    }
                    resolve();
                })
                .catch((err) => {
                    log.error(`Failed to get user list for pid ${server.pid} : ${err}`);
                    resolve();
                });
        }));
    });

    Promise.all(promises)
        .then(() => {
            allRows = _.sortBy(allRows, 'projectName');
            res.send({status:'ok', rows: allRows});
        })
        .catch((err) => {
            log.error(err);
            res.send({status:"fail", errorMessage: err.message});
        });
};

function processReturnedData(data) {
    return data.replace(/((\])|(\[))/g,'').replace(/(^\s*)|(\s*$)/g,'');
}

function loadUserInfo(userId, userInfoUrl, userInfoList) {
    return rp(userInfoUrl + userId)
        .then((data) => {
            data = processReturnedData(data);
            if (!data || !validateUserInfoJson(data, userId)) {
                log.error('Not found user data: ' + userId);
                userInfoList.push({'userId':userId});
            } else {
                const infoJson = JSON.parse('' + data);
                userInfoList.push({
                    'userId':userId,
                    'name':infoJson.cn,
                    'department':infoJson.department,
                    'title':infoJson.title,
                    'employeeNumber':infoJson.employeenumber});
            }
        })
        .catch((err) => {
            log.error(err);
            userInfoList.push({'userId':userId});
        });
}

exports.getMoreInfoByUserIdList = function(req, res) {
    const configText = fs.readFileSync("./config.json", 'utf8');
    const configJson = JSON.parse(configText);
    const userInfoUrl = configJson.userInfoUrl;
    const userIdList = req.params.userIdList.split(",");

    let userInfoList = [];
    let promises = [];
    userIdList.forEach((userId) => {
        promises.push(loadUserInfo(userId, userInfoUrl, userInfoList));
    });

    Promise.all(promises)
        .then(() => {
            res.send({status:'ok', rows: userInfoList});
        })
        .catch((err) => {
            log.error(err);
            res.send({status:"fail", errorMessage: err.message});
        });
};

function validateUserInfoJson(data, userid) {
    if(data.indexOf("\"userid\":\"" + userid + "\"") < 0) {
        log.error('Incorrect result from user info server');
        return false;
    }
    return true;
}

exports.getUserCountByProjectName = function(req, res) {
    const projectServer = _.find(server.getServerListInternal(), {'projectName': req.params.projectName});
    const userCountUrl = `http://${projectServer.hostIP}:${projectServer.portNumber}/api/v2/user-count`;
    rp(userCountUrl)
        .then((data) => {
            const parsedData = JSON.parse('' + data);
            res.send({status:'ok', value: parsedData.value});
        })
        .catch((err) => {
            log.error(`Failed to get user count for pid ${projectServer.pid} : ${err}`);
            res.send({status:"fail", errorMessage: err.message});
        });
};

function loadUserStatusList() {
    const sql = "SELECT userId, dexterYn FROM DexterUserList";
    return database.exec(sql)
        .then((rows) => {
            return rows;
        })
        .catch((err) => {
            log.error(err);
            return [];
        });
}

function loadUserList() {
    const activeServerList = _.filter(server.getServerListInternal(), {'active': true});
    let allRows = [];
    let promises = [];

    Promise.map(activeServerList, (server) => {
        promises.push(new Promise((resolve) => {
            const userListUrl = `http://${server.hostIP}:${server.portNumber}/api/v2/user-list`;
            rp(userListUrl)
                .then((data) => {
                    const rows = JSON.parse('' + data).rows;
                    if (rows) {
                        allRows = _.union(allRows, rows);
                    }
                    resolve();
                })
                .catch((err) => {
                    log.error(`Failed to get user list for pid ${server.pid} : ${err}`);
                    resolve();
                });
        }));
    });

    return Promise.all(promises)
        .then(() => {
            allRows = _.uniq(allRows, (row) => {
                return row.userId;
            });
            return allRows;
        })
        .catch((err) => {
            log.error(err);
            return [];
        });
}

function updateUserStatusList() {
    let promises = [];
    let userStatusList = [];
    let userList = [];

    promises.push(new Promise((resolve, reject) => {
        loadUserStatusList()
            .then((rows) => {
                userStatusList = rows;
                resolve();
            })
            .catch((err) => {
                log.error(err);
                reject();
            })
    }));
    promises.push(new Promise((resolve, reject) => {
        loadUserList()
            .then((rows) => {
                userList = rows;
                resolve();
            })
            .catch((err) => {
                log.error(err);
                reject();
            })
    }));

    return Promise.all(promises)
        .then(() => {
            return Promise.map(userStatusList, (row) => {
                if (_.findIndex(userList, (user) => user.userId == row.userId) >= 0) {
                    row.dexterYn = 'Y';
                } else if (row.dexterYn == 'Y') {
                    row.dexterYn = 'N';
                } else {
                    return;
                }

                const sql =
                    `UPDATE DexterUserList
                     SET dexterYn='${row.dexterYn}', reason='', ide='', language=''
                     WHERE userId='${row.userId}'`;
                return database.exec(sql)
                    .catch((err) => {
                        log.error('Failed to set dexterYn : ' + err);
                    });
            });
        });
}

function loadAndCreateUserStatusTable() {
    const sql = `SELECT DexterUserList.userLab AS groupName,
                        COUNT(DexterUserList.userId) AS allDeveloperCount,
                        installedDeveloperCount,
                        nonTargetDeveloperCount
                 FROM DexterUserList
                 LEFT JOIN (SELECT userLab, COUNT(DUL1.userId) AS installedDeveloperCount
                            FROM DexterUserList AS DUL1
                            WHERE DUL1.dexterYn='y'
                            GROUP BY DUL1.userLab) AS d1
                 ON DexterUserList.userLab = d1.userLab
                 LEFT JOIN (SELECT userLab, COUNT(DUL2.userId) AS nonTargetDeveloperCount
                            FROM DexterUserList AS DUL2
                            WHERE DUL2.dexterYn='u'
                            GROUP BY DUL2.userLab) AS d2
                 ON DexterUserList.userLab = d2.userLab
                 GROUP BY DexterUserList.userLab`;
    return database.exec(sql)
        .then((rows) => {
            rows.forEach((row) => {
                row.targetDeveloperCount = getTargetDeveloperCount(row);
                row.installationRatio = getInstallationRatio(row);
            });
            return rows;
        });
}

function getTargetDeveloperCount(row) {
    return row.allDeveloperCount - row.nonTargetDeveloperCount;
}

function getInstallationRatio(row) {
    return (row.installedDeveloperCount / row.targetDeveloperCount * 100).toFixed(1);
}

exports.getUserStatus = function(req, res) {
    updateUserStatusList()
        .then(loadAndCreateUserStatusTable)
        .then((userStatusTable) => {
            res.send({status:'ok', rows: userStatusTable});
        })
        .catch((err) => {
            res.send({status:"fail", errorMessage: err.message});
        });
};

exports.getUserStatusInternal = function() {
    return updateUserStatusList()
        .then(loadAndCreateUserStatusTable)
        .then((userStatusTable) => {
            return userStatusTable;
        })
        .catch((err) => {
            log.error(`Failed to get user status : ${err}`);
            return [];
        });
};<|endoftext|>


<commit_before>var e = module.exports = {};
var bu = require('./../util.js');

var bot;
e.init = (Tbot) => {
    bot = Tbot;
};

e.requireCtx = require;

e.isCommand = true;
e.hidden = false;
e.usage = 'todo [remove <item id> | add <item>]';
e.info = 'Access your todo list.\n'
    + 'To add items, do `todo add <item>`.\n'
    + 'To remove items, do `todo remove <item id>`, where item id is the number shown when you do `todo` by itself.';
e.longinfo = `
Access your todo list.

To add items, do todo add <item>.

To remove items, do todo remove <item id>, where item id is the number shown when you do <todo> by itself.
`;
e.category = bu.CommandType.GENERAL;

e.execute = (msg, words) => {
    var db = bu.db;
    if (words.length > 1) {
        var itemid;
        switch (words[1].toLowerCase()) {
            case 'add':
                console.log('adding');
                if (words.length < 3) {
                    bu.send(msg.channel.id, 'Not enough arguments given!');
                    return;
                }
                db.query(`select itemid from todo where userid = ? order by itemid desc limit 1`, [msg.author.id], (err, rows) => {
                    itemid = 0;
                    console.log(err);
                    if (rows && rows[0]) {
                        itemid = rows[0].itemid + 1;
                    }
                    db.query(`insert into todo (userid, itemid, content) values (?, ?, ?)`,
                        [msg.author.id, itemid, words.slice(2, words.length).join(' ')]);
                    bu.send(msg.channel.id, 'Done');

                });
                break;
            case 'remove':
                console.log('removing');
                if (words.length < 3) {
                    bu.send(msg.channel.id, 'Not enough arguments given!');
                    return;
                }
                db.query(`select itemid, content from todo where userid = ?`, [msg.author.id], (err, rows) => {
                    if (!rows && !rows[0]) {
                        bu.send(msg.channel.id, 'There was nothing to delete.');
                    }
                    db.query(`delete from todo where userid = ?`, [msg.author.id], () => {
                        var itemid = 0;
                        for (var i = 0; i < rows.length; i++) {
                            if (rows[i].itemid != words[2]) {
                                db.query(`insert into todo (userid, itemid, content) values (?, ?, ?)`,
                                    [msg.author.id, itemid, rows[i].content]);
                                itemid++;
                            }
                            if (i == rows.length - 1) {
                                bu.send(msg.channel.id, 'Done');
                            }
                        }
                    });
                });
                break;
            default:
                defaultOption(msg, db);
        }
    } else {
        defaultOption(msg, db);
    }
};

function defaultOption(msg, db) {
    db.query(`select itemid, content from todo where userid = ?`, [msg.author.id], (err, rows) => {
        if (rows.length > 0) {
            var list = 'Here\'s your to-do list!\n';
            for (i = 0; i < rows.length; i++) {
                list += rows[i].itemid + '. ' + rows[i].content + '\n';
            }
            bu.send(msg.channel.id, list);
        } else {
            bu.send(msg.channel.id, 'You have nothing on your list!');
        }
    });
} <commit_msg>made todo work more efficiently<commit_after>var e = module.exports = {};
var bu = require('./../util.js');

var bot;
e.init = (Tbot) => {
    bot = Tbot;
};

e.requireCtx = require;

e.isCommand = true;
e.hidden = false;
e.usage = 'todo [remove <item id> | add <item>]';
e.info = 'Access your todo list.\n'
    + 'To add items, do `todo add <item>`.\n'
    + 'To remove items, do `todo remove <item id>`, where item id is the number shown when you do `todo` by itself.';
e.longinfo = `
Access your todo list.

To add items, do todo add <item>.

To remove items, do todo remove <item id>, where item id is the number shown when you do <todo> by itself.
`;
e.category = bu.CommandType.GENERAL;

e.execute = (msg, words) => {
    var db = bu.db;
    if (words.length > 1) {
        var itemid;
        switch (words[1].toLowerCase()) {
            case 'add':
                console.log('adding');
                if (words.length < 3) {
                    bu.send(msg.channel.id, 'Not enough arguments given!');
                    return;
                }

                db.query(`insert into todo (userid, content) values (?, ?)`,
                    [msg.author.id, words.slice(2, words.length).join(' ')]);
                bu.send(msg.channel.id, 'Done');
                break;
            case 'remove':
                console.log('removing');
                if (words.length < 3) {
                    bu.send(msg.channel.id, 'Not enough arguments given!');
                    return;
                }
                db.query(`select itemid from todo where userid = ? and active = true order by itemid asc limit ?, 1`, [msg.author.id, parseInt(words[2])], (err, rows) => {
                    if (!rows && !rows[0]) {
                        bu.send(msg.channel.id, 'There was nothing to delete.');
                    }
                    console.log(rows[0]);
                    db.query(`update todo set active = false where itemid = ?`, [rows[0].itemid]);
                    bu.send(msg.channel.id, 'Done');
                });
                break;
            default:
                defaultOption(msg, db);
        }
    } else {
        defaultOption(msg, db);
    }
};

function defaultOption(msg, db) {
    db.query(`select content from todo where userid = ? and active = true`, [msg.author.id], (err, rows) => {
        if (rows.length > 0) {
            var list = 'Here\'s your to-do list!\n';
            for (i = 0; i < rows.length; i++) {
                list += i + '. ' + rows[i].content + '\n';
            }
            bu.send(msg.channel.id, list);
        } else {
            bu.send(msg.channel.id, 'You have nothing on your list!');
        }
    });
} <|endoftext|>


<commit_before>/**
 * @file DropdownSelect component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {findDOMNode} from 'react-dom';

import RaisedButton from '../RaisedButton';
import TextField from '../TextField';
import Popup from '../Popup';
import List from '../List';
import Theme from '../Theme';

import Util from '../_vendors/Util';
import Dom from '../_vendors/Dom';

export default class DropdownSelect extends Component {

    static Mode = List.Mode;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            value: props.value,
            filter: '',
            popupVisible: false,
            isAbove: false
        };

        this.isAbove = ::this.isAbove;
        this.filterChangeHandle = ::this.filterChangeHandle;
        this.togglePopup = ::this.togglePopup;
        this.closePopup = ::this.closePopup;
        this.filterData = ::this.filterData;
        this.popupRenderHandle = ::this.popupRenderHandle;
        this.changeHandler = ::this.changeHandler;

    }

    isAbove() {

        const dropdownSelect = this.refs.dropdownSelect;

        if (!this.popupHeight || !dropdownSelect) {
            return false;
        }

        const {top} = Dom.getOffset(dropdownSelect),
            scrollTop = Dom.getScrollTop();

        if (top + this.triggerHeight + this.popupHeight - scrollTop > window.innerHeight) {
            return true;
        }

        return false;

    }

    filterChangeHandle(filter) {
        this.setState({
            filter
        });
    }

    togglePopup() {
        this.setState({
            popupVisible: !this.state.popupVisible
        }, () => {
            this.props.onTriggerTouchTap && this.props.onTriggerTouchTap(this.state.popupVisible);
        });
    }

    closePopup() {
        this.setState({
            popupVisible: false
        }, () => {
            this.props.onClosePopup && this.props.onClosePopup();
        });
    }

    filterData(filter = this.state.filter, data = this.props.data) {

        if (!filter) {
            return data;
        }

        const {displayField, isGrouped} = this.props,
            filterFunc = (originData) => {
                return originData.filter(item => typeof item === 'object' && !!item[displayField] ?
                    item[displayField].toString().toUpperCase().includes(filter.toUpperCase())
                    :
                    item.toString().toUpperCase().includes(filter.toUpperCase()));
            };

        if (isGrouped) {

            let result = Object.assign(data);

            for (let i = 0, len = result.length; i < len; i++) {
                let group = result[i];
                group.children = filterFunc(group.children);
                if (group.children.length < 1) {
                    result.splice(i, 1);
                    i--;
                }
            }

        }

        return filterFunc(data);

    }

    popupRenderHandle(popupEl) {

        this.popupEl = findDOMNode(popupEl);
        this.popupHeight = this.popupEl.offsetHeight;

        const isAbove = this.isAbove();

        if (isAbove !== this.state.isAbove) {
            this.setState({
                isAbove
            });
        }

    }

    changeHandler(value) {

        const {autoClose} = this.props,
            state = {
                value
            };

        if (autoClose) {
            state.popupVisible = false;
        }

        this.setState(state, () => {
            const {onChange} = this.props;
            onChange && onChange(value);
        });

    }

    componentDidMount() {
        this.triggerEl = findDOMNode(this.refs.trigger);
        this.triggerHeight = this.triggerEl.clientHeight;
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.props.value) {
            this.setState({
                value: nextProps.value
            });
        }
    }

    render() {

        const {
                className, popupClassName, style, popupStyle, theme, name, placeholder,
                disabled, mode, useFilter, valueField, displayField, descriptionField, noMatchedMsg,
                isGrouped, itemTouchTapHandle, disableTouchRipple
            } = this.props,
            {value, filter, popupVisible, isAbove} = this.state,

            emptyEl = [{
                itemRenderer() {
                    return (

                            {
                                noMatchedMsg ?
                                    noMatchedMsg
                                    :

                                        No matched value.

                            }

                    );
                }
            }],

            triggerClassName = (popupVisible ? ' activated' : '') + (isAbove ? ' above' : ' blow')
                + (value ? '' : ' empty'),
            triggerValue = value ?
                (
                    mode === List.Mode.CHECKBOX ?
                        (
                            value.length > 0 ?
                                value.length + ' selected'
                                :
                                placeholder
                        )
                        :
                        Util.getTextByDisplayField(value, displayField, valueField)
                )
                :
                placeholder,

            dropdownSelectPopupClassName = (isAbove ? ' above' : ' blow')
                + (popupClassName ? ' ' + popupClassName : ''),
            dropdownPopupStyle = Object.assign({
                width: this.triggerEl && getComputedStyle(this.triggerEl).width
            }, popupStyle),

            listData = this.filterData();

        return (

                {
                    name ?
                        <input type="hidden"
                               name={name}
                               value={Util.getValueByValueField(value, valueField, displayField)}/>
                        :
                        null
                }

                <RaisedButton ref="trigger"
                              className={'dropdown-select-trigger' + triggerClassName}
                              theme={theme}
                              value={triggerValue}
                              rightIconCls={`fa fa-angle-${isAbove ? 'up' : 'down'} dropdown-select-trigger-icon`}
                              disabled={disabled}
                              disableTouchRipple={disableTouchRipple}
                              onTouchTap={this.togglePopup}/>

                <Popup ref="popup"
                       className={'dropdown-select-popup' + dropdownSelectPopupClassName}
                       style={dropdownPopupStyle}
                       theme={theme}
                       visible={popupVisible}
                       triggerEl={this.triggerEl}
                       hasTriangle={false}
                       position={isAbove ? Popup.Position.TOP_LEFT : Popup.Position.BOTTOM_LEFT}
                       onRender={this.popupRenderHandle}
                       onRequestClose={this.closePopup}>

                    {
                        useFilter ?
                            <TextField className="dropdown-select-filter"
                                       value={filter}
                                       rightIconCls="fa fa-search"
                                       onChange={this.filterChangeHandle}/>
                            :
                            null
                    }

                    <List className="dropdown-select-list"
                          theme={theme}
                          mode={mode}
                          isGrouped={isGrouped}
                          items={listData.length < 1 ? emptyEl : listData}
                          value={value}
                          valueField={valueField}
                          displayField={displayField}
                          descriptionField={descriptionField}
                          onItemTouchTap={itemTouchTapHandle}
                          onChange={this.changeHandler}/>

                </Popup>

        );

    }
};

DropdownSelect.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The class name of the popup element.
     */
    popupClassName: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Override the styles of the popup element.
     */
    popupStyle: PropTypes.object,

    /**
     * The theme.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The name of the dropDownSelect.
     */
    name: PropTypes.string,

    /**
     * The value of the dropDownSelect.
     */
    value: PropTypes.any,

    /**
     * The placeholder of the dropDownSelect.
     */
    placeholder: PropTypes.string,

    /**
     * The options data.
     */
    data: PropTypes.oneOfType([

        // not grouped
        PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({

            /**
             * The CSS class name of the list button.
             */
            className: PropTypes.string,

            /**
             * Override the styles of the list button.
             */
            style: PropTypes.object,

            /**
             * The theme of the list button.
             */
            theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

            /**
             * The text value of the list button.Type can be string or number.
             */
            value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * The desc value of the list button. Type can be string or number.
             */
            desc: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * If true, the list button will be disabled.
             */
            disabled: PropTypes.bool,

            /**
             * If true,the button will be have loading effect.
             */
            isLoading: PropTypes.bool,

            /**
             * If true,the element's ripple effect will be disabled.
             */
            disableTouchRipple: PropTypes.bool,

            /**
             * Use this property to display an icon. It will display on the left.
             */
            iconCls: PropTypes.string,

            /**
             * Use this property to display an icon. It will display on the right.
             */
            rightIconCls: PropTypes.string,

            /**
             * You can create a complicated renderer callback instead of value and desc prop.
             */
            renderer: PropTypes.func,

            /**
             * Callback function fired when a list item touch-tapped.
             */
            onTouchTap: PropTypes.func

        }), PropTypes.string, PropTypes.number])),

        // grouped
        PropTypes.array

    ]).isRequired,

    /**
     * The invalid message of dropDownSelect.
     */
    invalidMsg: PropTypes.string,

    /**
     * If true,the dropDownSelect will be disabled.
     */
    disabled: PropTypes.bool,

    /**
     * If true,the dropDownSelect will be multiply select.
     */
    multi: PropTypes.bool,

    /**
     * The mode of listItem.Can be normal,checkbox.
     */
    mode: PropTypes.oneOf(Util.enumerateValue(List.Mode)),

    /**
     * The value field name in data. (default: "value")
     */
    valueField: PropTypes.string,

    /**
     * The display field name in data. (default: "text")
     */
    displayField: PropTypes.string,

    /**
     * The description field name in data. (default: "desc")
     */
    descriptionField: PropTypes.string,

    /**
     * The message of the dropDownSelect.
     */
    infoMsg: PropTypes.string,

    /**
     * Use this function to format the options's text.
     */
    textFormat: PropTypes.func,

    /**
     * If true,the drop-down box automatically closed after selection.
     */
    autoClose: PropTypes.bool,

    /**
     * If true,the drop-down box will have search input.
     */
    useFilter: PropTypes.bool,

    /**
     * The message of no matching option.
     */
    noMatchedMsg: PropTypes.string,

    /**
     * If true,the drop-down box will be have group selection.
     */
    isGrouped: PropTypes.bool,

    /**
     * Callback function fired when the button is touch-tapped.
     */
    onItemTouchTap: PropTypes.func,

    /**
     * Callback function fired when the popup is closed.
     */
    onClosePopup: PropTypes.func,

    /**
     * Callback function fired when a menu item is selected.
     */
    onChange: PropTypes.func

};

DropdownSelect.defaultProps = {

    className: '',
    popupClassName: '',
    style: null,
    popupStyle: null,
    theme: Theme.DEFAULT,

    name: '',
    value: null,
    placeholder: 'Please select ...',
    data: [],
    invalidMsg: '',
    disabled: false,
    multi: false,
    mode: List.Mode.NORMAL,

    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',

    infoMsg: '',
    autoClose: true,
    useFilter: false,
    noMatchedMsg: '',
    isGrouped: false

};<commit_msg>update DropdownSelect<commit_after>/**
 * @file DropdownSelect component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {findDOMNode} from 'react-dom';

import RaisedButton from '../RaisedButton';
import TextField from '../TextField';
import Popup from '../Popup';
import List from '../List';
import Theme from '../Theme';

import Util from '../_vendors/Util';
import Dom from '../_vendors/Dom';

export default class DropdownSelect extends Component {

    static Mode = List.Mode;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            value: props.value,
            filter: '',
            popupVisible: false,
            isAbove: false
        };

        this.isAbove = ::this.isAbove;
        this.filterChangeHandle = ::this.filterChangeHandle;
        this.togglePopup = ::this.togglePopup;
        this.closePopup = ::this.closePopup;
        this.filterData = ::this.filterData;
        this.popupRenderHandle = ::this.popupRenderHandle;
        this.changeHandler = ::this.changeHandler;

    }

    isAbove() {

        const dropdownSelect = this.refs.dropdownSelect;

        if (!this.popupHeight || !dropdownSelect) {
            return false;
        }

        const {top} = Dom.getOffset(dropdownSelect),
            scrollTop = Dom.getScrollTop();

        if (top + this.triggerHeight + this.popupHeight - scrollTop > window.innerHeight) {
            return true;
        }

        return false;

    }

    filterChangeHandle(filter) {
        this.setState({
            filter
        });
    }

    togglePopup() {
        this.setState({
            popupVisible: !this.state.popupVisible
        }, () => {
            this.props.onTriggerTouchTap && this.props.onTriggerTouchTap(this.state.popupVisible);
        });
    }

    closePopup() {
        this.setState({
            popupVisible: false
        }, () => {
            this.props.onClosePopup && this.props.onClosePopup();
        });
    }

    filterData(filter = this.state.filter, data = this.props.data) {

        if (!filter) {
            return data;
        }

        const {displayField, isGrouped} = this.props,
            filterFunc = (originData) => {
                return originData.filter(item => typeof item === 'object' && !!item[displayField] ?
                    item[displayField].toString().toUpperCase().includes(filter.toUpperCase())
                    :
                    item.toString().toUpperCase().includes(filter.toUpperCase()));
            };

        if (isGrouped) {

            let result = Object.assign(data);

            for (let i = 0, len = result.length; i < len; i++) {
                let group = result[i];
                group.children = filterFunc(group.children);
                if (group.children.length < 1) {
                    result.splice(i, 1);
                    i--;
                }
            }

        }

        return filterFunc(data);

    }

    popupRenderHandle(popupEl) {

        this.popupEl = findDOMNode(popupEl);
        this.popupHeight = this.popupEl.offsetHeight;

        const isAbove = this.isAbove();

        if (isAbove !== this.state.isAbove) {
            this.setState({
                isAbove
            });
        }

    }

    changeHandler(value) {

        const {autoClose} = this.props,
            state = {
                value
            };

        if (autoClose) {
            state.popupVisible = false;
        }

        this.setState(state, () => {
            const {onChange} = this.props;
            onChange && onChange(value);
        });

    }

    componentDidMount() {
        this.triggerEl = findDOMNode(this.refs.trigger);
        this.triggerHeight = this.triggerEl.clientHeight;
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.props.value) {
            this.setState({
                value: nextProps.value
            });
        }
    }

    render() {

        const {
                className, popupClassName, style, popupStyle, theme, name, placeholder,
                disabled, mode, useFilter, valueField, displayField, descriptionField, noMatchedMsg,
                isGrouped, itemTouchTapHandle, disableTouchRipple
            } = this.props,
            {value, filter, popupVisible, isAbove} = this.state,

            emptyEl = [{
                itemRenderer() {
                    return (

                            {
                                noMatchedMsg ?
                                    noMatchedMsg
                                    :

                                        No matched value.

                            }

                    );
                }
            }],

            triggerClassName = (popupVisible ? ' activated' : '') + (isAbove ? ' above' : ' blow')
                + (value ? '' : ' empty'),
            triggerValue = value ?
                (
                    mode === List.Mode.CHECKBOX ?
                        (
                            value.length > 0 ?
                                value.length + ' selected'
                                :
                                placeholder
                        )
                        :
                        Util.getTextByDisplayField(value, displayField, valueField)
                )
                :
                placeholder,

            dropdownSelectPopupClassName = (isAbove ? ' above' : ' blow')
                + (popupClassName ? ' ' + popupClassName : ''),
            dropdownPopupStyle = Object.assign({
                width: this.triggerEl && getComputedStyle(this.triggerEl).width
            }, popupStyle),

            listData = this.filterData();

        return (

                {
                    name ?
                        <input type="hidden"
                               name={name}
                               value={Util.getValueByValueField(value, valueField, displayField)}/>
                        :
                        null
                }

                <RaisedButton ref="trigger"
                              className={'dropdown-select-trigger' + triggerClassName}
                              theme={theme}
                              value={triggerValue}
                              rightIconCls={`fa fa-angle-${isAbove ? 'up' : 'down'} dropdown-select-trigger-icon`}
                              disabled={disabled}
                              disableTouchRipple={disableTouchRipple}
                              onTouchTap={this.togglePopup}/>

                <Popup ref="popup"
                       className={'dropdown-select-popup' + dropdownSelectPopupClassName}
                       style={dropdownPopupStyle}
                       theme={theme}
                       visible={popupVisible}
                       triggerEl={this.triggerEl}
                       hasTriangle={false}
                       position={isAbove ? Popup.Position.TOP_LEFT : Popup.Position.BOTTOM_LEFT}
                       onRender={this.popupRenderHandle}
                       onRequestClose={this.closePopup}>

                    {
                        useFilter ?
                            <TextField className="dropdown-select-filter"
                                       value={filter}
                                       rightIconCls="fa fa-search"
                                       onChange={this.filterChangeHandle}/>
                            :
                            null
                    }

                    <List className="dropdown-select-list"
                          theme={theme}
                          mode={mode}
                          isGrouped={isGrouped}
                          items={listData.length < 1 ? emptyEl : listData}
                          value={value}
                          valueField={valueField}
                          displayField={displayField}
                          descriptionField={descriptionField}
                          onItemTouchTap={itemTouchTapHandle}
                          onChange={this.changeHandler}/>

                </Popup>

        );

    }
};

DropdownSelect.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The class name of the popup element.
     */
    popupClassName: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Override the styles of the popup element.
     */
    popupStyle: PropTypes.object,

    /**
     * The theme.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The name of the dropDownSelect.
     */
    name: PropTypes.string,

    /**
     * The value of the dropDownSelect.
     */
    value: PropTypes.any,

    /**
     * The placeholder of the dropDownSelect.
     */
    placeholder: PropTypes.string,

    /**
     * The options data.
     */
    data: PropTypes.oneOfType([

        // not grouped
        PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({

            /**
             * The CSS class name of the list button.
             */
            className: PropTypes.string,

            /**
             * Override the styles of the list button.
             */
            style: PropTypes.object,

            /**
             * The theme of the list button.
             */
            theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

            /**
             * The text value of the list button.Type can be string or number.
             */
            value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * The desc value of the list button. Type can be string or number.
             */
            desc: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * If true, the list button will be disabled.
             */
            disabled: PropTypes.bool,

            /**
             * If true,the button will be have loading effect.
             */
            isLoading: PropTypes.bool,

            /**
             * If true,the element's ripple effect will be disabled.
             */
            disableTouchRipple: PropTypes.bool,

            /**
             * Use this property to display an icon. It will display on the left.
             */
            iconCls: PropTypes.string,

            /**
             * Use this property to display an icon. It will display on the right.
             */
            rightIconCls: PropTypes.string,

            /**
             * You can create a complicated renderer callback instead of value and desc prop.
             */
            renderer: PropTypes.func,

            /**
             * Callback function fired when a list item touch-tapped.
             */
            onTouchTap: PropTypes.func

        }), PropTypes.string, PropTypes.number])),

        // grouped
        PropTypes.array

    ]).isRequired,

    /**
     * The invalid message of dropDownSelect.
     */
    invalidMsg: PropTypes.string,

    /**
     * If true,the dropDownSelect will be disabled.
     */
    disabled: PropTypes.bool,

    /**
     * The mode of listItem.Can be normal,checkbox.
     */
    mode: PropTypes.oneOf(Util.enumerateValue(List.Mode)),

    /**
     * The value field name in data. (default: "value")
     */
    valueField: PropTypes.string,

    /**
     * The display field name in data. (default: "text")
     */
    displayField: PropTypes.string,

    /**
     * The description field name in data. (default: "desc")
     */
    descriptionField: PropTypes.string,

    /**
     * The message of the dropDownSelect.
     */
    infoMsg: PropTypes.string,

    /**
     * Use this function to format the options's text.
     */
    textFormat: PropTypes.func,

    /**
     * If true,the drop-down box automatically closed after selection.
     */
    autoClose: PropTypes.bool,

    /**
     * If true,the drop-down box will have search input.
     */
    useFilter: PropTypes.bool,

    /**
     * The message of no matching option.
     */
    noMatchedMsg: PropTypes.string,

    /**
     * If true,the drop-down box will be have group selection.
     */
    isGrouped: PropTypes.bool,

    /**
     * Callback function fired when the button is touch-tapped.
     */
    onItemTouchTap: PropTypes.func,

    /**
     * Callback function fired when the popup is closed.
     */
    onClosePopup: PropTypes.func,

    /**
     * Callback function fired when a menu item is selected.
     */
    onChange: PropTypes.func

};

DropdownSelect.defaultProps = {

    className: '',
    popupClassName: '',
    style: null,
    popupStyle: null,
    theme: Theme.DEFAULT,

    name: '',
    value: null,
    placeholder: 'Please select ...',
    data: [],
    invalidMsg: '',
    disabled: false,
    mode: List.Mode.NORMAL,

    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',

    infoMsg: '',
    autoClose: true,
    useFilter: false,
    noMatchedMsg: '',
    isGrouped: false

};<|endoftext|>


<commit_before>
var url = require("url");

exports.name = "links.compound";
exports.check = function (sr, done) {
    var links = [];
    if ( typeof String.prototype.startsWith != 'function' ) {
        String.prototype.startsWith = function( str ) {
            return this.substring( 0, str.length ) === str;
        }
    };

    sr.$('a[href]').each(function () {
        var parsedLink = url.parse(url.resolve(sr.url, sr.$(this).attr("href"))),
        l = parsedLink.protocol + '//' + parsedLink.host + parsedLink.pathname;
        if (l.startsWith(sr.url) && l != sr.url) {
            links.push(l);
        }
    });
    // sort and remove duplicates
    links = links.sort().filter(function (item, pos) {return (!pos || item != links[pos - 1]);});
    links.forEach(function (l) {
        sr.info(exports.name, "links", { file : l.split('/').pop(), link : l } )
    });
};
<commit_msg>clean up<commit_after>
var url = require("url");

exports.name = "links.compound";
exports.check = function (sr, done) {
    var links = [];
    if ( typeof String.prototype.startsWith != 'function' ) {
        String.prototype.startsWith = function( str ) {
            return this.substring( 0, str.length ) === str;
        }
    };

    sr.$('a[href]').each(function () {
        var parsedLink = url.parse(url.resolve(sr.url, sr.$(this).attr("href"))),
            l = parsedLink.protocol + '//' + parsedLink.host + parsedLink.pathname;
        if (l.startsWith(sr.url) && l != sr.url) links.push(l);
    });
    // sort and remove duplicates
    links = links.sort().filter(function (item, pos) {return (!pos || item != links[pos - 1]);});
    links.forEach(function (l) {
        sr.info(exports.name, "links", { file : l.split('/').pop(), link : l })
    });
};
<|endoftext|>


<commit_before><commit_msg>Make delete basically click the cancel button (as expected)<commit_after><|endoftext|>


<commit_before>import ohm from "https://unpkg.com/ohm-js@15.2.1/dist/ohm.js";

export default class LeoUIExample{
  static async create () {

    var hello =
 lively.notify('hi')}>
        Hi

    var world =

        World

    let description =

    hello.addEventListener('dragstart', dragStart);
    hello.addEventListener('dragend', dragEnd);

    world.addEventListener('drop', drop);

    var g = ohm.grammar('Academic { \n  Exp = \n    AcademicQuery \n \n  AcademicQuery = Attribute Comparator Value -- simple \n    | ("And" | "Or") "(" AcademicQuery "," AcademicQuery ")" -- complex \n    | "Composite(" CompositeQuery ")" -- composite \n \n  CompositeQuery = CompositeAttribute Comparator Value -- simple \n    | ("And" | "Or") "(" CompositeQuery "," CompositeQuery ")" -- complex \n \n  Comparator = \n    PartialComparator "="? \n  PartialComparator = \n    "=" | "<" | ">" \n \n  Attribute (an attribute) = \n    letter letter? letter? \n  CompositeAttribute = \n    Attribute "." Attribute \n \n \n  Value (a value) = \n    "\'" alnum* "\'" -- string \n    | Number \n    | Date \n    | ( "[" | "(" ) Number "," Number ( "]" | ")" ) -- numberRange \n    | ( "[" | "(" ) Date "," Date ( "]" | ")" ) -- dateRange \n \n  Number = \n    digit+ \n  Date = \n    "\'" digit digit digit digit "-" digit digit "-" digit digit "\'" \n}');

    /*lively.notify(g.match("Composite(And(AA.AuN='mike smith',AA.AfN='harvard university'))").succeeded(), "Composite(And(AA.AuN='mike smith',AA.AfN='harvard university'))");
    lively.notify(g.match("And(AA.AuN='mike smith',AA.AfN='harvard university')").succeeded(), "And(AA.AuN='mike smith',AA.AfN='harvard university')");*/

    //var queryObject = {};

    var s = g.createSemantics();

    s.addOperation(
      'interpret', {
        Exp: function(e) {
          return e.interpret();
        },

        AcademicQuery_simple: function(attr, comp, val) {
          var attribute = attr.interpret();
          //var comparator = comp.interpret();
          //var value = val.interpret();
          return { [attribute]: {
            "comparator": "a",//comparator,
            "value": "b"//value,
          }}
        },
        AcademicQuery_complex: function(conj, x, left, y, right, z) {
          var conjunction = conj.interpret();

          return {conjunction: [
            left.interpret(),
            right.interpret()
          ]}
        },

        Attribute: function(a, b, c) {
          var array = [a.interpret(), b.interpret(), c.interpret()];
          return array.join('');
        },

        letter: function(a) {
          return a.sourceString;
        }
      }
    )

    var r = g.match("A = 'e'")
    var n = s(r)
    lively.notify("A = 'e'", n.interpret());

    function dragStart(event) {
      description.innerHTML = "dragging";
      event.dataTransfer.setData("element", event.target.id);
    }

    function dragEnd(event) {
      description.innerHTML = "";
    }

    function drop(event) {
      event.preventDefault();
      var data = event.dataTransfer.getData("element");
      console.log("Datatransfer Types" + event.dataTransfer.types);
      event.target.appendChild(lively.query(this, '#'+data))
    }

    return

            Title

            Author

            Year

            <input value='something'></input>

                  Name

                  <input value='name'></input>

                  Institution

                  <input value='inst'></input>

            <input value='2001'></input>

  }
}<commit_msg>improve semantics and kind of test a bit<commit_after>import ohm from "https://unpkg.com/ohm-js@15.2.1/dist/ohm.js";

const exampleQueries = [
  "Composite(AA.AuN='mike smith')",
  "Ti='indexing by latent seman'",
  "Ti=='indexing by latent semantic analysis'",
  "Composite(AA.AuN=='susan t dumais')",
  "Y=[2010, 2012)",
  "Y=[2010, 2012]",
  "Y<=2010",
  "Y>=2005",
  "Y<2010",
  "D>'2010-02-03'",
  "D=['2010-02-03','2010-02-05']",
  "D='2010-02-03'",
  "And(Y=1985, Ti='disordered electronic systems')",
  "Or(Ti='disordered electronic systems', Ti='fault tolerance principles and practice')",
  "And(Or(Y=1985,Y=2008), Ti='disordered electronic systems')",
  "Composite(And(AA.AuN='mike smith',AA.AfN='harvard university'))",
  "And(Composite(AA.AuN='mike smith'),Composite(AA.AfN='harvard university'))"
]

export default class LeoUIExample{
  static async create () {

    var hello =
 lively.notify('hi')}>
        Hi

    var world =

        World

    let description =

    hello.addEventListener('dragstart', dragStart);
    hello.addEventListener('dragend', dragEnd);

    world.addEventListener('drop', drop);

    var g = ohm.grammar('Academic { \n  Exp = \n    AcademicQuery \n \n  AcademicQuery = Attribute Comparator Value -- simple \n    | ("And" | "Or") "(" AcademicQuery "," AcademicQuery ")" -- complex \n    | "Composite(" CompositeQuery ")" -- composite \n \n  CompositeQuery = Attribute "." Attribute Comparator Value -- simple \n    | ("And" | "Or") "(" CompositeQuery "," CompositeQuery ")" -- complex \n \n  Comparator = \n    PartialComparator "="? \n  PartialComparator = \n    "=" | "<" | ">" \n \n  Attribute (an attribute) = \n    letter letter? letter? \n  \n Value (a value) = \n    "\'" alnum* "\'" -- string \n    | Number \n    | Date \n    | ( "[" | "(" ) Number "," Number ( "]" | ")" ) -- numberRange \n    | ( "[" | "(" ) Date "," Date ( "]" | ")" ) -- dateRange \n \n  Number = \n    digit+ \n  Date = \n    "\'" Number "-" Number "-" Number "\'" \n}');

    /*lively.notify(g.match("Composite(And(AA.AuN='mike smith',AA.AfN='harvard university'))").succeeded(), "Composite(And(AA.AuN='mike smith',AA.AfN='harvard university'))");
    lively.notify(g.match("And(AA.AuN='mike smith',AA.AfN='harvard university')").succeeded(), "And(AA.AuN='mike smith',AA.AfN='harvard university')");*/

    //var queryObject = {};

    var s = g.createSemantics();

    s.addOperation(
      'interpret', {
        Exp: function(e) {
          return e.interpret();
        },

        AcademicQuery_simple: function(attribute, comparator, value) {
          return { [attribute.interpret()]: {
            "comparator": comparator.interpret(),
            "value": value.interpret(),
          }}
        },
        AcademicQuery_complex: function(conjunction, _1, left, _2, right, _3) {
          return {[conjunction.sourceString]: [
            left.interpret(),
            right.interpret()
          ]}
        },
        AcademicQuery_composite: function(_1, query, _2) {
          return query.interpret();
        },

        CompositeQuery_simple: function(mainAttribute, _, secondaryAttribute, comparator, value) {
          return {[mainAttribute.interpret()]:
                  {[secondaryAttribute.interpret()]:
                    {
                      "comparator": comparator.interpret(),
                      "value": value.interpret(),
                    }
                  }
          }
        },
        CompositeQuery_complex: function(conjunction, _1, left, _2, right, _3) {
          return {[conjunction.sourceString]: [
            left.interpret(),
            right.interpret()
          ]}
        },

        Comparator: function(main, secondary) {
          return [main.interpret(), secondary.sourceString].join('');
        },
        PartialComparator: function(comparator) {
          return comparator.sourceString;
        },

        Attribute: function(a, b, c) {
          return [a.interpret(), b.interpret(), c.interpret()].join('');
        },

        Value: function(value) {
          return value.interpret();
        },
        Value_string: function(_1, string, _2) {
          return string.sourceString;
        },
        Value_numberRange: function(leftBracket, nLeft, _, nRight, rightBracket) {
          // TODO: refactor
          return "TODO";//arguments.map(a => {a.sourceString}).join('');
        },
        Value_dateRange: function(leftBracket, dLeft, _, dRight, rightBracket) {
          return "TODO";//arguments.map(a => {a.sourceString}).join('');
        },

        Number: function(n) {
          return parseFloat(n.sourceString);
        },
        Date: function(_1, year, _2, month, _3, day, _4) {
          return new Date(year.interpret(),
                          month.interpret(),
                          day.interpret())
        },

        letter: function(a) {
          return a.sourceString;
        }
      }
    )

    exampleQueries.forEach(q => {
      var m = g.match(q);
      if (m.failed()) {
        lively.notify("Failed query: ", q)
      } else {
        lively.notify(q, s(m).interpret());
      }
    })

    /*var r = g.match("A = 'e'")
    var n = s(r)
    lively.notify("A = 'e'", n.interpret());*/

    function dragStart(event) {
      description.innerHTML = "dragging";
      event.dataTransfer.setData("element", event.target.id);
    }

    function dragEnd(event) {
      description.innerHTML = "";
    }

    function drop(event) {
      event.preventDefault();
      var data = event.dataTransfer.getData("element");
      console.log("Datatransfer Types" + event.dataTransfer.types);
      event.target.appendChild(lively.query(this, '#'+data))
    }

    return

            Title

            Author

            Year

            <input value='something'></input>

                  Name

                  <input value='name'></input>

                  Institution

                  <input value='inst'></input>

            <input value='2001'></input>

  }
}<|endoftext|>


<commit_before>(function ($) {
    $.fn.jsAccordion = function (options) {
        var settings = $.extend({
            className: '',
            labelClass: 'accordion-label',
            openPanels: null,
            autoCollapse: true
        }, options);

        return this.each(function () {
            var $this = $(this),
                $li = $this.children('li'),
                setPanelWidth = function () {
                    $li.children('ul, div').each(function () {
                        // we use this complex width detection because jQuery's $(el).width() function
                        // isn't reliable for hidden elements. This method always gets an accurate width
                        var $panel = $(this),
                            padding = parseInt($panel.css('paddingLeft'), 10) + parseInt($panel.css('paddingRight'), 10),
                            border = parseInt($panel.css('borderLeft'), 10) + parseInt($panel.css('borderRight'), 10),
                            margin = parseInt($panel.css('marginLeft'), 10) + parseInt($panel.css('marginRight'), 10),
                            w = $panel.parent().width() - (padding + border + margin);

                        $panel.width(w);
                    });
                },
                showPanels = function (panels) {
                    if (panels) {
                        panels.show().parent().addClass('expanded');
                        $(document).trigger('panelExpanded');
                    }
                };

            // add the style class to each accordion
            $this.addClass(settings.className);

            // hide all of the accordion's panels
            $li.children('ul, div').hide();
            $(document).trigger('panelCollapsed');

            // expand the panels that should be open when the page loads
            showPanels(settings.openPanels);

            // make animations smoother by defining a width
            setPanelWidth();

            // recalculate width when panels are toggled or the window is resized
            $(document).bind('panelCollapsed', setPanelWidth);
            $(document).bind('panelExpanded', setPanelWidth);
            $(window).resize(setPanelWidth);

            // find all non-empty, top-level text nodes and wrap them with span tags
            $li.contents().filter(function () {
                return this.nodeType === 3 && $.trim(this.nodeValue) !== '';
            }).wrap('<span />');

            $li.children('a, span').each(function () {
                var $label = $(this);

                // if the `a` or `span` is a link instead of a label, return
                if ($label.next('ul, div').length < 1) {
                    return;
                }

                // each label that expands an accordion panel should be given a special class
                $label.addClass(settings.labelClass);

                // if those labels are links, prevent the links from doing anything
                if ($label.is('a')) {
                    $label.click(function (e) {
                        e.preventDefault();
                    });
                }

                // toggle the expanded/collapsed panel on click
                $label.click(function () {
                    // collapse the panel if it is currently visible
                    if ($label.next('ul, div').is(':visible')) {
                        $label.next('ul, div').slideUp(function () {
                            $(document).trigger('panelCollapsed');
                        });
                        $label.parent().removeClass('expanded');
                    } else {
                        // if autoCollapse is on, collapse all other panels
                        if (settings.autoCollapse) {
                            $li.filter('.expanded').removeClass('expanded')
                                .children('ul:visible, div:visible').slideUp();
                        }
                        $label.next('ul, div').slideDown(function () {
                            $(document).trigger('panelExpanded');
                        });
                        $label.parent().addClass('expanded');
                    }
                });

            });
        });
    };
}(jQuery));<commit_msg>Change property name for accordion class<commit_after>(function ($) {
    $.fn.jsAccordion = function (options) {
        var settings = $.extend({
            accordionClass: '',
            labelClass: 'accordion-label',
            openPanels: null,
            autoCollapse: true
        }, options);

        return this.each(function () {
            var $this = $(this),
                $li = $this.children('li'),
                setPanelWidth = function () {
                    $li.children('ul, div').each(function () {
                        // we use this complex width detection because jQuery's $(el).width() function
                        // isn't reliable for hidden elements. This method always gets an accurate width
                        var $panel = $(this),
                            padding = parseInt($panel.css('paddingLeft'), 10) + parseInt($panel.css('paddingRight'), 10),
                            border = parseInt($panel.css('borderLeft'), 10) + parseInt($panel.css('borderRight'), 10),
                            margin = parseInt($panel.css('marginLeft'), 10) + parseInt($panel.css('marginRight'), 10),
                            w = $panel.parent().width() - (padding + border + margin);

                        $panel.width(w);
                    });
                },
                showPanels = function (panels) {
                    if (panels) {
                        panels.show().parent().addClass('expanded');
                        $(document).trigger('panelExpanded');
                    }
                };

            // add the style class to each accordion
            $this.addClass(settings.accordionClass);

            // hide all of the accordion's panels
            $li.children('ul, div').hide();
            $(document).trigger('panelCollapsed');

            // expand the panels that should be open when the page loads
            showPanels(settings.openPanels);

            // make animations smoother by defining a width
            setPanelWidth();

            // recalculate width when panels are toggled or the window is resized
            $(document).bind('panelCollapsed', setPanelWidth);
            $(document).bind('panelExpanded', setPanelWidth);
            $(window).resize(setPanelWidth);

            // find all non-empty, top-level text nodes and wrap them with span tags
            $li.contents().filter(function () {
                return this.nodeType === 3 && $.trim(this.nodeValue) !== '';
            }).wrap('<span />');

            $li.children('a, span').each(function () {
                var $label = $(this);

                // if the `a` or `span` is a link instead of a label, return
                if ($label.next('ul, div').length < 1) {
                    return;
                }

                // each label that expands an accordion panel should be given a special class
                $label.addClass(settings.labelClass);

                // if those labels are links, prevent the links from doing anything
                if ($label.is('a')) {
                    $label.click(function (e) {
                        e.preventDefault();
                    });
                }

                // toggle the expanded/collapsed panel on click
                $label.click(function () {
                    // collapse the panel if it is currently visible
                    if ($label.next('ul, div').is(':visible')) {
                        $label.next('ul, div').slideUp(function () {
                            $(document).trigger('panelCollapsed');
                        });
                        $label.parent().removeClass('expanded');
                    } else {
                        // if autoCollapse is on, collapse all other panels
                        if (settings.autoCollapse) {
                            $li.filter('.expanded').removeClass('expanded')
                                .children('ul:visible, div:visible').slideUp();
                        }
                        $label.next('ul, div').slideDown(function () {
                            $(document).trigger('panelExpanded');
                        });
                        $label.parent().addClass('expanded');
                    }
                });

            });
        });
    };
}(jQuery));<|endoftext|>


<commit_before>var visiblePanels = null; // each page can set this to control which sections are open by default (see html documentation)

function Accordion() {
    this.initialize = function() {
        // add the style class to each accordion
        $('.jsAccordion').addClass('secondary-nav');
        // hide all sub-links
        $('.jsAccordion > ul > li').children('ul, div').each(function () {
            var padding = parseInt($(this).css('paddingLeft'), 10) + parseInt($(this).css('paddingRight'), 10),
                border = parseInt($(this).css('borderLeft'), 10) + parseInt($(this).css('borderRight'), 10),
                margin = parseInt($(this).css('marginLeft'), 10) + parseInt($(this).css('marginRight'), 10),
                w = $(this).parent().width() - (padding + border + margin);

            $(this).hide().css({width: w});
        });

        // find all non-empty, top-level text nodes and wrap them with span tags
        $('.jsAccordion > ul > li').contents().filter(function() {
            return this.nodeType === 3 && $.trim(this.nodeValue) !== '';
        }).wrap('');

        // if an anchor precedes a hidden section, don't treat it as a link
        $('.jsAccordion > ul > li > a').each(function() {
            if ($(this).next('ul, div').length > 0) {
                $(this).click(function(e) {
                    e.preventDefault();
                });
            }
        });

        $('.jsAccordion > ul > li > a, .jsAccordion > ul > li > span').click(function() {
            if ($(this).next('ul, div').is(':visible')) {
                // if you're closing a panel, don't hide all other panels
                // (this lets you close one panel without closing all panels if multiple are open)
                $(this).next('ul, div').slideUp();
                $(this).parent().removeClass('expanded');
            }
            else {
                // if you're opening a panel, it's safe to hide other panels in the same accordion
                $(this).parents('.jsAccordion').find('.expanded').removeClass('expanded')
                    .children('ul:visible, div:visible').slideUp();
                $(this).next('ul, div').slideDown();
                $(this).parent().addClass('expanded');
            }
        });
    };
    // determine which panels should be shown when the page loads
    this.showPanels = function(openPanels) {
        var i = 0;
        if (openPanels !== null) {
            if (openPanels === '-all') {
                $('.jsAccordion ul ul, .jsAccordion ul div').show();
                $('.jsAccordion ul>li').addClass('expanded');
            }
            else if (typeof openPanels === 'string') {
                // if there's a hash in front of the id, remove it
                if (openPanels.substr(0, 1) === '#') {
                    openPanels = openPanels.substr(1, openPanels.length);
                }
                $('.jsAccordion ul #' + openPanels).show().parent().addClass('expanded');
            }
            else if (typeof openPanels === 'number') {
                $('.jsAccordion ul ul, .jsAccordion ul div').eq(openPanels).show().parent().addClass('expanded');
            }
            // if openPanels contains an array of items, loop through it and handle each one individually
            else if (openPanels.constructor === Array) {
                for (i = 0; i < openPanels.length; i++) {
                    this.showPanels(openPanels[i]);
                }
            }
        }
    };
}
$(document).ready(function() {
    var accordion = new Accordion();
    accordion.initialize();
    accordion.showPanels(visiblePanels);
});
<commit_msg>Convert project to a jQuery plugin (Fixes #3)<commit_after>(function ($) {
    $.fn.jsAccordion = function () {
        var settings = {
            'className' : 'secondary-nav',
            'openPanels' : visiblePanels
        };

        return this.each(function () {
            var $this = $(this),
                $li = $this.children('ul').children('li'),
                showPanels;

            // add the style class to each accordion
            $this.addClass(settings.className);

            // hide all of the accordion's panels
            $li.children('ul, div').each(function () {
                // animation is smoother if the panel's width is set
                // we calculate it automatically based on the parent's width
                var $panel = $(this),
                    padding = parseInt($panel.css('paddingLeft'), 10) + parseInt($panel.css('paddingRight'), 10),
                    border = parseInt($panel.css('borderLeft'), 10) + parseInt($panel.css('borderRight'), 10),
                    margin = parseInt($panel.css('marginLeft'), 10) + parseInt($panel.css('marginRight'), 10),
                    w = $panel.parent().width() - (padding + border + margin);

                $panel.hide().css({width: w});
            });

            // find all non-empty, top-level text nodes and wrap them with span tags
            $li.contents().filter(function () {
                return this.nodeType === 3 && $.trim(this.nodeValue) !== '';
            }).wrap('');

            // if an anchor precedes a hidden section, don't treat it as a link
            $li.children('a').each(function () {
                var $a = $(this);

                if ($a.next('ul, div').length > 0) {
                    $a.click(function (e) {
                        e.preventDefault();
                    });
                }
            });

            $li.children('a, span').click(function () {
                var $label = $(this);

                if ($label.next('ul, div').is(':visible')) {
                    // if the corresponding panel is visible, collapse it
                    $label.next('ul, div').slideUp();
                    $label.parent().removeClass('expanded');
                } else {
                    // otherwise, if a panel is being opened, collapse all others
                    $label.parents('.jsAccordion').find('.expanded').removeClass('expanded')
                        .children('ul:visible, div:visible').slideUp();
                    $label.next('ul, div').slideDown();
                    $label.parent().addClass('expanded');
                }
            });

            // determine which panels should be shown when the page loads
            showPanels = function (panels) {
                var i;

                if (panels !== null) {
                    if (panels === '-all') {
                        $li.children('ul, div').show();
                        $li.addClass('expanded');
                    } else if (typeof panels === 'string') {
                        // assume we're working with an id; remove hash if present
                        if (panels.substr(0, 1) === '#') {
                            panels = panels.substr(1, panels.length);
                        }
                        $this.find(panels).show().parent().addClass('expanded');
                    } else if (typeof panels === 'number') {
                        $li.children('ul, div').eq(panels).show().parent().addClass('expanded');
                    } else if (panels.constructor === Array) {
                        // loop through the array and handle each item individually
                        for (i = 0; i < panels.length; i += 1) {
                            showPanels(panels[i]);
                        }
                    }
                }
            };
            showPanels(settings.openPanels);
        });
    };
}(jQuery));<|endoftext|>


<commit_before>const glob = require('glob');
const fs = require('fs');
const path = require('path');
const marked = require('marked');
const renderer = new marked.Renderer();
const camelCase = require('camel-case');
const titleCase = require('title-case');
const shell = require('shelljs');
const getFileNameFromPath = require('@lukeboyle/get-filename-from-path');

renderer.code = function(code, language) {
	console.log(code.split('\n'));
	return `

		${code.split('\n').map(codeBlock => {
			console.log(codeBlock);
		const codeWithEscapedQuotes = codeBlock.split('"').join('\\"');
		const codeWithEscapedHashes = codeWithEscapedQuotes.split('#').join('\\#');
		const codeWithEscapedCurlies = codeWithEscapedHashes.split('{').join('\\{').split('}').join('\\}');
		return `<span>{"${codeWithEscapedCurlies}"}</span>`;
	}).join('')}

`;
};

renderer.image = function(href, title, text) {
	return `<img src="${href}" alt="${text}"/>`;
};

function getMarkupFromMarkdown(markdownString) {
	return `<div>${marked(markdownString, {renderer: renderer, gfm: true})}</div>`;
}

function generateComponent(post) {
	const fileName = getFileNameFromPath(post.path);

	return {
		path: post.path,
		fileName,
		component: `
			import React from 'react';
			import Helmet from 'react-helmet';

			export default class ${camelCase(fileName)} extends React.Component {
				render() {
					return (

							<Helmet>
								<title>${titleCase(fileName)} | Luke Boyle</title>
							</Helmet>
							${getMarkupFromMarkdown(post.contents)}

					);
				}
			}
		`
	};
}

(() => {
	glob('blog-posts/**/*.md', {}, (err, files) => {
		const blogPosts = files.reduce((acc, curr) => {
			acc.push({
				path: curr,
				contents: fs.readFileSync(curr, {encoding: 'utf-8'})
			});

			return acc;
		}, []);

		const components = blogPosts.map(generateComponent);

		shell.rm('-rf', path.resolve(`${__dirname}/../src/pages/blog-posts`));

		components.forEach(component => {
			shell.mkdir('-p', path.resolve(`${__dirname}/../src/pages/${component.path.replace(`/${component.fileName}.md`, '')}`));
			fs.writeFileSync(path.resolve(`${__dirname}/../src/pages/${component.path.replace('.md', '.jsx')}`), component.component);
		});

		glob('./src/blog-posts/**/*.jsx', {}, (err, files) => {
			console.error(err);

			const pageCount = Math.ceil(files.length / 5);
		});
	});
})();<commit_msg>chore: add markup and classes to parsing<commit_after>const glob = require('glob');
const fs = require('fs');
const path = require('path');
const marked = require('marked');
const renderer = new marked.Renderer();
const camelCase = require('camel-case');
const titleCase = require('title-case');
const shell = require('shelljs');
const getFileNameFromPath = require('@lukeboyle/get-filename-from-path');

renderer.heading = function(code, level) {
	if (level === 1) {
		return `

${code}

		`;
	} else {
		return `<h${level}>${code}</h${level}>`;
	}
};

renderer.code = function(code, language) {
	return `

		${code.split('\n').map(codeBlock => {
		const codeWithEscapedQuotes = codeBlock.split('"').join('\\"');
		const codeWithEscapedHashes = codeWithEscapedQuotes.split('#').join('\\#');
		return `<span>{"${codeWithEscapedHashes}"}</span>`;
	}).join('')}

`;
};

renderer.image = function(href, title, text) {
	return `<img src="${href}" alt="${text}"/>`;
};

function getMarkupFromMarkdown(markdownString) {
	return `<article className="blog-post">${marked(markdownString, {renderer: renderer, gfm: true})}</article>`;
}

function generateComponent(post) {
	const fileName = getFileNameFromPath(post.path);

	return {
		path: post.path,
		fileName,
		component: `
			import React from 'react';
			import Helmet from 'react-helmet';

			export default class ${camelCase(fileName)} extends React.Component {
				render() {
					return (

							<Helmet>
								<title>${titleCase(fileName)} | Luke Boyle</title>
							</Helmet>
							${getMarkupFromMarkdown(post.contents)}

					);
				}
			}
		`
	};
}

(() => {
	glob('blog-posts/**/*.md', {}, (err, files) => {
		const blogPosts = files.reduce((acc, curr) => {
			acc.push({
				path: curr,
				contents: fs.readFileSync(curr, {encoding: 'utf-8'})
			});

			return acc;
		}, []);

		const components = blogPosts.map(generateComponent);

		shell.rm('-rf', path.resolve(`${__dirname}/../src/pages/blog-posts`));

		components.forEach(component => {
			shell.mkdir('-p', path.resolve(`${__dirname}/../src/pages/${component.path.replace(`/${component.fileName}.md`, '')}`));
			fs.writeFileSync(path.resolve(`${__dirname}/../src/pages/${component.path.replace('.md', '.jsx')}`), component.component);
		});

		glob('./src/blog-posts/**/*.jsx', {}, (err, files) => {
			console.error(err);

			const pageCount = Math.ceil(files.length / 5);
		});
	});
})();<|endoftext|>


<commit_before>require("shelljs/global");

var path = require("path");
var fs   = require("fs");

// uninstall global babel install
try {
  exec("npm uninstall -g babel");
} catch (err) {}

// get packages
var packages = [];

// order important so they are linkable to each other
var packageNames = ['flint.js', 'runner', 'cli'];

packageNames.forEach(function (loc) {
  var name = path.basename(loc);
  if (name[0] === ".") return;

  var pkgLoc = __dirname + "/../packages/" + name + "/package.json";
  if (!fs.existsSync(pkgLoc)) return;

  var pkg = require(pkgLoc);
  packages.push({
    folder: name,
    pkg: pkg,
    name: pkg.name,
    global: pkg.global,
    links: Object.keys(pkg.dependencies)
      .filter(function(package) {
        return package.indexOf('flint-') === 0
      })
  });
});

// link in apps first
['tools'].forEach(function(app) {
  cd("apps/" + app + "/.flint")
  exec("npm install")
  exec("npm link")
  cd("../..")
})

// create links
packages.forEach(function (pkg) {
  console.log(pkg.name);

  var nodeModulesLoc = "packages/" + pkg.folder + "/node_modules";
  mkdir("-p", nodeModulesLoc);

  packages.forEach(function (sub) {
    if (!pkg.pkg.dependencies || !pkg.pkg.dependencies[sub.name]) return;

    if (!fs.existsSync(nodeModulesLoc + "/" + sub.name)) {
      console.log("Linking", "packages/" + sub.folder, "to", nodeModulesLoc + "/" + sub.name);
      ln("-s", "packages/" + sub.folder, nodeModulesLoc + "/" + sub.name);
    }
  });

  cd("packages/" + pkg.folder);
  exec("npm install");
  exec("npm link");

  pkg.links.forEach(function(link) {
    console.log('LINKING IN ', link)
    exec("npm link " + link)
  })

  cd("../..");
});

exec("make build");
<commit_msg>add setup for vendors<commit_after>require("shelljs/global");

var path = require("path");
var fs   = require("fs");

// setup flint-babel
cd('vendor/babel');
exec('make bootstrap')
cd('../..')

// setup flint-react-tools
cd('vendor/react-tools')
exec('npm install')
exec('npm link')
cd('../..')

// get packages
var packages = [];

// order important so they are linkable to each other
var packageNames = ['flint.js', 'runner', 'cli'];

packageNames.forEach(function (loc) {
  var name = path.basename(loc);
  if (name[0] === ".") return;

  var pkgLoc = __dirname + "/../packages/" + name + "/package.json";
  if (!fs.existsSync(pkgLoc)) return;

  var pkg = require(pkgLoc);
  packages.push({
    folder: name,
    pkg: pkg,
    name: pkg.name,
    global: pkg.global,
    links: Object.keys(pkg.dependencies)
      .filter(function(package) {
        return package.indexOf('flint-') === 0
      })
  });
});

// link in apps first
['tools'].forEach(function(app) {
  cd("apps/" + app + "/.flint")
  exec("npm install")
  exec("npm link")
  cd("../..")
})

// create links
packages.forEach(function (pkg) {
  console.log(pkg.name);

  var nodeModulesLoc = "packages/" + pkg.folder + "/node_modules";
  mkdir("-p", nodeModulesLoc);

  packages.forEach(function (sub) {
    if (!pkg.pkg.dependencies || !pkg.pkg.dependencies[sub.name]) return;

    if (!fs.existsSync(nodeModulesLoc + "/" + sub.name)) {
      console.log("Linking", "packages/" + sub.folder, "to", nodeModulesLoc + "/" + sub.name);
      ln("-s", "packages/" + sub.folder, nodeModulesLoc + "/" + sub.name);
    }
  });

  cd("packages/" + pkg.folder);
  exec("npm install");
  exec("npm link");

  pkg.links.forEach(function(link) {
    console.log('LINKING IN ', link)
    exec("npm link " + link)
  })

  cd("../..");
});

exec("make build");
<|endoftext|>


<commit_before>import { fetchQueries } from '../util/fetchUtils';

/**
 * PostEpic provides a generic interface for triggering POST requests and
 * dispatching particular actions with the API response. The POST action must
 * follow this structure:
 *
 * ```
 * {
 *   type: 'POST',
 *   onSuccess: a callback that takes the API response as an argument, and
 *     returns an action object. The middleware takes care of dispatch
 *   onError: a callback that takes an Error argument and returns an action
 *     object
 * }
 * ```
 *
 * This structure usually allows the success/error handling code to be bundled
 * alongside the POST action creator, with the expectation that all response
 * processing can be done there
 *
 * @module PostEpic
 */

/**
 * get a function that receives a post action and returns the corresponding
 * fetch Promise
 *
 * The wrapping function needs a store so that the returned function can
 * read from state
 *
 * @param {Redux Store} store
 * @param {Object} postAction, providing query, onSuccess, and onError
 * @return {Promise} results of the fetch, either onSuccess or onError
 */
const getPostActionFetch = ({ getState }) =>
	({ type, payload: { query, onSuccess, onError }}) => {
		const {
			config,
			auth,
		} = getState();

		return fetchQueries(config.apiUrl, { method: 'POST', auth })([query])
			.then(onSuccess)
			.catch(onError);
	};

const PostEpic = (action$, store) =>
	action$.filter(({ type })=> type.endsWith('_POST') || type.startsWith('POST_'))
		.flatMap(getPostActionFetch(store));

export default PostEpic;
<commit_msg>Update post.js<commit_after>import { fetchQueries } from '../util/fetchUtils';

/**
 * PostEpic provides a generic interface for triggering POST requests and
 * dispatching particular actions with the API response. The POST action must
 * follow this structure:
 *
 * ```
 * {
 *   type: 'POST_<SOMETHING>' (or 'SOMETHING_POST'),
 *   payload: {
 *     query: a 'reactive query' object that maps to an API call,
 *     onSuccess: a callback that takes the API response as an argument, and
 *       returns an action object. The middleware takes care of dispatch
 *     onError: a callback that takes an Error argument and returns an action
 *       object
 *   }
 * }
 * ```
 *
 * This structure usually allows the success/error handling code to be bundled
 * alongside the POST action creator, with the expectation that all response
 * processing can be done there
 *
 * @module PostEpic
 */

/**
 * get a function that receives a post action and returns the corresponding
 * fetch Promise
 *
 * The wrapping function needs a store so that the returned function can
 * read from state
 *
 * @param {Redux Store} store
 * @param {Object} postAction, providing query, onSuccess, and onError
 * @return {Promise} results of the fetch, either onSuccess or onError
 */
const getPostActionFetch = ({ getState }) =>
	({ type, payload: { query, onSuccess, onError }}) => {
		const {
			config,
			auth,
		} = getState();

		return fetchQueries(config.apiUrl, { method: 'POST', auth })([query])
			.then(onSuccess)
			.catch(onError);
	};

const PostEpic = (action$, store) =>
	action$.filter(({ type })=> type.endsWith('_POST') || type.startsWith('POST_'))
		.flatMap(getPostActionFetch(store));

export default PostEpic;
<|endoftext|>