<commit_before>#!/bin/env node

'use strict';

const chokidar = require('chokidar');
const co = require('co');
const fs = require('fs-extra');
const fsp = require('thenify-all')(fs);
const path = require('path');
const program = require('commander');

const debug = require('../lib/util/debug')('bin:import');
const die = require('../lib/util/die');
const home = require('../lib/config/home');
const imp = require('../lib/import/import');

var processChain = Promise.resolve();
const importFiles = {};
const createdDirs = {};

program
    .usage('<file>')
    .option('-l, --limit <number>', 'Limit of files to import', Number)
    .option('-w, --watch', 'Watch files')
    .option('--continuous', 'Continuous mode. When import is finished, wait for some time and then import again')
    .option('--wait <time>', 'Wait time in seconds between imports for continuous mode (default: 60)', Number, 60)
    .option('-c --config <path>', 'Path to custom config file')
    .parse(process.argv);

function doContinuous(waitTime) {
    importAll().then(
        () => {
            debug('now waiting');
            setTimeout(() => doContinuous(waitTime), waitTime);
        },
        err => die(err.message || err)
    );
}

const importAll = co.wrap(function*() {
    const homeDir = getHomeDir();
    const files = yield findFiles(homeDir);
    const limit = program.limit || files.length;
    debug(`${files.length} files and limit is ${limit}`);
    const min = Math.min(limit, files.length);
    for (var i = 0; i < min; i++) {
        var file = files[i];
        yield processFile2(file.database, file.importName, file.path);
    }
});

const findFiles = co.wrap(function* (homeDir) {
    let files = [];

    const databases = yield fsp.readdir(homeDir);
    for (const database of databases) {
        if (shouldIgnore(database)) continue;
        const databasePath = path.join(homeDir, database);
        const stat = yield fsp.stat(databasePath);
        if (!stat.isDirectory()) continue;

        const importNames = yield fsp.readdir(databasePath);
        for (const importName of importNames) {
            if (shouldIgnore(importName)) continue;
            const importNamePath = path.join(databasePath, importName);
            const stat = yield fsp.stat(importNamePath);
            if (!stat.isDirectory()) continue;

            try {
                const importConfigPath = path.join(importNamePath, 'import');
                const importConfig = require(importConfigPath);
                if (importConfig && Array.isArray(importConfig.source)) {
                    for (const source of importConfig.source) {
                        try {
                            const sourcePath = path.resolve(importNamePath, source);
                            const sourceToProcessPath = path.join(sourcePath, 'to_process');
                            const stat = yield fsp.stat(sourceToProcessPath);
                            if (stat.isDirectory()) {
                                const fileList = yield getFilesToProcess(sourceToProcessPath);
                                const objFiles = fileList.map(file => ({database, importName, path: file}));
                                files = files.concat(objFiles);
                            }
                        } catch (e) {
                            // ignore
                        }
                    }
                }
            } catch (e) {
                // ignore
            }

            try {
                const toProcessPath = path.join(importNamePath, 'to_process');
                const stat = yield fsp.stat(toProcessPath);
                if (stat.isDirectory()) {
                    const fileList = yield getFilesToProcess(toProcessPath);
                    const objFiles = fileList.map(file => ({database, importName, path: file}));
                    files = files.concat(objFiles);
                }
            } catch (e) {
                // ignore
            }
        }
    }

    return files;
});

function getFilesToProcess(directory) {
    return new Promise((resolve, reject) => {
        const items = [];
        var readStream = fs.walk(directory);
        readStream
            .on('data', function (item) {
                if (item.stats.isFile()) {
                    items.push(item.path);
                }
            })
            .on('end', function () {
                resolve(items);
            })
            .on('error', function (error) {
                reject(error);
            });
    });
}

function getHomeDir() {
    let homeDir = home.homeDir;
    if (!homeDir) {
        die('homeDir must be set to import all');
    }
    return homeDir;
}

function checkFile(homeDir, p) {
    p = path.resolve(homeDir, p);
    const relpath = path.relative(homeDir, p);
    const elements = relpath.split('/');
    if (elements.length < 4) return false;
    if (elements[2] !== 'to_process') return false;
    if (hasImportFile(path.resolve(homeDir, elements[0] + '/' + elements[1]))) {
        return {
            database: elements[0],
            importName: elements[1]
        };
    }
}

function processFile(database, importName, homeDir, p) {
    debug.trace(`process file ${p}`);
    p = path.resolve(homeDir, p);
    let parsedPath = path.parse(p);

    processChain = processChain.then(() => {
        return imp.import(database, importName, p);
    }).then(() => {
        // mv to processed
        return new Promise(function (resolve, reject) {
            let dir = path.join(parsedPath.dir, '../processed/' + getDatePath());
            createDir(dir);
            tryRename(p, path.join(dir, parsedPath.base), resolve, reject);
        });
    }).catch(e => {
        // mv to errored
        return new Promise(function (resolve, reject) {
            if (e.message.startsWith('no import config')) {
                debug.warn('no import configuration found, skipping this file');
                return resolve();
            }
            debug.error(e + '\n' + e.stack);
            let dir = path.join(parsedPath.dir, '../errored/' + getDatePath());
            createDir(dir);
            tryRename(p, path.join(dir, parsedPath.base), resolve, reject);
        });
    });

    return processChain;
}

function* processFile2(database, importName, filePath) {
    debug.trace(`process file ${filePath}`);
    const parsedPath = path.parse(filePath);
    const splitParsedPath = parsedPath.dir.split('/');
    const toProcess = splitParsedPath.indexOf('to_process');
    if (toProcess === -1) {
        throw new Error('to_process not found in path. This should not happen');
    }

    try {
        yield imp.import(database, importName, filePath);
        // success, move to processed
        yield moveFile(filePath, parsedPath.base, splitParsedPath, toProcess, 'processed');
    } catch (e) {
        // error, move to errored
        if (e.message.startsWith('no import config')) {
            debug.warn('no import configuration found, skipping this file');
            return;
        }
        debug.error(e + '\n' + e.stack);
        yield moveFile(filePath, parsedPath.base, splitParsedPath, toProcess, 'errored');
    }
}

function* moveFile(filePath, fileName, splitParsedPath, toProcess, dest) {
    const base = splitParsedPath.slice(0, toProcess).join('/');
    let subdir;
    if (splitParsedPath.length - toProcess > 1) {
        subdir = splitParsedPath.slice(toProcess + 1).join('/');
    } else {
        subdir = getDatePath();
    }
    const destination = path.join(base, dest, subdir, fileName);
    yield tryMove(filePath, destination);
}

function* tryMove(from, to, suffix) {
    if (suffix > 1000) {
        throw new Error('tryMove: too many retries');
    }
    if (!suffix) {
        suffix = 0;
    }
    var newTo = to;
    if (suffix > 0) {
        newTo += '.' + suffix;
    }
    try {
        yield fsp.move(from, newTo);
    } catch (e) {
        if (e.code !== 'EEXIST') {
            throw new Error(`Could could rename ${from} to ${newTo}: ${e}`);
        }
        yield tryMove(from, to, ++suffix);
    }
}

function tryRename(from, to, resolve, reject, suffix) {
    if (!suffix) {
        suffix = 0;
    }
    var newTo = to;
    if (suffix > 0) {
        newTo += '.' + suffix;
    }
    fs.access(newTo, function (err) {
        if (err) {
            if (err.code !== 'ENOENT') {
                debug.error(`Could could rename ${from} to ${newTo}: ${err}`);
                return reject(err);
            } else {
                return fs.rename(from, newTo, function (err) {
                    if (err) return reject(err);
                    resolve();
                });
            }
        }
        // file exists. retry with another name
        return tryRename(from, to, resolve, reject, ++suffix);
    });
}

function hasImportFile(p) {
    if (importFiles[p]) return true;
    const importFile = path.join(p, 'import.js');
    try {
        fs.accessSync(importFile);
        importFiles[p] = true;
        return true;
    } catch (e) {
        return false;
    }
}

function createDir(dir) {
    if (createdDirs[dir]) return;

    fs.mkdirpSync(dir);
    createdDirs[dir] = true;
}

function getDatePath() {
    var now = new Date();
    return now.getUTCFullYear() + '/' + ('0' + (now.getUTCMonth() + 1)).slice(-2) + '/' + ('0' + now.getUTCDate()).slice(-2);
}

function shouldIgnore(name) {
    return name === 'node_modules' ||
        name.startsWith('.');
}

if (program.args[0]) {
    debug(`file argument: ${program.args[0]}`);
    // TODO add 2 arguments: db and import names
    throw new Error('not ready');
    //const file = path.resolve(program.args[0]);
    //imp.import(config, file);
} else if (program.watch) {
    // watch files to import
    let homeDir = getHomeDir();
    debug(`watch ${homeDir}`);
    chokidar.watch(homeDir, {
        ignored: /[\/\\](\.|processed|errored|node_modules)/,
        persistent: true
    }).on('all', function (event, p) {
        debug.trace(`watch event: ${event} - ${p}`);
        let file = checkFile(homeDir, p);
        if (event !== 'add' && event !== 'change' || !file) {
            return;
        }
        processFile(file.database, file.importName, homeDir, p);
    });
} else if (program.continuous) {
    const waitTime = program.wait * 1000;
    debug(`continuous import. Wait time is ${program.wait}`);
    doContinuous(waitTime);
} else {
    debug('no watch');
    importAll().then(function () {
        debug('finished');
    }, function (err) {
        die(err.message || err);
    });
}
<commit_msg>WIP: skip import 2<commit_after>#!/bin/env node

'use strict';

const chokidar = require('chokidar');
const co = require('co');
const fs = require('fs-extra');
const fsp = require('thenify-all')(fs);
const path = require('path');
const program = require('commander');

const debug = require('../lib/util/debug')('bin:import');
const die = require('../lib/util/die');
const home = require('../lib/config/home');
const imp = require('../lib/import/import');

var processChain = Promise.resolve();
const importFiles = {};
const createdDirs = {};

program
    .usage('<file>')
    .option('-l, --limit <number>', 'Limit of files to import', Number)
    .option('-w, --watch', 'Watch files')
    .option('--continuous', 'Continuous mode. When import is finished, wait for some time and then import again')
    .option('--wait <time>', 'Wait time in seconds between imports for continuous mode (default: 60)', Number, 60)
    .option('-c --config <path>', 'Path to custom config file')
    .parse(process.argv);

function doContinuous(waitTime) {
    importAll().then(
        () => {
            debug('now waiting');
            setTimeout(() => doContinuous(waitTime), waitTime);
        },
        err => die(err.message || err)
    );
}

const importAll = co.wrap(function*() {
    const homeDir = getHomeDir();
    const files = yield findFiles(homeDir);
    const limit = program.limit || files.length;
    debug(`${files.length} files and limit is ${limit}`);
    const min = Math.min(limit, files.length);
    for (var i = 0; i < min; i++) {
        var file = files[i];
        yield processFile2(file.database, file.importName, file.path);
    }
});

const findFiles = co.wrap(function* (homeDir) {
    let files = [];

    const databases = yield fsp.readdir(homeDir);
    for (const database of databases) {
        if (shouldIgnore(database)) continue;
        const databasePath = path.join(homeDir, database);
        const stat = yield fsp.stat(databasePath);
        if (!stat.isDirectory()) continue;

        const importNames = yield fsp.readdir(databasePath);
        for (const importName of importNames) {
            if (shouldIgnore(importName)) continue;
            const importNamePath = path.join(databasePath, importName);
            const stat = yield fsp.stat(importNamePath);
            if (!stat.isDirectory()) continue;

            try {
                const importConfigPath = path.join(importNamePath, 'import');
                const importConfig = require(importConfigPath);
                if (importConfig && Array.isArray(importConfig.source)) {
                    for (const source of importConfig.source) {
                        try {
                            const sourcePath = path.resolve(importNamePath, source);
                            const sourceToProcessPath = path.join(sourcePath, 'to_process');
                            const stat = yield fsp.stat(sourceToProcessPath);
                            if (stat.isDirectory()) {
                                const fileList = yield getFilesToProcess(sourceToProcessPath);
                                const objFiles = fileList.map(file => ({database, importName, path: file}));
                                files = files.concat(objFiles);
                            }
                        } catch (e) {
                            // ignore
                        }
                    }
                }
            } catch (e) {
                // ignore
            }

            try {
                const toProcessPath = path.join(importNamePath, 'to_process');
                const stat = yield fsp.stat(toProcessPath);
                if (stat.isDirectory()) {
                    const fileList = yield getFilesToProcess(toProcessPath);
                    const objFiles = fileList.map(file => ({database, importName, path: file}));
                    files = files.concat(objFiles);
                }
            } catch (e) {
                // ignore
            }
        }
    }

    return files;
});

function getFilesToProcess(directory) {
    return new Promise((resolve, reject) => {
        const items = [];
        var readStream = fs.walk(directory);
        readStream
            .on('data', function (item) {
                if (item.stats.isFile()) {
                    items.push(item.path);
                }
            })
            .on('end', function () {
                resolve(items);
            })
            .on('error', function (error) {
                reject(error);
            });
    });
}

function getHomeDir() {
    let homeDir = home.homeDir;
    if (!homeDir) {
        die('homeDir must be set to import all');
    }
    return homeDir;
}

function checkFile(homeDir, p) {
    p = path.resolve(homeDir, p);
    const relpath = path.relative(homeDir, p);
    const elements = relpath.split('/');
    if (elements.length < 4) return false;
    if (elements[2] !== 'to_process') return false;
    if (hasImportFile(path.resolve(homeDir, elements[0] + '/' + elements[1]))) {
        return {
            database: elements[0],
            importName: elements[1]
        };
    }
}

function processFile(database, importName, homeDir, p) {
    debug.trace(`process file ${p}`);
    p = path.resolve(homeDir, p);
    let parsedPath = path.parse(p);

    processChain = processChain.then(() => {
        return imp.import(database, importName, p);
    }).then(() => {
        // mv to processed
        return new Promise(function (resolve, reject) {
            let dir = path.join(parsedPath.dir, '../processed/' + getDatePath());
            createDir(dir);
            tryRename(p, path.join(dir, parsedPath.base), resolve, reject);
        });
    }).catch(e => {
        if (e.skip) return;
        // mv to errored
        return new Promise(function (resolve, reject) {
            if (e.message.startsWith('no import config')) {
                debug.warn('no import configuration found, skipping this file');
                return resolve();
            }
            debug.error(e + '\n' + e.stack);
            let dir = path.join(parsedPath.dir, '../errored/' + getDatePath());
            createDir(dir);
            tryRename(p, path.join(dir, parsedPath.base), resolve, reject);
        });
    });

    return processChain;
}

function* processFile2(database, importName, filePath) {
    debug.trace(`process file ${filePath}`);
    const parsedPath = path.parse(filePath);
    const splitParsedPath = parsedPath.dir.split('/');
    const toProcess = splitParsedPath.indexOf('to_process');
    if (toProcess === -1) {
        throw new Error('to_process not found in path. This should not happen');
    }

    try {
        yield imp.import(database, importName, filePath);
        // success, move to processed
        yield moveFile(filePath, parsedPath.base, splitParsedPath, toProcess, 'processed');
    } catch (e) {
        if (e.skip) return;
        // error, move to errored
        if (e.message.startsWith('no import config')) {
            debug.warn('no import configuration found, skipping this file');
            return;
        }
        debug.error(e + '\n' + e.stack);
        yield moveFile(filePath, parsedPath.base, splitParsedPath, toProcess, 'errored');
    }
}

function* moveFile(filePath, fileName, splitParsedPath, toProcess, dest) {
    const base = splitParsedPath.slice(0, toProcess).join('/');
    let subdir;
    if (splitParsedPath.length - toProcess > 1) {
        subdir = splitParsedPath.slice(toProcess + 1).join('/');
    } else {
        subdir = getDatePath();
    }
    const destination = path.join(base, dest, subdir, fileName);
    yield tryMove(filePath, destination);
}

function* tryMove(from, to, suffix) {
    if (suffix > 1000) {
        throw new Error('tryMove: too many retries');
    }
    if (!suffix) {
        suffix = 0;
    }
    var newTo = to;
    if (suffix > 0) {
        newTo += '.' + suffix;
    }
    try {
        yield fsp.move(from, newTo);
    } catch (e) {
        if (e.code !== 'EEXIST') {
            throw new Error(`Could could rename ${from} to ${newTo}: ${e}`);
        }
        yield tryMove(from, to, ++suffix);
    }
}

function tryRename(from, to, resolve, reject, suffix) {
    if (!suffix) {
        suffix = 0;
    }
    var newTo = to;
    if (suffix > 0) {
        newTo += '.' + suffix;
    }
    fs.access(newTo, function (err) {
        if (err) {
            if (err.code !== 'ENOENT') {
                debug.error(`Could could rename ${from} to ${newTo}: ${err}`);
                return reject(err);
            } else {
                return fs.rename(from, newTo, function (err) {
                    if (err) return reject(err);
                    resolve();
                });
            }
        }
        // file exists. retry with another name
        return tryRename(from, to, resolve, reject, ++suffix);
    });
}

function hasImportFile(p) {
    if (importFiles[p]) return true;
    const importFile = path.join(p, 'import.js');
    try {
        fs.accessSync(importFile);
        importFiles[p] = true;
        return true;
    } catch (e) {
        return false;
    }
}

function createDir(dir) {
    if (createdDirs[dir]) return;

    fs.mkdirpSync(dir);
    createdDirs[dir] = true;
}

function getDatePath() {
    var now = new Date();
    return now.getUTCFullYear() + '/' + ('0' + (now.getUTCMonth() + 1)).slice(-2) + '/' + ('0' + now.getUTCDate()).slice(-2);
}

function shouldIgnore(name) {
    return name === 'node_modules' ||
        name.startsWith('.');
}

if (program.args[0]) {
    debug(`file argument: ${program.args[0]}`);
    // TODO add 2 arguments: db and import names
    throw new Error('not ready');
    //const file = path.resolve(program.args[0]);
    //imp.import(config, file);
} else if (program.watch) {
    // watch files to import
    let homeDir = getHomeDir();
    debug(`watch ${homeDir}`);
    chokidar.watch(homeDir, {
        ignored: /[\/\\](\.|processed|errored|node_modules)/,
        persistent: true
    }).on('all', function (event, p) {
        debug.trace(`watch event: ${event} - ${p}`);
        let file = checkFile(homeDir, p);
        if (event !== 'add' && event !== 'change' || !file) {
            return;
        }
        processFile(file.database, file.importName, homeDir, p);
    });
} else if (program.continuous) {
    const waitTime = program.wait * 1000;
    debug(`continuous import. Wait time is ${program.wait}`);
    doContinuous(waitTime);
} else {
    debug('no watch');
    importAll().then(function () {
        debug('finished');
    }, function (err) {
        die(err.message || err);
    });
}
<|endoftext|>


<commit_before><commit_msg>Update ogario.v4.js<commit_after><|endoftext|>


<commit_before>/**
 * Pages
 *
 * for PagesController
 */
var Pages = {};

/**
 * functions to execute when document is ready
 *
 * only for PagesController
 *
 * @return void
 */
Pages.documentReady = function() {
    Pages.search();
}

/**
 * Submits form for searching Pages
 *
 * @return void
 */
Pages.search = function() {

    $('#PageAdminIndexForm, #PageAdminFilterForm').submit(function() {
        var q='';

        //query string
        if($('#PageQ').val() != '') {
            q=$('#PageQ').val();
        }
        var loadUrl = Hurad.basePath + 'admin/pages/index';
        if (q != '') {
            loadUrl +='/q:'+q;
        }

        window.location = loadUrl;
        return false;
    });
}

/**
 * document ready
 *
 * @return void
 */
$(document).ready(function() {
    if (Hurad.params.controller == 'pages') {
        Pages.documentReady();
    }
});
<commit_msg>Change form id.<commit_after>/**
 * Pages
 *
 * for PagesController
 */
var Pages = {};

/**
 * functions to execute when document is ready
 *
 * only for PagesController
 *
 * @return void
 */
Pages.documentReady = function() {
    Pages.search();
}

/**
 * Submits form for searching Pages
 *
 * @return void
 */
Pages.search = function() {

    $('#AdminSearchForm').submit(function() {
        var q = '';

        //query string
        if ($('#PageQ').val() != '') {
            q = $('#PageQ').val();
        }
        var loadUrl = Hurad.basePath + 'admin/pages/index';
        if (q != '') {
            loadUrl += '/q:' + q;
        }

        window.location = loadUrl;
        return false;
    });
}

/**
 * document ready
 *
 * @return void
 */
$(document).ready(function() {
    if (Hurad.params.controller == 'pages') {
        Pages.documentReady();
    }
});
<|endoftext|>


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

/**
 * List of all FOAM files available to be loaded in a JSONP
 * format, so it can used from both nodejs scripts, and web
 * pages via script tags easily.
 */

FOAM_FILES([
  { name: "foam/core/poly" },
  { name: "foam/core/lib" },
  { name: "foam/core/stdlib" },
  { name: "foam/core/events" },
  { name: "foam/core/Context" },
  { name: "foam/core/Boot" },
  { name: "foam/core/FObject" },
  { name: "foam/core/Model" },
  { name: "foam/core/Property" },
  { name: "foam/core/Method" },
  { name: "foam/core/Boolean" },
  { name: "foam/core/AxiomArray" },
  { name: "foam/core/EndBoot" },
  { name: "foam/core/FObjectArray" },
  { name: "foam/core/Constant" },
  { name: "foam/core/Validation" },
  { name: "foam/pattern/Faceted" },
  { name: "foam/core/types" },
  { name: "foam/core/Topic" },
  { name: "foam/core/InnerClass" },
  { name: "foam/core/InnerEnum" },
  { name: "foam/core/Implements" },
  { name: "foam/core/ImportsExports" },
  { name: "foam/core/Listener" },
  { name: "foam/core/IDSupport" },
  { name: "foam/core/Requires" },
  { name: "foam/core/Slot" },
  { name: "foam/core/Proxy" },
  { name: "foam/core/Promised" },
  { name: "foam/core/Interface" },
  { name: "foam/core/ContextMethod" },
  { name: "foam/core/Window" },
  { name: "foam/classloader/ClassLoader" },
  { name: "foam/core/Argument" },
  { name: "foam/core/MultiMethod" },
  { name: "foam/core/debug", flags: ['debug'] },
  { name: "foam/pattern/Singleton" },
  { name: "foam/pattern/Multiton" },
  { name: "foam/core/Enum" },
  { name: "foam/core/JSON" },
  { name: "foam/parse/parse" },
  { name: "foam/core/templates" },
  { name: "foam/core/Action" },
  { name: "foam/core/Serializable" },
  { name: "lib/java", flags: ['java'] },
  { name: "lib/JavaClass", flags: ['java'] },
  { name: "foam/util/Timer" },
  { name: "foam/memento/MementoMgr" },
  { name: "lib/input", flags: ['web'] },
  { name: "foam/u2/AttrSlot" },
  { name: "foam/u2/ViewSpec" },
  { name: "foam/u2/Element" },
//  { name: "foam/u2/AttrSlot", flags: ['web'] },
//  { name: "foam/u2/Element", flags: ['web'] },
  { name: "foam/u2/ProgressView", flags: ['web'] },
  { name: "foam/dao/FlowControl" },
  { name: "foam/dao/FlowControlJava", flags: ['java'] },
  { name: "foam/dao/Sink" },
  { name: "foam/dao/SinkJava", flags: ['java'] },
  { name: "foam/dao/DAO" },
  { name: "foam/dao/DAOJava", flags: ['java'] },
  { name: "foam/dao/daoUtils" },
  { name: "foam/dao/AbstractDAO" },
  { name: "foam/dao/DAOProperty" },
  { name: "foam/mlang/mlang" },
  { name: "foam/mlang/mlangJava", flags: ['java'] },
  { name: "foam/mlang/LabeledValue" },
  { name: "foam/dao/index/Plan" },
  { name: "foam/dao/index/Index" },
  { name: "foam/dao/index/ProxyIndex" },
  { name: "foam/dao/index/AltIndex" },
  { name: "foam/dao/index/ValueIndex" },
  { name: "foam/dao/index/AATree" },
  { name: "foam/dao/index/TreeIndex" },
  { name: "foam/dao/index/AutoIndex" },
  { name: "foam/dao/MDAO" },
  { name: "foam/dao/ArrayDAO" },
  { name: "foam/dao/TimestampDAO" },
  { name: "foam/dao/GUIDDAO" },
  { name: "foam/dao/JournalDAO" },
  { name: "foam/dao/Relationship" },
  { name: "foam/dao/RelationshipDAO" },
  { name: "foam/dao/LazyCacheDAO" },
  { name: "foam/dao/CachingDAO" },
  { name: "foam/dao/DeDupDAO" },
  { name: "foam/dao/LRUDAOManager" },
  { name: "foam/dao/SequenceNumberDAO" },
  { name: "foam/dao/ContextualizingDAO" },
  { name: "foam/dao/SyncDAO" },
  { name: "foam/dao/EasyDAO" },
  { name: "foam/dao/NoSelectAllDAO" },
  { name: "foam/dao/NullDAO" },
  { name: "foam/dao/TimingDAO" },
  { name: "foam/dao/LoggingDAO" },
  { name: "foam/dao/IDBDAO", flags: ['web'] },
  { name: "foam/parse/QueryParser" },
  { name: "foam/physics/Physical" },
  { name: "foam/physics/Collider" },
  { name: "foam/physics/PhysicsEngine" },
  { name: "lib/node/json_dao", flags: ['node'] },
  { name: "lib/utf8" },
  { name: "lib/net" },
  { name: "lib/messageport", flags: ['web'] },
  { name: "lib/node/net", flags: ['node'] },
  { name: "lib/firebase" },
  { name: "lib/fcm" },
  { name: "lib/Stub" },
  { name: "lib/box" },
  { name: "lib/boxJava", flags: ['java'] },
  { name: "foam/core/async" },
  { name: "foam/u2/ViewFactory", flags: ['web'] },
  { name: "foam/u2/daos", flags: ['web'] },
  { name: "foam/u2/TableView", flags: ['web'] },
  { name: "foam/u2/TableSelection", flags: ['web'] },
  { name: "foam/u2/Scroller", flags: ['web'] },
  { name: "foam/u2/ActionView", flags: ['web'] },
  { name: "foam/u2/DetailPropertyView", flags: ['web'] },
  { name: "foam/u2/DetailView", flags: ['web'] },
  { name: "foam/u2/tag/Image", flags: ['web'] },
  { name: "foam/u2/tag/Input", flags: ['web'] },
  { name: "foam/u2/tag/TextArea", flags: ['web'] },
  { name: "foam/u2/TextField", flags: ['web'] },
  { name: "foam/u2/IntView", flags: ['web'] },
  { name: "foam/u2/FloatView", flags: ['web'] },
  { name: "foam/u2/CheckBox", flags: ['web'] },
  { name: "foam/u2/CitationView", flags: ['web'] },
  { name: "foam/u2/PopupView", flags: ['web'] },
  { name: "foam/u2/DateView", flags: ['web'] },
  { name: "foam/u2/DateTimeView", flags: ['web'] },
  { name: "foam/u2/RangeView", flags: ['web'] },
  { name: "foam/u2/ReadWriteView", flags: ['web'] },
  { name: "foam/u2/HTMLElement", flags: ['web'] },
  { name: "foam/u2/tag/Select", flags: ['web'] },
  { name: "foam/u2/Tabs", flags: ['web'] },
  { name: "foam/u2/view/ChoiceView", flags: ['web'] },
  { name: "foam/u2/view/RadioView", flags: ['web'] },
  { name: "foam/u2/view/TextField", flags: ['web'] },
  { name: "foam/u2/view/TreeView", flags: ['web'] },
  { name: "foam/u2/view/DualView", flags: ['web'] },
  { name: "foam/u2/view/ColorPicker", flags: ['web'] },
  { name: "foam/u2/view/TableView", flags: ['web'] },
  { name: "foam/u2/ClassView", flags: ['web'] },
  { name: "foam/u2/view/ReferenceView", flags: ['web'] },
  { name: "foam/u2/tag/Card", flags: ['web'] },
  { name: "foam/u2/dialog/Popup", flags: ['web'] },
  { name: "foam/u2/Autocompleter", flags: ['web'] },
  { name: "foam/u2/search/FilterController", flags: ['web'] },
  { name: "foam/u2/search/GroupCompleter", flags: ['web'] },
  { name: "foam/u2/search/GroupAutocompleteSearchView", flags: ['web'] },
  { name: "foam/u2/search/GroupBySearchView", flags: ['web'] },
  { name: "foam/u2/search/SearchManager", flags: ['web'] },
  { name: "foam/u2/search/TextSearchView", flags: ['web'] },
  { name: "foam/u2/stack/Stack", flags: ['web'] },
  { name: "foam/u2/stack/StackView", flags: ['web'] },
  { name: "foam/u2/FoamTagLoader", flags: ['loader'] },
  { name: "foam/graphics/CView", flags: ['web'] },
  { name: "foam/graphics/ScrollCView", flags: ['web'] },
  { name: "foam/physics/PhysicalCircle", flags: ['web'] },
  { name: "foam/comics/DAOCreateController" },
  { name: "lib/node/net", flags: ['node'] },
  { name: "lib/node/box", flags: ['node'] },
  { name: "foam/net/HTTPMethod" },
  { name: "foam/doc/DocBrowser", flags: ['debug'] },
]);
<commit_msg>files.js - add SQL<commit_after>/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * List of all FOAM files available to be loaded in a JSONP
 * format, so it can used from both nodejs scripts, and web
 * pages via script tags easily.
 */

FOAM_FILES([
  { name: "foam/core/poly" },
  { name: "foam/core/lib" },
  { name: "foam/core/stdlib" },
  { name: "foam/core/events" },
  { name: "foam/core/Context" },
  { name: "foam/core/Boot" },
  { name: "foam/core/FObject" },
  { name: "foam/core/Model" },
  { name: "foam/core/Property" },
  { name: "foam/core/Method" },
  { name: "foam/core/Boolean" },
  { name: "foam/core/AxiomArray" },
  { name: "foam/core/EndBoot" },
  { name: "foam/core/FObjectArray" },
  { name: "foam/core/Constant" },
  { name: "foam/core/Validation" },
  { name: "foam/pattern/Faceted" },
  { name: "foam/core/types" },
  { name: "foam/core/Topic" },
  { name: "foam/core/InnerClass" },
  { name: "foam/core/InnerEnum" },
  { name: "foam/core/Implements" },
  { name: "foam/core/ImportsExports" },
  { name: "foam/core/Listener" },
  { name: "foam/core/IDSupport" },
  { name: "foam/core/Requires" },
  { name: "foam/core/Slot" },
  { name: "foam/core/Proxy" },
  { name: "foam/core/Promised" },
  { name: "foam/core/Interface" },
  { name: "foam/core/ContextMethod" },
  { name: "foam/core/Window" },
  { name: "foam/classloader/ClassLoader" },
  { name: "foam/core/Argument" },
  { name: "foam/core/MultiMethod" },
  { name: "foam/core/debug", flags: ['debug'] },
  { name: "foam/pattern/Singleton" },
  { name: "foam/pattern/Multiton" },
  { name: "foam/core/Enum" },
  { name: "foam/core/JSON" },
  { name: "foam/parse/parse" },
  { name: "foam/core/templates" },
  { name: "foam/core/Action" },
  { name: "foam/core/Serializable" },
  { name: "lib/java", flags: ['java'] },
  { name: "lib/JavaClass", flags: ['java'] },
  { name: "foam/util/Timer" },
  { name: "foam/memento/MementoMgr" },
  { name: "lib/input", flags: ['web'] },
  { name: "foam/u2/AttrSlot" },
  { name: "foam/u2/ViewSpec" },
  { name: "foam/u2/Element" },
//  { name: "foam/u2/AttrSlot", flags: ['web'] },
//  { name: "foam/u2/Element", flags: ['web'] },
  { name: "foam/u2/ProgressView", flags: ['web'] },
  { name: "foam/dao/FlowControl" },
  { name: "foam/dao/FlowControlJava", flags: ['java'] },
  { name: "foam/dao/Sink" },
  { name: "foam/dao/SinkJava", flags: ['java'] },
  { name: "foam/dao/DAO" },
  { name: "foam/dao/DAOJava", flags: ['java'] },
  { name: "foam/dao/daoUtils" },
  { name: "foam/dao/AbstractDAO" },
  { name: "foam/dao/DAOProperty" },
  { name: "foam/mlang/mlang" },
  { name: "foam/mlang/mlangJava", flags: ['java'] },
  { name: "foam/mlang/LabeledValue" },
  { name: "foam/dao/index/Plan" },
  { name: "foam/dao/index/Index" },
  { name: "foam/dao/index/ProxyIndex" },
  { name: "foam/dao/index/AltIndex" },
  { name: "foam/dao/index/ValueIndex" },
  { name: "foam/dao/index/AATree" },
  { name: "foam/dao/index/TreeIndex" },
  { name: "foam/dao/index/AutoIndex" },
  { name: "foam/dao/MDAO" },
  { name: "foam/dao/ArrayDAO" },
  { name: "foam/dao/TimestampDAO" },
  { name: "foam/dao/GUIDDAO" },
  { name: "foam/dao/JournalDAO" },
  { name: "foam/dao/Relationship" },
  { name: "foam/dao/RelationshipDAO" },
  { name: "foam/dao/LazyCacheDAO" },
  { name: "foam/dao/CachingDAO" },
  { name: "foam/dao/DeDupDAO" },
  { name: "foam/dao/LRUDAOManager" },
  { name: "foam/dao/SequenceNumberDAO" },
  { name: "foam/dao/ContextualizingDAO" },
  { name: "foam/dao/SyncDAO" },
  { name: "foam/dao/EasyDAO" },
  { name: "foam/dao/NoSelectAllDAO" },
  { name: "foam/dao/NullDAO" },
  { name: "foam/dao/TimingDAO" },
  { name: "foam/dao/LoggingDAO" },
  { name: "foam/dao/IDBDAO", flags: ['web'] },
  { name: "foam/dao/SQL" },
  { name: "foam/parse/QueryParser" },
  { name: "foam/physics/Physical" },
  { name: "foam/physics/Collider" },
  { name: "foam/physics/PhysicsEngine" },
  { name: "lib/node/json_dao", flags: ['node'] },
  { name: "lib/utf8" },
  { name: "lib/net" },
  { name: "lib/messageport", flags: ['web'] },
  { name: "lib/node/net", flags: ['node'] },
  { name: "lib/firebase" },
  { name: "lib/fcm" },
  { name: "lib/Stub" },
  { name: "lib/box" },
  { name: "lib/boxJava", flags: ['java'] },
  { name: "foam/core/async" },
  { name: "foam/u2/ViewFactory", flags: ['web'] },
  { name: "foam/u2/daos", flags: ['web'] },
  { name: "foam/u2/TableView", flags: ['web'] },
  { name: "foam/u2/TableSelection", flags: ['web'] },
  { name: "foam/u2/Scroller", flags: ['web'] },
  { name: "foam/u2/ActionView", flags: ['web'] },
  { name: "foam/u2/DetailPropertyView", flags: ['web'] },
  { name: "foam/u2/DetailView", flags: ['web'] },
  { name: "foam/u2/tag/Image", flags: ['web'] },
  { name: "foam/u2/tag/Input", flags: ['web'] },
  { name: "foam/u2/tag/TextArea", flags: ['web'] },
  { name: "foam/u2/TextField", flags: ['web'] },
  { name: "foam/u2/IntView", flags: ['web'] },
  { name: "foam/u2/FloatView", flags: ['web'] },
  { name: "foam/u2/CheckBox", flags: ['web'] },
  { name: "foam/u2/CitationView", flags: ['web'] },
  { name: "foam/u2/PopupView", flags: ['web'] },
  { name: "foam/u2/DateView", flags: ['web'] },
  { name: "foam/u2/DateTimeView", flags: ['web'] },
  { name: "foam/u2/RangeView", flags: ['web'] },
  { name: "foam/u2/ReadWriteView", flags: ['web'] },
  { name: "foam/u2/HTMLElement", flags: ['web'] },
  { name: "foam/u2/tag/Select", flags: ['web'] },
  { name: "foam/u2/Tabs", flags: ['web'] },
  { name: "foam/u2/view/ChoiceView", flags: ['web'] },
  { name: "foam/u2/view/RadioView", flags: ['web'] },
  { name: "foam/u2/view/TextField", flags: ['web'] },
  { name: "foam/u2/view/TreeView", flags: ['web'] },
  { name: "foam/u2/view/DualView", flags: ['web'] },
  { name: "foam/u2/view/ColorPicker", flags: ['web'] },
  { name: "foam/u2/view/TableView", flags: ['web'] },
  { name: "foam/u2/ClassView", flags: ['web'] },
  { name: "foam/u2/view/ReferenceView", flags: ['web'] },
  { name: "foam/u2/tag/Card", flags: ['web'] },
  { name: "foam/u2/dialog/Popup", flags: ['web'] },
  { name: "foam/u2/Autocompleter", flags: ['web'] },
  { name: "foam/u2/search/FilterController", flags: ['web'] },
  { name: "foam/u2/search/GroupCompleter", flags: ['web'] },
  { name: "foam/u2/search/GroupAutocompleteSearchView", flags: ['web'] },
  { name: "foam/u2/search/GroupBySearchView", flags: ['web'] },
  { name: "foam/u2/search/SearchManager", flags: ['web'] },
  { name: "foam/u2/search/TextSearchView", flags: ['web'] },
  { name: "foam/u2/stack/Stack", flags: ['web'] },
  { name: "foam/u2/stack/StackView", flags: ['web'] },
  { name: "foam/u2/FoamTagLoader", flags: ['loader'] },
  { name: "foam/graphics/CView", flags: ['web'] },
  { name: "foam/graphics/ScrollCView", flags: ['web'] },
  { name: "foam/physics/PhysicalCircle", flags: ['web'] },
  { name: "foam/comics/DAOCreateController" },
  { name: "lib/node/net", flags: ['node'] },
  { name: "lib/node/box", flags: ['node'] },
  { name: "foam/net/HTTPMethod" },
  { name: "foam/doc/DocBrowser", flags: ['debug'] },
]);
<|endoftext|>


<commit_before>/* global d3 */
/* global autobahn */
/* global $ */
(function() {
    "use strict";
    /* TODO:
     *  - keep up with messages
     *    - cljs?
     *  - be nice to separate base Serf functionality
     */
    var w = 960,
        h = 500;

    var midx = Math.floor(w/2),
        midy = Math.floor(h/2);

    var g_nodes = [];

    var force = d3.layout.force()
        .gravity(0)
        .charge(0)
        .linkDistance(50)
        .nodes(g_nodes)
        .size([w, h]);

    var links = force.links();
    var pendingLinks = [];
    var started = false;
    var colors = { "alive": "#5cb85c",
                   "failed": "#d9534f",
                   "fixing": "#f0ad4e",
                   "fixed": "#5cb85c",
                   "leaving": "gray"};

    force.start();

    var svg = d3.select("#node_graph").append("svg:svg")
        .attr("width", w)
        .attr("height", h);

    //Definition of graphic for arrows on deps
    svg.append("svg:defs").append("svg:marker")
        .attr("id", "triangle")
        .attr("refX", "14")
        .attr("refY", "6.5")
        .attr("markerUnits", "strokeWidth")
        .attr("markerWidth", "26")
        .attr("markerHeight", "26")
        .attr("orient", "auto")
        .append("svg:path")
          .attr("d", "M2,4 L2,9 L5,6.5 L2,4")
          .attr("style", "fill: #000000;");

    svg.append("svg:rect")
        .attr("width", w)
        .attr("height", h);

    force.on("tick", function(e) {
        var q = d3.geom.quadtree(g_nodes),
            k = e.alpha * 0.1,
            i = 0,
            n = g_nodes.length,
            o;

        for (i=0; i<n; i++) {
            o = g_nodes[i];
            if (o.fixed) {
                continue;
            }
            //Move towards middle
            o.x += (midx - o.x) * k;
            o.y += (midy - o.y) * k;
            q.visit(collide(o));
        }

        svg.selectAll(".node")
            .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")";});

        svg.selectAll("circle")
           .attr("r", function(n) { return n.radius - 2; }) // -2 creates border
           .style("fill", function(n) {return colors[n.status];});

        svg.selectAll("text")
            .text(function(d) { return d.role.substring(0,1); });

        var lines = svg.selectAll(".link");
        lines.data(links).enter()
            .insert("line", ".node")
            .attr("class", "link")
            .attr("marker-end", "url(#triangle)");
        lines.attr("x1", function(d) { return d.source.x; })
            .attr("y1", function(d) { return d.source.y; })
            .attr("x2", function(d) { return d.target.x; })
            .attr("y2", function(d) { return d.target.y; });
    });

    function collide(node) {
        var r = node.radius + 16,
            nx1 = node.x - r,
            nx2 = node.x + r,
            ny1 = node.y - r,
            ny2 = node.y + r;

        return function(quad, x1, y1, x2, y2) {
            if (quad.point && (quad.point !== node)) {
                var x = node.x - quad.point.x,
                    y = node.y - quad.point.y,
                    l = Math.sqrt(x * x + y * y),
                    r = node.radius + quad.point.radius;
                if (l < r) {
                    l = (l - r) / l * 0.5;
                    node.px += x * l;
                    node.py += y * l;
                }
            }
            return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
        };
    }

    var connection = new autobahn.Connection({
        url: 'ws://127.0.0.1:5000/ws',
        realm: 'realm1'
    });

    var nodes = {};

    function logMessage(message) {

        console.log(message);

        for (var key in message) {
            //Make sure avoid anything in prototype
            if (message.hasOwnProperty(key)) {
                $("#message_log").append("
" + key + " " + message[key] + "
");
            }
        }
        while ($("#message_log p").length > 5) {
            $("#message_log p")[0].remove();
        }

    }

    function updateNodes(error, json) {

        if (error) {
            return console.warn(error);
        }

        for (var i = 0; i < json.members.length; i++) {
            var m = json.members[i];

            var id = "A" + m.addr.split(":")[0].replace(/\./g, "d");
            var add = false;
            if (!(id in nodes)) {
                //Set a default value for memory
                nodes[id] = {"memory": 20};
                nodes[id].par = "None";
                add = true;
            }
            nodes[id].addr = m.addr;
            nodes[id].radius = 8 + nodes[id].memory / 2;
            nodes[id].name = m.name;
            nodes[id].status = m.status;
            nodes[id].id = "A" + m.addr.split(":")[0].replace(/\./g, "d");
            if (m.tags.role) {
                nodes[id].role = m.tags.role;
            } else {
                nodes[id].role = "?";
            }

            if (m.tags.parent) {
                if (nodes[id].par !== m.tags.parent) {
                    nodes[id].par = m.tags.parent;
                    var toAdd = nodes[id].par.split(",");
                    for (var j=0; j< toAdd.length; j++) {
                        pendingLinks.push({sourceId: addrToId(toAdd[j]), targetId: id});
                    }
                }
            }

            if (add) {
                addGraphNode(nodes[id]);
            }

            if (nodes[id].status === "left") {
                removeGraphNode(nodes[id]);
            }
        }
        //Should also delete any nodes that don't appear in list

        checkPendingLinks();
        updateMemberTable();
        updateGraph();
    }

    function checkPendingLinks() {

        for (var i = pendingLinks.length -1; i >= 0; i--) {

            var src = nodes[pendingLinks[i].sourceId];
            var trg = nodes[pendingLinks[i].targetId];

            //think src && trg should work
            if (typeof(src) != "undefined" && typeof(trg) != "undefined") {
                //console.log(src);
                //console.log(trg);
                links.push({source: src, target: trg});
                pendingLinks.splice(i, 1);
            }

        }

    }

    function updateMemberTable() {

        var table = d3.select("#node_table").html("").append("table")
            .attr("class", "table table-bordered table-condensed");
        var tbody = table.append("tbody");

        for (var id in nodes) {
            if (nodes.hasOwnProperty(id)) {
                var n = nodes[id];
                var tr = tbody.append("tr").attr("id", id);
                tr.append("td").text(n.name);
                tr.append("td").text(n.addr);
                tr.append("td").text(n.memory);
                tr.append("td").text(n.role);
                tr.append("td").text(n.par);
                tr.append("td").text(n.status);
                if (n.status === "fixing") {
                    tr.classed("success", false);
                    tr.classed("warning", true);
                } else if (n.status === "fixed") {
                    tr.classed("warning", false);
                    tr.classed("success", true);
                }
            }
        }

        var thead = table.append("thead");
        thead.append("th").text("Name");
        thead.append("th").text("Address");
        thead.append("th").text("Memory");
        thead.append("th").text("Role");
        thead.append("th").text("Parent");
        thead.append("th").text("Status");

    }

    //Change this to be function on nodes
    function getNodeArray() {

        var children = [];
        for (var id in nodes) {
            if (nodes.hasOwnProperty(id)) {
                children.push(nodes[id]);
            }
        }
        return children;
    }

    function removeGraphNode(n) {
        var ind = g_nodes.indexOf(n);
        if (ind !== -1) {
            g_nodes.splice(ind, 1);
        }
        d3.select("#" + n.id).remove();

    }

    function addGraphNode(n) {

        n.x = Math.floor(Math.random() * w);
        n.y = Math.floor(Math.random() * w);

        var g = svg.append("svg:g")
            .data([n])
            .attr("id", n.id)
            .attr("class", "node")
            .attr("transform", function (n) { return "translate(" + n.x + "," + n.y + ")";});
        var circ = g.append("svg:circle")
            .data([n])
            .attr("r", function(n) { return n.radius - 2; }) // -2 creates border
            .style("fill", function(n) {return colors[n.status];});
        circ.append("svg:title")
            .text(function(d) { return d.addr; });
        g.append("text")
            .data([n])
            .attr("dy", ".3em")
            .style("text-anchor", "middle")
            .text(function(d) { return d.role.substring(0,1); });

        g_nodes.push(n);

    }

    function updateGraph() {

        force.start();

    }

    function addrToId(addr) {
        return "A" + addr.replace(/\./g, "d").replace(/\n/g, "");
    }

    function extractArg(arg, string) {

        var re = new RegExp(arg + "=(\\S*)");
        var res = re.exec(string);
        if (res && res.length > 1) {
            return  re.exec(string)[1];
        }
        return "";
    }

    connection.onopen = function (session) {

        var received = 0;

        var updateNodesFunc = function() {
            d3.json("members", updateNodes);
        };
        function onevent1(args) {

            var message = $.parseJSON(args);
            logMessage(message);

            /*
             * Ignore NEWNODE and use member-join
             * Read member-update
             * Figure out leave stuff */
            for (var key in message) {
                if (message.hasOwnProperty(key)) {
                    console.log("got key " + key);
                    if (key === "FIXING") {
                        var target = addrToId(message[key]);
                        nodes[target].status = "fixing";
                        updateMemberTable();
                        updateGraph();
                    } else if (key === "FIXED") {
                        var target = addrToId(message[key]);
                        nodes[target].status = "fixed";
                        updateMemberTable();
                        updateGraph();
                    } else if (key === "REMOVENODE") {
                        setTimeout(updateNodesFunc, 500);
                    } else if (key === "MEMORY_LEVEL") {
                        var level = extractArg("LEVEL", message[key]);
                        var target = extractArg("IP", message[key]);

                        if (level !== "" && target !== "") {
                            var ilevel = +level;
                            if (ilevel !== nodes[addrToId(target)].memory) {
                                nodes[addrToId(target)].memory = ilevel;
                                nodes[addrToId(target)].radius = 8 + ilevel/2;
                                updateMemberTable();
                                updateGraph();
                            }
                        }
                    } else if (key === "member-join" || key === 'member-update' || key === 'member-leave') {
                        updateNodesFunc();
                    }
                }
            }

            received += 1;
            if (received > 5000) {
                console.log("Closing ..");
                connection.close();
            }
        }

        session.subscribe('mitosis.event', onevent1);
    };

    connection.open();

    d3.json("members", updateNodes);

})();
<commit_msg>Small change that allows the websocket connection towards the base host of the url<commit_after>/* global d3 */
/* global autobahn */
/* global $ */
(function() {
    "use strict";
    /* TODO:
     *  - keep up with messages
     *    - cljs?
     *  - be nice to separate base Serf functionality
     */
    var w = 960,
        h = 500;

    var midx = Math.floor(w/2),
        midy = Math.floor(h/2);

    var g_nodes = [];

    var force = d3.layout.force()
        .gravity(0)
        .charge(0)
        .linkDistance(50)
        .nodes(g_nodes)
        .size([w, h]);

    var links = force.links();
    var pendingLinks = [];
    var started = false;
    var colors = { "alive": "#5cb85c",
                   "failed": "#d9534f",
                   "fixing": "#f0ad4e",
                   "fixed": "#5cb85c",
                   "leaving": "gray"};

    force.start();

    var svg = d3.select("#node_graph").append("svg:svg")
        .attr("width", w)
        .attr("height", h);

    //Definition of graphic for arrows on deps
    svg.append("svg:defs").append("svg:marker")
        .attr("id", "triangle")
        .attr("refX", "14")
        .attr("refY", "6.5")
        .attr("markerUnits", "strokeWidth")
        .attr("markerWidth", "26")
        .attr("markerHeight", "26")
        .attr("orient", "auto")
        .append("svg:path")
          .attr("d", "M2,4 L2,9 L5,6.5 L2,4")
          .attr("style", "fill: #000000;");

    svg.append("svg:rect")
        .attr("width", w)
        .attr("height", h);

    force.on("tick", function(e) {
        var q = d3.geom.quadtree(g_nodes),
            k = e.alpha * 0.1,
            i = 0,
            n = g_nodes.length,
            o;

        for (i=0; i<n; i++) {
            o = g_nodes[i];
            if (o.fixed) {
                continue;
            }
            //Move towards middle
            o.x += (midx - o.x) * k;
            o.y += (midy - o.y) * k;
            q.visit(collide(o));
        }

        svg.selectAll(".node")
            .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")";});

        svg.selectAll("circle")
           .attr("r", function(n) { return n.radius - 2; }) // -2 creates border
           .style("fill", function(n) {return colors[n.status];});

        svg.selectAll("text")
            .text(function(d) { return d.role.substring(0,1); });

        var lines = svg.selectAll(".link");
        lines.data(links).enter()
            .insert("line", ".node")
            .attr("class", "link")
            .attr("marker-end", "url(#triangle)");
        lines.attr("x1", function(d) { return d.source.x; })
            .attr("y1", function(d) { return d.source.y; })
            .attr("x2", function(d) { return d.target.x; })
            .attr("y2", function(d) { return d.target.y; });
    });

    function collide(node) {
        var r = node.radius + 16,
            nx1 = node.x - r,
            nx2 = node.x + r,
            ny1 = node.y - r,
            ny2 = node.y + r;

        return function(quad, x1, y1, x2, y2) {
            if (quad.point && (quad.point !== node)) {
                var x = node.x - quad.point.x,
                    y = node.y - quad.point.y,
                    l = Math.sqrt(x * x + y * y),
                    r = node.radius + quad.point.radius;
                if (l < r) {
                    l = (l - r) / l * 0.5;
                    node.px += x * l;
                    node.py += y * l;
                }
            }
            return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
        };
    }

    var connection = new autobahn.Connection({
        url: 'ws://' + window.location.host  + ':5000/ws',
        realm: 'realm1'
    });

    var nodes = {};

    function logMessage(message) {

        console.log(message);

        for (var key in message) {
            //Make sure avoid anything in prototype
            if (message.hasOwnProperty(key)) {
                $("#message_log").append("
" + key + " " + message[key] + "
");
            }
        }
        while ($("#message_log p").length > 5) {
            $("#message_log p")[0].remove();
        }

    }

    function updateNodes(error, json) {

        if (error) {
            return console.warn(error);
        }

        for (var i = 0; i < json.members.length; i++) {
            var m = json.members[i];

            var id = "A" + m.addr.split(":")[0].replace(/\./g, "d");
            var add = false;
            if (!(id in nodes)) {
                //Set a default value for memory
                nodes[id] = {"memory": 20};
                nodes[id].par = "None";
                add = true;
            }
            nodes[id].addr = m.addr;
            nodes[id].radius = 8 + nodes[id].memory / 2;
            nodes[id].name = m.name;
            nodes[id].status = m.status;
            nodes[id].id = "A" + m.addr.split(":")[0].replace(/\./g, "d");
            if (m.tags.role) {
                nodes[id].role = m.tags.role;
            } else {
                nodes[id].role = "?";
            }

            if (m.tags.parent) {
                if (nodes[id].par !== m.tags.parent) {
                    nodes[id].par = m.tags.parent;
                    var toAdd = nodes[id].par.split(",");
                    for (var j=0; j< toAdd.length; j++) {
                        pendingLinks.push({sourceId: addrToId(toAdd[j]), targetId: id});
                    }
                }
            }

            if (add) {
                addGraphNode(nodes[id]);
            }

            if (nodes[id].status === "left") {
                removeGraphNode(nodes[id]);
            }
        }
        //Should also delete any nodes that don't appear in list

        checkPendingLinks();
        updateMemberTable();
        updateGraph();
    }

    function checkPendingLinks() {

        for (var i = pendingLinks.length -1; i >= 0; i--) {

            var src = nodes[pendingLinks[i].sourceId];
            var trg = nodes[pendingLinks[i].targetId];

            //think src && trg should work
            if (typeof(src) != "undefined" && typeof(trg) != "undefined") {
                //console.log(src);
                //console.log(trg);
                links.push({source: src, target: trg});
                pendingLinks.splice(i, 1);
            }

        }

    }

    function updateMemberTable() {

        var table = d3.select("#node_table").html("").append("table")
            .attr("class", "table table-bordered table-condensed");
        var tbody = table.append("tbody");

        for (var id in nodes) {
            if (nodes.hasOwnProperty(id)) {
                var n = nodes[id];
                var tr = tbody.append("tr").attr("id", id);
                tr.append("td").text(n.name);
                tr.append("td").text(n.addr);
                tr.append("td").text(n.memory);
                tr.append("td").text(n.role);
                tr.append("td").text(n.par);
                tr.append("td").text(n.status);
                if (n.status === "fixing") {
                    tr.classed("success", false);
                    tr.classed("warning", true);
                } else if (n.status === "fixed") {
                    tr.classed("warning", false);
                    tr.classed("success", true);
                }
            }
        }

        var thead = table.append("thead");
        thead.append("th").text("Name");
        thead.append("th").text("Address");
        thead.append("th").text("Memory");
        thead.append("th").text("Role");
        thead.append("th").text("Parent");
        thead.append("th").text("Status");

    }

    //Change this to be function on nodes
    function getNodeArray() {

        var children = [];
        for (var id in nodes) {
            if (nodes.hasOwnProperty(id)) {
                children.push(nodes[id]);
            }
        }
        return children;
    }

    function removeGraphNode(n) {
        var ind = g_nodes.indexOf(n);
        if (ind !== -1) {
            g_nodes.splice(ind, 1);
        }
        d3.select("#" + n.id).remove();

    }

    function addGraphNode(n) {

        n.x = Math.floor(Math.random() * w);
        n.y = Math.floor(Math.random() * w);

        var g = svg.append("svg:g")
            .data([n])
            .attr("id", n.id)
            .attr("class", "node")
            .attr("transform", function (n) { return "translate(" + n.x + "," + n.y + ")";});
        var circ = g.append("svg:circle")
            .data([n])
            .attr("r", function(n) { return n.radius - 2; }) // -2 creates border
            .style("fill", function(n) {return colors[n.status];});
        circ.append("svg:title")
            .text(function(d) { return d.addr; });
        g.append("text")
            .data([n])
            .attr("dy", ".3em")
            .style("text-anchor", "middle")
            .text(function(d) { return d.role.substring(0,1); });

        g_nodes.push(n);

    }

    function updateGraph() {

        force.start();

    }

    function addrToId(addr) {
        return "A" + addr.replace(/\./g, "d").replace(/\n/g, "");
    }

    function extractArg(arg, string) {

        var re = new RegExp(arg + "=(\\S*)");
        var res = re.exec(string);
        if (res && res.length > 1) {
            return  re.exec(string)[1];
        }
        return "";
    }

    connection.onopen = function (session) {

        var received = 0;

        var updateNodesFunc = function() {
            d3.json("members", updateNodes);
        };
        function onevent1(args) {

            var message = $.parseJSON(args);
            logMessage(message);

            /*
             * Ignore NEWNODE and use member-join
             * Read member-update
             * Figure out leave stuff */
            for (var key in message) {
                if (message.hasOwnProperty(key)) {
                    console.log("got key " + key);
                    if (key === "FIXING") {
                        var target = addrToId(message[key]);
                        nodes[target].status = "fixing";
                        updateMemberTable();
                        updateGraph();
                    } else if (key === "FIXED") {
                        var target = addrToId(message[key]);
                        nodes[target].status = "fixed";
                        updateMemberTable();
                        updateGraph();
                    } else if (key === "REMOVENODE") {
                        setTimeout(updateNodesFunc, 500);
                    } else if (key === "MEMORY_LEVEL") {
                        var level = extractArg("LEVEL", message[key]);
                        var target = extractArg("IP", message[key]);

                        if (level !== "" && target !== "") {
                            var ilevel = +level;
                            if (ilevel !== nodes[addrToId(target)].memory) {
                                nodes[addrToId(target)].memory = ilevel;
                                nodes[addrToId(target)].radius = 8 + ilevel/2;
                                updateMemberTable();
                                updateGraph();
                            }
                        }
                    } else if (key === "member-join" || key === 'member-update' || key === 'member-leave') {
                        updateNodesFunc();
                    }
                }
            }

            received += 1;
            if (received > 5000) {
                console.log("Closing ..");
                connection.close();
            }
        }

        session.subscribe('mitosis.event', onevent1);
    };

    connection.open();

    d3.json("members", updateNodes);

})();
<|endoftext|>


<commit_before>Ext.namespace('Gemma.Metaheatmap');

	  // a window for displaying details as elements of the image are
	  // hovered over

Gemma.Metaheatmap.HoverWindow = Ext.extend ( Ext.Window, {

	//height : 200,
	width  : 350,
	closable   : false,
	shadow 	   : false,
	border 	   : false,
	bodyBorder : false,
	//hidden	   : true,
	//	bodyStyle  : 'padding: 7px',

	isDocked : false, //

	tplWriteMode : 'overwrite',

	initComponent : function () {
		Gemma.Metaheatmap.HoverWindow.superclass.initComponent.apply ( this, arguments );

		this.tpl = this.initTemplate_();
	},

	initTemplate_ : function () {
		return new Ext.XTemplate (
				'',
				'<tpl for=".">',
				'<tpl if="type==\'condition\'">',   //condition
				'Experiment: {datasetShortName}, {datasetName}

',
				'Condition: {contrastFactorValue} vs {baselineFactorValue} ({factorCategory})

 ',
				'Baseline: {baselineFactorValue}

 ',
				'Specificity: {specificityPercent}% of probes were differentially expressed under this condition ({numberDiffExpressedProbes} out of {numberOfProbesOnArray})

 ',
				'</tpl>',
				'<tpl if="type==\'minipie\'">',     //minipie
				'{percentProbesDiffExpressed} of probes are differentially expressed.

',
				'({numberOfProbesDiffExpressed} of {numberOfProbesTotal}) Click for details.',
				'</tpl>',
				'<tpl if="type==\'gene\'">',		//gene
				'Gene: {geneSymbol} {geneFullName}
',
				'</tpl>',
//				'<tpl if="type==\'contrastCell\'">',  //contrast
//				'Gene: {geneSymbol} {geneFullName}

 ',
//				'Experiment: {datasetShortName}, {datasetName}

',
//				'Factor: {factorCategory} - {factorDescription}

 ',
//				'Log2 fold change: {foldChange:sciNotation}
',
//				'pValue: {contrastPvalue:sciNotation}
',
//				'</tpl>',
				'<tpl if="type==\'cell\'">',		 //cell
				'Gene: {geneSymbol} {geneFullName}

 ',
				'Experiment: {datasetShortName}, {datasetName}

',
				'Condition: {contrastFactorValue} vs {baselineFactorValue} ({factorCategory})

 ',
				'Baseline: {baselineFactorValue}

 ',
				'p-value: {pvalue:sciNotation}

',
				'log fold change: {foldChange:sciNotation}',
				'</tpl>', '</tpl>');
	},

	onRender: function() {
		Gemma.Metaheatmap.HoverWindow.superclass.onRender.apply ( this, arguments );
	}

});

Ext.reg('Metaheatmap.HoverWindow',Gemma.Metaheatmap.HoverWindow);
<commit_msg>Show more info in a hover window.<commit_after>Ext.namespace('Gemma.Metaheatmap');

	  // a window for displaying details as elements of the image are
	  // hovered over

Gemma.Metaheatmap.HoverWindow = Ext.extend ( Ext.Window, {

	//height : 200,
	width  : 350,
	closable   : false,
	shadow 	   : false,
	border 	   : false,
	bodyBorder : false,
	//hidden	   : true,
	//	bodyStyle  : 'padding: 7px',

	isDocked : false, //

	tplWriteMode : 'overwrite',

	initComponent : function () {
		Gemma.Metaheatmap.HoverWindow.superclass.initComponent.apply ( this, arguments );

		this.tpl = this.initTemplate_();
	},

	initTemplate_ : function () {
		return new Ext.XTemplate (
				'',
				'<tpl for=".">',
				'<tpl if="type==\'condition\'">',   //condition
				'Experiment: {datasetShortName}, {datasetName}
',
				'Condition: {contrastFactorValue} vs {baselineFactorValue} ({factorCategory})
 ',
				'Baseline: {baselineFactorValue}
 ',
				'Enrichment: {ora:sciNotation}
 ',
				'Specificity: {specificityPercent}% of probes were differentially expressed under this condition ({numberDiffExpressedProbes} out of {numberOfProbesOnArray})

 ',
				'</tpl>',
				'<tpl if="type==\'minipie\'">',     //minipie
				'{percentProbesDiffExpressed} of probes are differentially expressed.
',
				'({numberOfProbesDiffExpressed} of {numberOfProbesTotal}) Click for details.',
				'</tpl>',
				'<tpl if="type==\'gene\'">',		//gene
				'Gene: {geneSymbol} {geneFullName}
',
				'Meta P value: {geneMetaPvalue:sciNotation}
',
				'</tpl>',
//				'<tpl if="type==\'contrastCell\'">',  //contrast
//				'Gene: {geneSymbol} {geneFullName}

 ',
//				'Experiment: {datasetShortName}, {datasetName}

',
//				'Factor: {factorCategory} - {factorDescription}

 ',
//				'Log2 fold change: {foldChange:sciNotation}
',
//				'pValue: {contrastPvalue:sciNotation}
',
//				'</tpl>',
				'<tpl if="type==\'cell\'">',		 //cell
				'Gene: {geneSymbol} {geneFullName}
',
				'Experiment: {datasetShortName}, {datasetName}
',
				'Condition: {contrastFactorValue} vs {baselineFactorValue} ({factorCategory})
',
				'Baseline: {baselineFactorValue}
',
				'Number of probes: {numberOfProbesDiffExpressed} / {numberOfProbes}
',
				'p-value: {pvalue:sciNotation}
',
				'log fold change: {foldChange:sciNotation}',
				'</tpl>', '</tpl>');
	},

	onRender: function() {
		Gemma.Metaheatmap.HoverWindow.superclass.onRender.apply ( this, arguments );
	}

});

Ext.reg('Metaheatmap.HoverWindow',Gemma.Metaheatmap.HoverWindow);
<|endoftext|>


<commit_before>/*
 * grunt-escher
 * https://github.com/goodybag/grunt-escher
 *
 * Copyright (c) 2013 John Fawcett
 * Licensed under the MIT license.
 */

var escher = require('escher');

module.exports = function(grunt){
  grunt.registerTask('escher', 'Compile Escher project', function(){
    var done = this.async();

    escher({
      appPath: this.appPath
    , outputDir: this.outputDir
    , silent: this.silent === "undefined" ? true : this.silent
    , optimize: true
    }, function(error){
      // Done is passed a boolean indicating whether or not the task was successful
      done(!error);
    });
  });
};
<commit_msg>added task<commit_after>/*
 * grunt-escher
 * https://github.com/goodybag/grunt-escher
 *
 * Copyright (c) 2013 John Fawcett
 * Licensed under the MIT license.
 */

var escher = require('escher');

module.exports = function(grunt){
  grunt.registerTask('escher', 'Compile Escher project', function(){
    var done = this.async();

    escher({
      appPath:    this.appPath
    , outputDir:  this.outputDir
    , silent:     this.silent === "undefined" ? true : this.silent
    , optimize:   true
    }, function(error){
      // Done is passed a boolean indicating whether or not the task was successful
      done(!error);
    });
  });
};
<|endoftext|>


<commit_before>/**
 * Posts
 *
 * for PostsController
 */
var Posts = {};

/**
 * functions to execute when document is ready
 *
 * only for PagesController
 *
 * @return void
 */
Posts.documentReady = function() {
    Posts.search();
}

/**
 * Submits form for searching Pages
 *
 * @return void
 */
Posts.search = function() {

    $('#AdminSearchForm').submit(function() {
        var q = '';

        //query string
        if ($('#PostQ').val() != '') {
            q = $('#PostQ').val();
        }
        var loadUrl = Hurad.basePath + 'admin/posts/index';
        if (q != '') {
            loadUrl += '/q:' + q;
        }

        window.location = loadUrl;
        return false;
    });
}

/**
 * Sortable widget in posts admin
 *
 * @return void
 */
Posts.widget = function() {
    $(function() {
        $(".column").sortable({
            connectWith: ".column"
        });
        $(".portlet").find(".portlet-header")
                .prepend("")
                .end()
                .find(".portlet-content");
        $(".portlet-header .ui-icon").click(function() {
            $(this).toggleClass("ui-icon-minusthick").toggleClass("ui-icon-plusthick");
            $(this).parents(".portlet:first").find(".portlet-content").toggle();
        });
        //$(".column").disableSelection();
    });
}

Posts.tag_autocomplete = function() {
    $(function() {
        function split(val) {
            return val.split(/,\s*/);
        }
        function extractLast(term) {
            return split(term).pop();
        }
        $("#PostTags")
                // don't navigate away from the field on tab when selecting an item
                .bind("keydown", function(event) {
            if (event.keyCode === $.ui.keyCode.TAB &&
                    $(this).data("autocomplete").menu.active) {
                event.preventDefault();
            }
        })
                .autocomplete({
            source: function(request, response) {
                $.getJSON(Hurad.basePath + "tags/index.json", {
                    term: extractLast(request.term)
                }, response);
            },
            search: function() {
                // custom minLength
                var term = extractLast(this.value);
                if (term.length < 2) {
                    return false;
                }
            },
            focus: function() {
                // prevent value inserted on focus
                return false;
            },
            select: function(event, ui) {
                var terms = split(this.value);
                // remove the current input
                terms.pop();
                // add the selected item
                terms.push(ui.item.value);
                // add placeholder to get the comma-and-space at the end
                terms.push("");
                this.value = terms.join(", ");
                return false;
            }
        });
    });
}

/**
 * document ready
 *
 * @return void
 */
$(document).ready(function() {
    if (Hurad.params.controller == 'posts') {
        Posts.documentReady();
        if (Hurad.params.action == 'admin_add', 'admin_edit') {
            Posts.widget();
            Posts.tag_autocomplete();
        }
    }
});
<commit_msg>Change it sortable<commit_after>/**
 * Posts
 *
 * for PostsController
 */
var Posts = {};

/**
 * functions to execute when document is ready
 *
 * only for PagesController
 *
 * @return void
 */
Posts.documentReady = function() {
    Posts.search();
}

/**
 * Submits form for searching Pages
 *
 * @return void
 */
Posts.search = function() {

    $('#AdminSearchForm').submit(function() {
        var q = '';

        //query string
        if ($('#PostQ').val() != '') {
            q = $('#PostQ').val();
        }
        var loadUrl = Hurad.basePath + 'admin/posts/index';
        if (q != '') {
            loadUrl += '/q:' + q;
        }

        window.location = loadUrl;
        return false;
    });
}

/**
 * Sortable widget in posts admin
 *
 * @return void
 */
Posts.widget = function() {
    $(function() {
        $(".column").sortable({
            connectWith: ".column",
            placeholder: "ui-sortable-placeholder",
            forcePlaceholderSize: true,
            start: function(e, ui) {
                ui.placeholder.height(ui.item.height());
            }
        });
        $(".portlet").find(".portlet-header")
                .prepend("")
                .end()
                .find(".portlet-content");
        $(".portlet-header .ui-icon").click(function() {
            $(this).toggleClass("ui-icon-minusthick").toggleClass("ui-icon-plusthick");
            $(this).parents(".portlet:first").find(".portlet-content").toggle();
        });
        //$(".column").disableSelection();
    });
}

Posts.tag_autocomplete = function() {
    $(function() {
        function split(val) {
            return val.split(/,\s*/);
        }
        function extractLast(term) {
            return split(term).pop();
        }
        $("#PostTags")
                // don't navigate away from the field on tab when selecting an item
                .bind("keydown", function(event) {
            if (event.keyCode === $.ui.keyCode.TAB &&
                    $(this).data("autocomplete").menu.active) {
                event.preventDefault();
            }
        })
                .autocomplete({
            source: function(request, response) {
                $.getJSON(Hurad.basePath + "tags/index.json", {
                    term: extractLast(request.term)
                }, response);
            },
            search: function() {
                // custom minLength
                var term = extractLast(this.value);
                if (term.length < 2) {
                    return false;
                }
            },
            focus: function() {
                // prevent value inserted on focus
                return false;
            },
            select: function(event, ui) {
                var terms = split(this.value);
                // remove the current input
                terms.pop();
                // add the selected item
                terms.push(ui.item.value);
                // add placeholder to get the comma-and-space at the end
                terms.push("");
                this.value = terms.join(", ");
                return false;
            }
        });
    });
}

/**
 * document ready
 *
 * @return void
 */
$(document).ready(function() {
    if (Hurad.params.controller == 'posts') {
        Posts.documentReady();
        if (Hurad.params.action == 'admin_add', 'admin_edit') {
            Posts.widget();
            Posts.tag_autocomplete();
        }
    }
});
<|endoftext|>


<commit_before>import { actionTypes } from '../actions';
import getTags         from './get_tags';
import getLatest       from './get_latest';
import getTimeline     from './get_timeline';
import getDirectory    from './get_directory';
import getPaper        from './get_paper';

var appReducer = (state = {}, action) => {
    switch (action.type) {
        case actionTypes.GET_TAGS:
            return getTags(state, action);

        case actionTypes.GET_LATEST:
            return getLatest(state, action);

        case actionTypes.GET_TIMELINE:
            return getTimeline(state, action);

        case actionTypes.GET_DIRECTORY:
            return getDirectory(state, action);

        case actionTypes.GET_PAPER:
            return getPaper(state, action);

        default:
            return state;
    }
};

export default appReducer;
/* 原本还预想用redux来搭配使用的，好像和路由冲突了，没辙了，暂时先把redux放置一边了 */
/*
    data struct:
        {
            tags: [
                {
                    tagName    : 'tag name',
                    paperCount : 2,
                    keyword    : 'tag name',  // same as tagName
                    keywordType: 'tag'
                },
                {...}
            ],
            latest: [
                {
                    latestName: 'paper title',
                    latestDate: '2011-11-11',
                    paperId   : '3'
                },
                {...}
            ],
            timeline: [
                {
                    timelineName: '2011-11',
                    paperCount  : 2,
                    keyword     : '2011-11',    // same as timelineName
                    keywordType : 'timeline'
                },
                {...}
            ],
            directory: [
                {
                    paperId      : 2
                    paperTitle   : 'paper title',
                    paperDate    : '2011-11-11',
                    paperTags    : 'paper tags',
                    paperOverview: 'paper overview ...'
                },
                {...}
            ],
            currentPaper: {
                paperId       : 2,
                paperTitle    : 'paper title',
                paperDate     : '2011-11-11',
                paperTags     : 'paper tags',
                paperContent  : 'paper content ...',
                prevPaperId   : 1,
                prevPaperTitle: 'paper title',
                nextPaperId   : '',
                nextPaperTitle: ''
            }
        }
*/
<commit_msg>Update index.js<commit_after>import { actionTypes } from '../actions';
import getTags         from './get_tags';
import getLatest       from './get_latest';
import getTimeline     from './get_timeline';
import getDirectory    from './get_directory';
import getPaper        from './get_paper';

var appReducer = (state, action) => {
    switch (action.type) {
        case actionTypes.GET_TAGS:
            return getTags(state, action);

        case actionTypes.GET_LATEST:
            return getLatest(state, action);

        case actionTypes.GET_TIMELINE:
            return getTimeline(state, action);

        case actionTypes.GET_DIRECTORY:
            return getDirectory(state, action);

        case actionTypes.GET_PAPER:
            return getPaper(state, action);

        default:
            return state;
    }
};

export default appReducer;
/* 原本还预想用redux来搭配使用的，好像和路由冲突了，没辙了，暂时先把redux放置一边了 */
/*
    data struct:
        {
            tags: [
                {
                    tagName    : 'tag name',
                    paperCount : 2,
                    keyword    : 'tag name',  // same as tagName
                    keywordType: 'tag'
                },
                {...}
            ],
            latest: [
                {
                    latestName: 'paper title',
                    latestDate: '2011-11-11',
                    paperId   : '3'
                },
                {...}
            ],
            timeline: [
                {
                    timelineName: '2011-11',
                    paperCount  : 2,
                    keyword     : '2011-11',    // same as timelineName
                    keywordType : 'timeline'
                },
                {...}
            ],
            directory: [
                {
                    paperId      : 2
                    paperTitle   : 'paper title',
                    paperDate    : '2011-11-11',
                    paperTags    : 'paper tags',
                    paperOverview: 'paper overview ...'
                },
                {...}
            ],
            currentPaper: {
                paperId       : 2,
                paperTitle    : 'paper title',
                paperDate     : '2011-11-11',
                paperTags     : 'paper tags',
                paperContent  : 'paper content ...',
                prevPaperId   : 1,
                prevPaperTitle: 'paper title',
                nextPaperId   : '',
                nextPaperTitle: ''
            }
        }
*/
<|endoftext|>


<commit_before>(function (env) {
    "use strict";
    env.ddg_spice_package_tracking = function(api_result){
        if (!api_result || api_result.error) {
            return Spice.failed('package_tracking');
        }
        Spice.add({
            id: "package_tracking",
            name: "Answer",
            data: {
                title: api_result.status_description,
                subtitle: api_result.location,
                description: "Last update: " + DDG.getDateFromString(api_result.progress_at),
                image: DDG.get_asset_path('package_tracking', 'logos/' + api_result.c + '.png'),
                infoboxData: [
                    {
                        heading: "Info shipping"
                    },
                    {
                        label: "Shipped at: ",
                        value: DDG.getDateFromString(api_result.shipped_at)
                    },
                    {
                        label: "Scheduled delivery at: ",
                        value: DDG.getDateFromString(api_result.est_delivery_at)
                    },
                    {
                        label: "Delivery at: ",
                        value: DDG.getDateFromString(api_result.act_delivery_at)
                    },
                ]
            },
            templates: {
                group: 'info',
            }
        });
    };
}(this));
<commit_msg>fix null value and ups-package logo<commit_after>(function (env) {
    "use strict";
    env.ddg_spice_package_tracking = function(api_result){
        if (!api_result || api_result.error) {
            return Spice.failed('package_tracking');
        }
        var logo = api_result.c;
        if (logo == 'ups-packages') {
            logo = 'ups';
        }
        Spice.add({
            id: "package_tracking",
            name: "Answer",
            data: {
                title: api_result.status_description,
                subtitle: api_result.location,
                description: "Last update: " + DDG.getDateFromString(api_result.progress_at),
                image: DDG.get_asset_path('package_tracking', 'logos/' + logo + '.png'),
                infoboxData: [
                    {
                        heading: "Info shipping"
                    },
                    {
                        label: "Shipped at: ",
                        value: api_result.shipped_at != null ? DDG.getDateFromString(api_result.shipped_at) : ""
                    },
                    {
                        label: "Scheduled delivery at: ",
                        value: api_result.est_delivery_at != null ? DDG.getDateFromString(api_result.est_delivery_at) : ""
                    },
                    {
                        label: "Delivery at: ",
                        value:  api_result.act_delivery_at != null ? DDG.getDateFromString(api_result.act_delivery_at) : ""
                    },
                ]
            },
            templates: {
                group: 'info',
            }
        });
    };
}(this));
<|endoftext|>