<commit_before>/*
 Copyright (c) 2012, Yahoo! Inc.  All rights reserved.
 Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
 */
var Module = require('module'),
    path = require('path'),
    fs = require('fs'),
    nopt = require('nopt'),
    which = require('which'),
    mkdirp = require('mkdirp'),
    existsSync = fs.existsSync || path.existsSync,
    inputError = require('../../util/input-error'),
    matcherFor = require('../../util/file-matcher').matcherFor,
    Instrumenter = require('../../instrumenter'),
    Collector = require('../../collector'),
    formatOption = require('../../util/help-formatter').formatOption,
    hook = require('../../hook'),
    Reporter = require('../../reporter'),
    resolve = require('resolve'),
    configuration = require('../../config');

function usage(arg0, command) {

    console.error('\nUsage: ' + arg0 + ' ' + command + ' [<options>] <executable-js-file-or-command> [-- <arguments-to-jsfile>]\n\nOptions are:\n\n'
        + [
            formatOption('--config <path-to-config>', 'the configuration file to use, defaults to .istanbul.yml'),
            formatOption('--root <path> ', 'the root path to look for files to instrument, defaults to .'),
            formatOption('-x <exclude-pattern> [-x <exclude-pattern>]', 'one or more fileset patterns e.g. "**/vendor/**"'),
            formatOption('-i <include-pattern> [-i <include-pattern>]', 'one or more fileset patterns e.g. "**/*.js"'),
            formatOption('--[no-]default-excludes', 'apply default excludes [ **/node_modules/**, **/test/**, **/tests/** ], defaults to true'),
            formatOption('--hook-run-in-context', 'hook vm.runInThisContext in addition to require (supports RequireJS), defaults to false'),
            formatOption('--post-require-hook <file> | <module>', 'JS module that exports a function for post-require processing'),
            formatOption('--report <format> [--report <format>] ', 'report format, defaults to lcov (= lcov.info + HTML)'),
            formatOption('--dir <report-dir>', 'report directory, defaults to ./coverage'),
            formatOption('--print <type>', 'type of report to print to console, one of summary (default), detail, both or none'),
            formatOption('--verbose, -v', 'verbose mode'),
            formatOption('--[no-]preserve-comments', 'remove / preserve comments in the output, defaults to false'),
            formatOption('--include-all-sources', 'instrument all unused sources after running tests, defaults to false'),
            formatOption('--[no-]include-pid', 'include PID in output coverage filename')
        ].join('\n\n') + '\n');
    console.error('\n');
}

function run(args, commandName, enableHooks, callback) {

    var template = {
            config: path,
            root: path,
            x: [ Array, String ],
            report: [Array, String ],
            dir: path,
            verbose: Boolean,
            yui: Boolean,
            'default-excludes': Boolean,
            print: String,
            'self-test': Boolean,
            'hook-run-in-context': Boolean,
            'post-require-hook': String,
            'preserve-comments': Boolean,
            'include-all-sources': Boolean,
            'preload-sources': Boolean,
            i: [ Array, String ],
            'include-pid': Boolean
        },
        opts = nopt(template, { v : '--verbose' }, args, 0),
        overrides = {
            verbose: opts.verbose,
            instrumentation: {
                root: opts.root,
                'default-excludes': opts['default-excludes'],
                excludes: opts.x,
                'include-all-sources': opts['include-all-sources'],
                'preload-sources': opts['preload-sources'],
                'include-pid': opts['include-pid']
            },
            reporting: {
                reports: opts.report,
                print: opts.print,
                dir: opts.dir
            },
            hooks: {
                'hook-run-in-context': opts['hook-run-in-context'],
                'post-require-hook': opts['post-require-hook'],
                'handle-sigint': opts['handle-sigint']
            }
        },
        config = configuration.loadFile(opts.config, overrides),
        verbose = config.verbose,
        cmdAndArgs = opts.argv.remain,
        preserveComments = opts['preserve-comments'],
        includePid = opts['include-pid'],
        cmd,
        cmdArgs,
        reportingDir,
        reporter = new Reporter(config),
        runFn,
        excludes;

    if (cmdAndArgs.length === 0) {
        return callback(inputError.create('Need a filename argument for the ' + commandName + ' command!'));
    }

    cmd = cmdAndArgs.shift();
    cmdArgs = cmdAndArgs;

    if (!existsSync(cmd)) {
        try {
            cmd = which.sync(cmd);
        } catch (ex) {
            return callback(inputError.create('Unable to resolve file [' + cmd + ']'));
        }
    } else {
        cmd = path.resolve(cmd);
    }

    runFn = function () {
        process.argv = ["node", cmd].concat(cmdArgs);
        if (verbose) {
            console.log('Running: ' + process.argv.join(' '));
        }
        process.env.running_under_istanbul=1;
        Module.runMain(cmd, null, true);
    };

    excludes = config.instrumentation.excludes(true);

    if (enableHooks) {
        reportingDir = path.resolve(config.reporting.dir());
        mkdirp.sync(reportingDir); //ensure we fail early if we cannot do this
        reporter.addAll(config.reporting.reports());
        if (config.reporting.print() !== 'none') {
            switch (config.reporting.print()) {
            case 'detail':
                reporter.add('text');
                break;
            case 'both':
                reporter.add('text');
                reporter.add('text-summary');
                break;
            default:
                reporter.add('text-summary');
                break;
            }
        }

        excludes.push(path.relative(process.cwd(), path.join(reportingDir, '**', '*')));
        matcherFor({
            root: config.instrumentation.root() || process.cwd(),
            includes: opts.i || config.instrumentation.extensions().map(function (ext) {
                return '**/*' + ext;
            }),
            excludes: excludes
        },
            function (err, matchFn) {
                if (err) { return callback(err); }

                var coverageVar = '$$cov_' + new Date().getTime() + '$$',
                    instrumenter = new Instrumenter({ coverageVariable: coverageVar , preserveComments: preserveComments}),
                    transformer = instrumenter.instrumentSync.bind(instrumenter),
                    hookOpts = { verbose: verbose, extensions: config.instrumentation.extensions() },
                    postRequireHook = config.hooks.postRequireHook(),
                    postLoadHookFile;

                if (postRequireHook) {
                    postLoadHookFile = path.resolve(postRequireHook);
                } else if (opts.yui) { //EXPERIMENTAL code: do not rely on this in anyway until the docs say it is allowed
                    postLoadHookFile = path.resolve(__dirname, '../../util/yui-load-hook');
                }

                if (postRequireHook) {
                    if (!existsSync(postLoadHookFile)) { //assume it is a module name and resolve it
                        try {
                            postLoadHookFile = resolve.sync(postRequireHook, { basedir: process.cwd() });
                        } catch (ex) {
                            if (verbose) { console.error('Unable to resolve [' + postRequireHook + '] as a node module'); }
                            callback(ex);
                            return;
                        }
                    }
                }
                if (postLoadHookFile) {
                    if (verbose) { console.error('Use post-load-hook: ' + postLoadHookFile); }
                    hookOpts.postLoadHook = require(postLoadHookFile)(matchFn, transformer, verbose);
                }

                if (opts['self-test']) {
                    hook.unloadRequireCache(matchFn);
                }
                // runInThisContext is used by RequireJS [issue #23]
                if (config.hooks.hookRunInContext()) {
                    hook.hookRunInThisContext(matchFn, transformer, hookOpts);
                }
                hook.hookRequire(matchFn, transformer, hookOpts);

                //initialize the global variable to stop mocha from complaining about leaks
                global[coverageVar] = {};

                // enable passing --handle-sigint to write reports on SIGINT.
                // This allows a user to manually kill a process while
                // still getting the istanbul report.
                if (config.hooks.handleSigint()) {
                    process.once('SIGINT', process.exit);
                }

                process.once('exit', function () {
                    var pidExt = includePid ? ('-' + process.pid) : '',
                        file = path.resolve(reportingDir, 'coverage' + pidExt + '.json'),
                        collector,
                        cov;
                    if (typeof global[coverageVar] === 'undefined' || Object.keys(global[coverageVar]).length === 0) {
                        console.error('No coverage information was collected, exit without writing coverage information');
                        return;
                    } else {
                        cov = global[coverageVar];
                    }
                    //important: there is no event loop at this point
                    //everything that happens in this exit handler MUST be synchronous
                    if (config.instrumentation.includeAllSources()) {
                        // Files that are not touched by code ran by the test runner is manually instrumented, to
                        // illustrate the missing coverage.
                        matchFn.files.forEach(function (file) {
                            if (!cov[file]) {
                                transformer(fs.readFileSync(file, 'utf-8'), file);

                                // When instrumenting the code, istanbul will give each FunctionDeclaration a value of 1 in coverState.s,
                                // presumably to compensate for function hoisting. We need to reset this, as the function was not hoisted,
                                // as it was never loaded.
                                Object.keys(instrumenter.coverState.s).forEach(function (key) {
                                    instrumenter.coverState.s[key] = 0;
                                });

                                cov[file] = instrumenter.coverState;
                            }
                        });
                    }
                    mkdirp.sync(reportingDir); //yes, do this again since some test runners could clean the dir initially created
                    if (config.reporting.print() !== 'none') {
                        console.error('=============================================================================');
                        console.error('Writing coverage object [' + file + ']');
                    }
                    fs.writeFileSync(file, JSON.stringify(cov), 'utf8');
                    collector = new Collector();
                    collector.add(cov);
                    if (config.reporting.print() !== 'none') {
                        console.error('Writing coverage reports at [' + reportingDir + ']');
                        console.error('=============================================================================');
                    }
                    reporter.write(collector, true, callback);
                });
                runFn();
            });
    } else {
        runFn();
    }
}

module.exports = {
    run: run,
    usage: usage
};
<commit_msg>When setting up the `reportDir` add it to `reporter.dir`<commit_after>/*
 Copyright (c) 2012, Yahoo! Inc.  All rights reserved.
 Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
 */
var Module = require('module'),
    path = require('path'),
    fs = require('fs'),
    nopt = require('nopt'),
    which = require('which'),
    mkdirp = require('mkdirp'),
    existsSync = fs.existsSync || path.existsSync,
    inputError = require('../../util/input-error'),
    matcherFor = require('../../util/file-matcher').matcherFor,
    Instrumenter = require('../../instrumenter'),
    Collector = require('../../collector'),
    formatOption = require('../../util/help-formatter').formatOption,
    hook = require('../../hook'),
    Reporter = require('../../reporter'),
    resolve = require('resolve'),
    configuration = require('../../config');

function usage(arg0, command) {

    console.error('\nUsage: ' + arg0 + ' ' + command + ' [<options>] <executable-js-file-or-command> [-- <arguments-to-jsfile>]\n\nOptions are:\n\n'
        + [
            formatOption('--config <path-to-config>', 'the configuration file to use, defaults to .istanbul.yml'),
            formatOption('--root <path> ', 'the root path to look for files to instrument, defaults to .'),
            formatOption('-x <exclude-pattern> [-x <exclude-pattern>]', 'one or more fileset patterns e.g. "**/vendor/**"'),
            formatOption('-i <include-pattern> [-i <include-pattern>]', 'one or more fileset patterns e.g. "**/*.js"'),
            formatOption('--[no-]default-excludes', 'apply default excludes [ **/node_modules/**, **/test/**, **/tests/** ], defaults to true'),
            formatOption('--hook-run-in-context', 'hook vm.runInThisContext in addition to require (supports RequireJS), defaults to false'),
            formatOption('--post-require-hook <file> | <module>', 'JS module that exports a function for post-require processing'),
            formatOption('--report <format> [--report <format>] ', 'report format, defaults to lcov (= lcov.info + HTML)'),
            formatOption('--dir <report-dir>', 'report directory, defaults to ./coverage'),
            formatOption('--print <type>', 'type of report to print to console, one of summary (default), detail, both or none'),
            formatOption('--verbose, -v', 'verbose mode'),
            formatOption('--[no-]preserve-comments', 'remove / preserve comments in the output, defaults to false'),
            formatOption('--include-all-sources', 'instrument all unused sources after running tests, defaults to false'),
            formatOption('--[no-]include-pid', 'include PID in output coverage filename')
        ].join('\n\n') + '\n');
    console.error('\n');
}

function run(args, commandName, enableHooks, callback) {

    var template = {
            config: path,
            root: path,
            x: [ Array, String ],
            report: [Array, String ],
            dir: path,
            verbose: Boolean,
            yui: Boolean,
            'default-excludes': Boolean,
            print: String,
            'self-test': Boolean,
            'hook-run-in-context': Boolean,
            'post-require-hook': String,
            'preserve-comments': Boolean,
            'include-all-sources': Boolean,
            'preload-sources': Boolean,
            i: [ Array, String ],
            'include-pid': Boolean
        },
        opts = nopt(template, { v : '--verbose' }, args, 0),
        overrides = {
            verbose: opts.verbose,
            instrumentation: {
                root: opts.root,
                'default-excludes': opts['default-excludes'],
                excludes: opts.x,
                'include-all-sources': opts['include-all-sources'],
                'preload-sources': opts['preload-sources'],
                'include-pid': opts['include-pid']
            },
            reporting: {
                reports: opts.report,
                print: opts.print,
                dir: opts.dir
            },
            hooks: {
                'hook-run-in-context': opts['hook-run-in-context'],
                'post-require-hook': opts['post-require-hook'],
                'handle-sigint': opts['handle-sigint']
            }
        },
        config = configuration.loadFile(opts.config, overrides),
        verbose = config.verbose,
        cmdAndArgs = opts.argv.remain,
        preserveComments = opts['preserve-comments'],
        includePid = opts['include-pid'],
        cmd,
        cmdArgs,
        reportingDir,
        reporter = new Reporter(config),
        runFn,
        excludes;

    if (cmdAndArgs.length === 0) {
        return callback(inputError.create('Need a filename argument for the ' + commandName + ' command!'));
    }

    cmd = cmdAndArgs.shift();
    cmdArgs = cmdAndArgs;

    if (!existsSync(cmd)) {
        try {
            cmd = which.sync(cmd);
        } catch (ex) {
            return callback(inputError.create('Unable to resolve file [' + cmd + ']'));
        }
    } else {
        cmd = path.resolve(cmd);
    }

    runFn = function () {
        process.argv = ["node", cmd].concat(cmdArgs);
        if (verbose) {
            console.log('Running: ' + process.argv.join(' '));
        }
        process.env.running_under_istanbul=1;
        Module.runMain(cmd, null, true);
    };

    excludes = config.instrumentation.excludes(true);

    if (enableHooks) {
        reportingDir = path.resolve(config.reporting.dir());
        mkdirp.sync(reportingDir); //ensure we fail early if we cannot do this
        reporter.dir = reportingDir;
        reporter.addAll(config.reporting.reports());
        if (config.reporting.print() !== 'none') {
            switch (config.reporting.print()) {
            case 'detail':
                reporter.add('text');
                break;
            case 'both':
                reporter.add('text');
                reporter.add('text-summary');
                break;
            default:
                reporter.add('text-summary');
                break;
            }
        }

        excludes.push(path.relative(process.cwd(), path.join(reportingDir, '**', '*')));
        matcherFor({
            root: config.instrumentation.root() || process.cwd(),
            includes: opts.i || config.instrumentation.extensions().map(function (ext) {
                return '**/*' + ext;
            }),
            excludes: excludes
        },
            function (err, matchFn) {
                if (err) { return callback(err); }

                var coverageVar = '$$cov_' + new Date().getTime() + '$$',
                    instrumenter = new Instrumenter({ coverageVariable: coverageVar , preserveComments: preserveComments}),
                    transformer = instrumenter.instrumentSync.bind(instrumenter),
                    hookOpts = { verbose: verbose, extensions: config.instrumentation.extensions() },
                    postRequireHook = config.hooks.postRequireHook(),
                    postLoadHookFile;

                if (postRequireHook) {
                    postLoadHookFile = path.resolve(postRequireHook);
                } else if (opts.yui) { //EXPERIMENTAL code: do not rely on this in anyway until the docs say it is allowed
                    postLoadHookFile = path.resolve(__dirname, '../../util/yui-load-hook');
                }

                if (postRequireHook) {
                    if (!existsSync(postLoadHookFile)) { //assume it is a module name and resolve it
                        try {
                            postLoadHookFile = resolve.sync(postRequireHook, { basedir: process.cwd() });
                        } catch (ex) {
                            if (verbose) { console.error('Unable to resolve [' + postRequireHook + '] as a node module'); }
                            callback(ex);
                            return;
                        }
                    }
                }
                if (postLoadHookFile) {
                    if (verbose) { console.error('Use post-load-hook: ' + postLoadHookFile); }
                    hookOpts.postLoadHook = require(postLoadHookFile)(matchFn, transformer, verbose);
                }

                if (opts['self-test']) {
                    hook.unloadRequireCache(matchFn);
                }
                // runInThisContext is used by RequireJS [issue #23]
                if (config.hooks.hookRunInContext()) {
                    hook.hookRunInThisContext(matchFn, transformer, hookOpts);
                }
                hook.hookRequire(matchFn, transformer, hookOpts);

                //initialize the global variable to stop mocha from complaining about leaks
                global[coverageVar] = {};

                // enable passing --handle-sigint to write reports on SIGINT.
                // This allows a user to manually kill a process while
                // still getting the istanbul report.
                if (config.hooks.handleSigint()) {
                    process.once('SIGINT', process.exit);
                }

                process.once('exit', function () {
                    var pidExt = includePid ? ('-' + process.pid) : '',
                        file = path.resolve(reportingDir, 'coverage' + pidExt + '.json'),
                        collector,
                        cov;
                    if (typeof global[coverageVar] === 'undefined' || Object.keys(global[coverageVar]).length === 0) {
                        console.error('No coverage information was collected, exit without writing coverage information');
                        return;
                    } else {
                        cov = global[coverageVar];
                    }
                    //important: there is no event loop at this point
                    //everything that happens in this exit handler MUST be synchronous
                    if (config.instrumentation.includeAllSources()) {
                        // Files that are not touched by code ran by the test runner is manually instrumented, to
                        // illustrate the missing coverage.
                        matchFn.files.forEach(function (file) {
                            if (!cov[file]) {
                                transformer(fs.readFileSync(file, 'utf-8'), file);

                                // When instrumenting the code, istanbul will give each FunctionDeclaration a value of 1 in coverState.s,
                                // presumably to compensate for function hoisting. We need to reset this, as the function was not hoisted,
                                // as it was never loaded.
                                Object.keys(instrumenter.coverState.s).forEach(function (key) {
                                    instrumenter.coverState.s[key] = 0;
                                });

                                cov[file] = instrumenter.coverState;
                            }
                        });
                    }
                    mkdirp.sync(reportingDir); //yes, do this again since some test runners could clean the dir initially created
                    if (config.reporting.print() !== 'none') {
                        console.error('=============================================================================');
                        console.error('Writing coverage object [' + file + ']');
                    }
                    fs.writeFileSync(file, JSON.stringify(cov), 'utf8');
                    collector = new Collector();
                    collector.add(cov);
                    if (config.reporting.print() !== 'none') {
                        console.error('Writing coverage reports at [' + reportingDir + ']');
                        console.error('=============================================================================');
                    }
                    reporter.write(collector, true, callback);
                });
                runFn();
            });
    } else {
        runFn();
    }
}

module.exports = {
    run: run,
    usage: usage
};
<|endoftext|>


<commit_before>import { navigator, window, document } from 'global';
import React from 'react';
import ReactDOM from 'react-dom';
import deprecate from 'util-deprecate';
import AnsiToHtml from 'ansi-to-html';

import addons from '@storybook/addons';
import createChannel from '@storybook/channel-postmessage';
import { ClientApi, StoryStore, ConfigApi } from '@storybook/client-api';
import { toId, storyNameFromExport } from '@storybook/router/utils';
import { logger } from '@storybook/client-logger';
import Events from '@storybook/core-events';

import { initializePath, setPath } from './url';
import { NoDocs } from './NoDocs';

const ansiConverter = new AnsiToHtml();

const classes = {
  MAIN: 'sb-show-main',
  NOPREVIEW: 'sb-show-nopreview',
  ERROR: 'sb-show-errordisplay',
};

function matches(storyKey, arrayOrRegex) {
  if (Array.isArray(arrayOrRegex)) {
    return arrayOrRegex.includes(storyKey);
  }
  return storyKey.match(arrayOrRegex);
}

export function isExportStory(key, { includeStories, excludeStories }) {
  return (
    // https://babeljs.io/docs/en/babel-plugin-transform-modules-commonjs
    key !== '__esModule' &&
    (!includeStories || matches(key, includeStories)) &&
    (!excludeStories || !matches(key, excludeStories))
  );
}

function showMain() {
  document.body.classList.remove(classes.NOPREVIEW);
  document.body.classList.remove(classes.ERROR);

  document.body.classList.add(classes.MAIN);
}

function showNopreview() {
  document.body.classList.remove(classes.MAIN);
  document.body.classList.remove(classes.ERROR);

  document.body.classList.add(classes.NOPREVIEW);
}

function showErrorDisplay({ message = '', stack = '' }) {
  document.getElementById('error-message').innerHTML = ansiConverter.toHtml(message);
  document.getElementById('error-stack').innerHTML = ansiConverter.toHtml(stack);

  document.body.classList.remove(classes.MAIN);
  document.body.classList.remove(classes.NOPREVIEW);

  document.body.classList.add(classes.ERROR);
}

// showError is used by the various app layers to inform the user they have done something
// wrong -- for instance returned the wrong thing from a story
function showError({ title, description }) {
  addons.getChannel().emit(Events.STORY_ERRORED, { title, description });
  showErrorDisplay({
    message: title,
    stack: description,
  });
}

// showException is used if we fail to render the story and it is uncaught by the app layer
function showException(exception) {
  addons.getChannel().emit(Events.STORY_THREW_EXCEPTION, exception);
  showErrorDisplay(exception);

  // Log the stack to the console. So, user could check the source code.
  logger.error(exception);
}

const isBrowser =
  navigator &&
  navigator.userAgent &&
  navigator.userAgent !== 'storyshots' &&
  !(navigator.userAgent.indexOf('Node.js') > -1) &&
  !(navigator.userAgent.indexOf('jsdom') > -1);

export const getContext = (() => {
  let cache;
  return decorateStory => {
    if (cache) {
      return cache;
    }
    let channel = null;
    if (isBrowser) {
      try {
        channel = addons.getChannel();
      } catch (e) {
        channel = createChannel({ page: 'preview' });
        addons.setChannel(channel);
      }
    }
    let storyStore;
    let clientApi;
    if (typeof window !== 'undefined' && window.__STORYBOOK_CLIENT_API__) {
      clientApi = window.__STORYBOOK_CLIENT_API__;
      // eslint-disable-next-line no-underscore-dangle
      storyStore = clientApi._storyStore;
    } else {
      storyStore = new StoryStore({ channel });
      clientApi = new ClientApi({ storyStore, decorateStory });
    }
    const { clearDecorators } = clientApi;
    const configApi = new ConfigApi({ clearDecorators, storyStore, channel, clientApi });

    return {
      configApi,
      storyStore,
      channel,
      clientApi,
      showMain,
      showError,
      showException,
    };
  };
})();

function focusInInput(event) {
  return (
    /input|textarea/i.test(event.target.tagName) ||
    event.target.getAttribute('contenteditable') !== null
  );
}

export default function start(render, { decorateStory } = {}) {
  const context = getContext(decorateStory);

  const { clientApi, channel, configApi, storyStore } = context;
  // Provide access to external scripts if `window` is defined.
  // NOTE this is different to isBrowser, primarily for the JSDOM use case
  let previousKind = '';
  let previousStory = '';
  let previousRevision = -1;
  let previousViewMode = '';
  let previousId = null;

  const renderMain = forceRender => {
    const revision = storyStore.getRevision();
    const loadError = storyStore.getError();
    const { storyId, viewMode: urlViewMode } = storyStore.getSelection();

    const data = storyStore.fromId(storyId);

    const { kind, name, getDecorated, id, parameters, error } = data || {};

    const viewMode = parameters && parameters.docsOnly ? 'docs' : urlViewMode;

    const renderContext = {
      ...context,
      ...data,
      selectedKind: kind,
      selectedStory: name,
      parameters,
      forceRender,
    };

    if (loadError || error) {
      showErrorDisplay(loadError || error);
      return;
    }

    // Render story only if selectedKind or selectedStory have changed.
    // However, we DO want the story to re-render if the store itself has changed
    // (which happens at the moment when HMR occurs)
    if (
      !forceRender &&
      revision === previousRevision &&
      viewMode === previousViewMode &&
      kind === previousKind &&
      name === previousStory
    ) {
      addons.getChannel().emit(Events.STORY_UNCHANGED, {
        id,
        revision,
        kind,
        name,
        viewMode,
      });
      return;
    }

    if (!forceRender && previousKind && previousStory) {
      addons.getChannel().emit(Events.STORY_CHANGED, id);
    }

    switch (previousViewMode) {
      case 'docs':
        if (previousKind != null && (kind !== previousKind || viewMode !== previousViewMode)) {
          storyStore.cleanHooksForKind(previousKind);
        }
        break;
      case 'story':
      default:
        if (previousId != null && (id !== previousId || viewMode !== previousViewMode)) {
          storyStore.cleanHooks(previousId);
        }
    }

    // Docs view renders into a different root ID to avoid conflicts
    // with the user's view layer. Therefore we need to clean up whenever
    // we transition between view modes
    if (viewMode !== previousViewMode) {
      switch (viewMode) {
        case 'docs': {
          showMain();
          document.getElementById('root').setAttribute('hidden', true);
          document.getElementById('docs-root').removeAttribute('hidden');
          break;
        }
        case 'story':
        default: {
          if (previousViewMode === 'docs') {
            document.getElementById('docs-root').setAttribute('hidden', true);
            ReactDOM.unmountComponentAtNode(document.getElementById('docs-root'));
            document.getElementById('root').removeAttribute('hidden');
          }
        }
      }
    }
    // Given a cleaned up state, render the appropriate view mode
    switch (viewMode) {
      case 'docs': {
        const docs = (parameters && parameters.docs) || {};
        const DocsContainer = docs.container || (({ children }) => <>{children}</>);
        const Page = docs.page || NoDocs;
        ReactDOM.render(
          <DocsContainer context={renderContext}>
            <Page />
          </DocsContainer>,
          document.getElementById('docs-root'),
          () => addons.getChannel().emit(Events.DOCS_RENDERED, kind)
        );
        break;
      }
      case 'story':
      default: {
        if (getDecorated) {
          (async () => {
            try {
              await render(renderContext);
              addons.getChannel().emit(Events.STORY_RENDERED, id);
            } catch (ex) {
              showException(ex);
            }
          })();
        } else {
          showNopreview();
          addons.getChannel().emit(Events.STORY_MISSING, id);
        }
        break;
      }
    }

    previousRevision = revision;
    previousKind = kind;
    previousStory = name;
    previousViewMode = viewMode;
    previousId = id;

    if (!forceRender) {
      document.documentElement.scrollTop = 0;
    }
  };

  // initialize the UI
  const renderUI = forceRender => {
    if (isBrowser) {
      try {
        renderMain(forceRender);
      } catch (ex) {
        showException(ex);
      }
    }
  };

  const forceReRender = () => renderUI(true);

  // channel can be null in NodeJS
  if (isBrowser) {
    const deprecatedToId = deprecate(
      toId,
      `Passing name+kind to the SET_CURRENT_STORY event is deprecated, use a storyId instead`
    );

    channel.on(Events.FORCE_RE_RENDER, forceReRender);
    channel.on(Events.SET_CURRENT_STORY, ({ storyId: inputStoryId, name, kind, viewMode }) => {
      let storyId = inputStoryId;
      // For backwards compatibility
      if (!storyId) {
        if (!name || !kind) {
          throw new Error('You should pass `storyId` into SET_CURRENT_STORY');
        }
        storyId = deprecatedToId(kind, name);
      }

      storyStore.setSelection({ storyId, viewMode });
      setPath({ storyId, viewMode });
    });

    // Handle keyboard shortcuts
    window.onkeydown = event => {
      if (!focusInInput(event)) {
        // We have to pick off the keys of the event that we need on the other side
        const { altKey, ctrlKey, metaKey, shiftKey, key, code, keyCode } = event;
        channel.emit(Events.PREVIEW_KEYDOWN, {
          event: { altKey, ctrlKey, metaKey, shiftKey, key, code, keyCode },
        });
      }
    };
  }

  storyStore.on(Events.STORY_INIT, () => {
    const { storyId, viewMode } = initializePath();
    storyStore.setSelection({ storyId, viewMode });
  });

  storyStore.on(Events.STORY_RENDER, renderUI);

  if (typeof window !== 'undefined') {
    window.__STORYBOOK_CLIENT_API__ = clientApi;
    window.__STORYBOOK_STORY_STORE__ = storyStore;
    window.__STORYBOOK_ADDONS_CHANNEL__ = channel; // may not be defined
  }

  let previousExports = new Map();
  const loadStories = (loadable, framework) => () => {
    let reqs = null;
    if (Array.isArray(loadable)) {
      reqs = loadable;
    } else if (loadable.keys) {
      reqs = [loadable];
    }

    let currentExports = new Map();
    if (reqs) {
      reqs.forEach(req => {
        req.keys().forEach(filename => {
          const fileExports = req(filename);
          currentExports.set(
            fileExports,
            typeof req.resolve === 'function' ? req.resolve(filename) : null
          );
        });
      });
    } else {
      const exported = loadable();
      if (Array.isArray(exported) && !exported.find(obj => !obj.default)) {
        currentExports = new Map(exported.map(fileExports => [fileExports, null]));
      } else if (exported) {
        logger.warn(
          `Loader function passed to 'configure' should return void or an array of module exports that all contain a 'default' export. Received: ${JSON.stringify(
            exported
          )}`
        );
      }
    }

    const removed = [...previousExports.keys()].filter(exp => !currentExports.has(exp));
    removed.forEach(exp => {
      if (exp.default) {
        storyStore.removeStoryKind(exp.default.title);
      }
    });
    if (removed.length > 0) {
      storyStore.incrementRevision();
    }

    const added = [...currentExports.keys()].filter(exp => !previousExports.has(exp));
    added.forEach(fileExports => {
      // An old-style story file
      if (!fileExports.default) {
        return;
      }

      if (!fileExports.default.title) {
        throw new Error(
          `Unexpected default export without title: ${JSON.stringify(fileExports.default)}`
        );
      }

      const { default: meta, ...exports } = fileExports;
      const { title: kindName, parameters: params, decorators: decos, component } = meta;
      // We pass true here to avoid the warning about HMR. It's cool clientApi, we got this
      const kind = clientApi.storiesOf(kindName, true);

      // we should always have a framework, rest optional
      kind.addParameters({
        framework,
        component,
        fileName: currentExports.get(fileExports),
        ...params,
      });

      (decos || []).forEach(decorator => {
        kind.addDecorator(decorator);
      });

      Object.keys(exports).forEach(key => {
        if (isExportStory(key, meta)) {
          const storyFn = exports[key];
          const { name, parameters, decorators } = storyFn.story || {};
          if (parameters && parameters.decorators) {
            deprecate(() => {},
            `${kindName} => ${name || key}: story.parameters.decorators is deprecated; use story.decorators instead.`)();
          }
          const decoratorParams = decorators ? { decorators } : null;
          const displayNameParams = name ? { displayName: name } : {};
          kind.add(storyNameFromExport(key), storyFn, {
            ...parameters,
            ...decoratorParams,
            ...displayNameParams,
          });
        }
      });
    });
    previousExports = currentExports;
  };

  let loaded = false;
  /**
   * Load a collection of stories. If it has a default export, assume that it is a module-style
   * file and process its named exports as stories. If not, assume it's an old-style
   * storiesof file and require it.
   *
   * @param {*} loadable a require.context `req`, an array of `req`s, or a loader function that returns void or an array of exports
   * @param {*} m - ES module object for hot-module-reloading (HMR)
   * @param {*} framework - name of framework in use, e.g. "react"
   */
  const configure = (loadable, m, framework) => {
    if (typeof m === 'string') {
      throw new Error(
        `Invalid module '${m}'. Did you forget to pass \`module\` as the second argument to \`configure\`"?`
      );
    }
    if (m && m.hot && m.hot.dispose) {
      ({ previousExports = new Map() } = m.hot.data || {});

      m.hot.dispose(data => {
        loaded = false;
        // eslint-disable-next-line no-param-reassign
        data.previousExports = previousExports;
      });
    }
    if (loaded) {
      logger.warn('Unexpected loaded state. Did you call `load` twice?');
    }
    loaded = true;
    configApi.configure(loadStories(loadable, framework), m);
  };

  return { configure, context, clientApi, configApi, forceReRender };
}
<commit_msg>Updated storybook client preview to unmount the components when viewMode switch from story to docs<commit_after>import { navigator, window, document } from 'global';
import React from 'react';
import ReactDOM from 'react-dom';
import deprecate from 'util-deprecate';
import AnsiToHtml from 'ansi-to-html';

import addons from '@storybook/addons';
import createChannel from '@storybook/channel-postmessage';
import { ClientApi, StoryStore, ConfigApi } from '@storybook/client-api';
import { toId, storyNameFromExport } from '@storybook/router/utils';
import { logger } from '@storybook/client-logger';
import Events from '@storybook/core-events';

import { initializePath, setPath } from './url';
import { NoDocs } from './NoDocs';

const ansiConverter = new AnsiToHtml();

const classes = {
  MAIN: 'sb-show-main',
  NOPREVIEW: 'sb-show-nopreview',
  ERROR: 'sb-show-errordisplay',
};

function matches(storyKey, arrayOrRegex) {
  if (Array.isArray(arrayOrRegex)) {
    return arrayOrRegex.includes(storyKey);
  }
  return storyKey.match(arrayOrRegex);
}

export function isExportStory(key, { includeStories, excludeStories }) {
  return (
    // https://babeljs.io/docs/en/babel-plugin-transform-modules-commonjs
    key !== '__esModule' &&
    (!includeStories || matches(key, includeStories)) &&
    (!excludeStories || !matches(key, excludeStories))
  );
}

function showMain() {
  document.body.classList.remove(classes.NOPREVIEW);
  document.body.classList.remove(classes.ERROR);

  document.body.classList.add(classes.MAIN);
}

function showNopreview() {
  document.body.classList.remove(classes.MAIN);
  document.body.classList.remove(classes.ERROR);

  document.body.classList.add(classes.NOPREVIEW);
}

function showErrorDisplay({ message = '', stack = '' }) {
  document.getElementById('error-message').innerHTML = ansiConverter.toHtml(message);
  document.getElementById('error-stack').innerHTML = ansiConverter.toHtml(stack);

  document.body.classList.remove(classes.MAIN);
  document.body.classList.remove(classes.NOPREVIEW);

  document.body.classList.add(classes.ERROR);
}

// showError is used by the various app layers to inform the user they have done something
// wrong -- for instance returned the wrong thing from a story
function showError({ title, description }) {
  addons.getChannel().emit(Events.STORY_ERRORED, { title, description });
  showErrorDisplay({
    message: title,
    stack: description,
  });
}

// showException is used if we fail to render the story and it is uncaught by the app layer
function showException(exception) {
  addons.getChannel().emit(Events.STORY_THREW_EXCEPTION, exception);
  showErrorDisplay(exception);

  // Log the stack to the console. So, user could check the source code.
  logger.error(exception);
}

const isBrowser =
  navigator &&
  navigator.userAgent &&
  navigator.userAgent !== 'storyshots' &&
  !(navigator.userAgent.indexOf('Node.js') > -1) &&
  !(navigator.userAgent.indexOf('jsdom') > -1);

export const getContext = (() => {
  let cache;
  return decorateStory => {
    if (cache) {
      return cache;
    }
    let channel = null;
    if (isBrowser) {
      try {
        channel = addons.getChannel();
      } catch (e) {
        channel = createChannel({ page: 'preview' });
        addons.setChannel(channel);
      }
    }
    let storyStore;
    let clientApi;
    if (typeof window !== 'undefined' && window.__STORYBOOK_CLIENT_API__) {
      clientApi = window.__STORYBOOK_CLIENT_API__;
      // eslint-disable-next-line no-underscore-dangle
      storyStore = clientApi._storyStore;
    } else {
      storyStore = new StoryStore({ channel });
      clientApi = new ClientApi({ storyStore, decorateStory });
    }
    const { clearDecorators } = clientApi;
    const configApi = new ConfigApi({ clearDecorators, storyStore, channel, clientApi });

    return {
      configApi,
      storyStore,
      channel,
      clientApi,
      showMain,
      showError,
      showException,
    };
  };
})();

function focusInInput(event) {
  return (
    /input|textarea/i.test(event.target.tagName) ||
    event.target.getAttribute('contenteditable') !== null
  );
}

export default function start(render, { decorateStory } = {}) {
  const context = getContext(decorateStory);

  const { clientApi, channel, configApi, storyStore } = context;
  // Provide access to external scripts if `window` is defined.
  // NOTE this is different to isBrowser, primarily for the JSDOM use case
  let previousKind = '';
  let previousStory = '';
  let previousRevision = -1;
  let previousViewMode = '';
  let previousId = null;

  const renderMain = forceRender => {
    const revision = storyStore.getRevision();
    const loadError = storyStore.getError();
    const { storyId, viewMode: urlViewMode } = storyStore.getSelection();

    const data = storyStore.fromId(storyId);

    const { kind, name, getDecorated, id, parameters, error } = data || {};

    const viewMode = parameters && parameters.docsOnly ? 'docs' : urlViewMode;

    const renderContext = {
      ...context,
      ...data,
      selectedKind: kind,
      selectedStory: name,
      parameters,
      forceRender,
    };

    if (loadError || error) {
      showErrorDisplay(loadError || error);
      return;
    }

    // Render story only if selectedKind or selectedStory have changed.
    // However, we DO want the story to re-render if the store itself has changed
    // (which happens at the moment when HMR occurs)
    if (
      !forceRender &&
      revision === previousRevision &&
      viewMode === previousViewMode &&
      kind === previousKind &&
      name === previousStory
    ) {
      addons.getChannel().emit(Events.STORY_UNCHANGED, {
        id,
        revision,
        kind,
        name,
        viewMode,
      });
      return;
    }

    if (!forceRender && previousKind && previousStory) {
      addons.getChannel().emit(Events.STORY_CHANGED, id);
    }

    switch (previousViewMode) {
      case 'docs':
        if (previousKind != null && (kind !== previousKind || viewMode !== previousViewMode)) {
          storyStore.cleanHooksForKind(previousKind);
        }
        break;
      case 'story':
      default:
        if (previousId != null && (id !== previousId || viewMode !== previousViewMode)) {
          storyStore.cleanHooks(previousId);
        }
    }

    // Docs view renders into a different root ID to avoid conflicts
    // with the user's view layer. Therefore we need to clean up whenever
    // we transition between view modes
    if (viewMode !== previousViewMode) {
      ReactDOM.unmountComponentAtNode(document.getElementById('root'));

      switch (viewMode) {
        case 'docs': {
          showMain();
          document.getElementById('root').setAttribute('hidden', true);
          document.getElementById('docs-root').removeAttribute('hidden');
          break;
        }
        case 'story':
        default: {
          if (previousViewMode === 'docs') {
            document.getElementById('docs-root').setAttribute('hidden', true);
            ReactDOM.unmountComponentAtNode(document.getElementById('docs-root'));
            document.getElementById('root').removeAttribute('hidden');
          }
        }
      }
    }
    // Given a cleaned up state, render the appropriate view mode
    switch (viewMode) {
      case 'docs': {
        const docs = (parameters && parameters.docs) || {};
        const DocsContainer = docs.container || (({ children }) => <>{children}</>);
        const Page = docs.page || NoDocs;
        ReactDOM.render(
          <DocsContainer context={renderContext}>
            <Page />
          </DocsContainer>,
          document.getElementById('docs-root'),
          () => addons.getChannel().emit(Events.DOCS_RENDERED, kind)
        );
        break;
      }
      case 'story':
      default: {
        if (getDecorated) {
          (async () => {
            try {
              await render(renderContext);
              addons.getChannel().emit(Events.STORY_RENDERED, id);
            } catch (ex) {
              showException(ex);
            }
          })();
        } else {
          showNopreview();
          addons.getChannel().emit(Events.STORY_MISSING, id);
        }
        break;
      }
    }

    previousRevision = revision;
    previousKind = kind;
    previousStory = name;
    previousViewMode = viewMode;
    previousId = id;

    if (!forceRender) {
      document.documentElement.scrollTop = 0;
    }
  };

  // initialize the UI
  const renderUI = forceRender => {
    if (isBrowser) {
      try {
        renderMain(forceRender);
      } catch (ex) {
        showException(ex);
      }
    }
  };

  const forceReRender = () => renderUI(true);

  // channel can be null in NodeJS
  if (isBrowser) {
    const deprecatedToId = deprecate(
      toId,
      `Passing name+kind to the SET_CURRENT_STORY event is deprecated, use a storyId instead`
    );

    channel.on(Events.FORCE_RE_RENDER, forceReRender);
    channel.on(Events.SET_CURRENT_STORY, ({ storyId: inputStoryId, name, kind, viewMode }) => {
      let storyId = inputStoryId;
      // For backwards compatibility
      if (!storyId) {
        if (!name || !kind) {
          throw new Error('You should pass `storyId` into SET_CURRENT_STORY');
        }
        storyId = deprecatedToId(kind, name);
      }

      storyStore.setSelection({ storyId, viewMode });
      setPath({ storyId, viewMode });
    });

    // Handle keyboard shortcuts
    window.onkeydown = event => {
      if (!focusInInput(event)) {
        // We have to pick off the keys of the event that we need on the other side
        const { altKey, ctrlKey, metaKey, shiftKey, key, code, keyCode } = event;
        channel.emit(Events.PREVIEW_KEYDOWN, {
          event: { altKey, ctrlKey, metaKey, shiftKey, key, code, keyCode },
        });
      }
    };
  }

  storyStore.on(Events.STORY_INIT, () => {
    const { storyId, viewMode } = initializePath();
    storyStore.setSelection({ storyId, viewMode });
  });

  storyStore.on(Events.STORY_RENDER, renderUI);

  if (typeof window !== 'undefined') {
    window.__STORYBOOK_CLIENT_API__ = clientApi;
    window.__STORYBOOK_STORY_STORE__ = storyStore;
    window.__STORYBOOK_ADDONS_CHANNEL__ = channel; // may not be defined
  }

  let previousExports = new Map();
  const loadStories = (loadable, framework) => () => {
    let reqs = null;
    if (Array.isArray(loadable)) {
      reqs = loadable;
    } else if (loadable.keys) {
      reqs = [loadable];
    }

    let currentExports = new Map();
    if (reqs) {
      reqs.forEach(req => {
        req.keys().forEach(filename => {
          const fileExports = req(filename);
          currentExports.set(
            fileExports,
            typeof req.resolve === 'function' ? req.resolve(filename) : null
          );
        });
      });
    } else {
      const exported = loadable();
      if (Array.isArray(exported) && !exported.find(obj => !obj.default)) {
        currentExports = new Map(exported.map(fileExports => [fileExports, null]));
      } else if (exported) {
        logger.warn(
          `Loader function passed to 'configure' should return void or an array of module exports that all contain a 'default' export. Received: ${JSON.stringify(
            exported
          )}`
        );
      }
    }

    const removed = [...previousExports.keys()].filter(exp => !currentExports.has(exp));
    removed.forEach(exp => {
      if (exp.default) {
        storyStore.removeStoryKind(exp.default.title);
      }
    });
    if (removed.length > 0) {
      storyStore.incrementRevision();
    }

    const added = [...currentExports.keys()].filter(exp => !previousExports.has(exp));
    added.forEach(fileExports => {
      // An old-style story file
      if (!fileExports.default) {
        return;
      }

      if (!fileExports.default.title) {
        throw new Error(
          `Unexpected default export without title: ${JSON.stringify(fileExports.default)}`
        );
      }

      const { default: meta, ...exports } = fileExports;
      const { title: kindName, parameters: params, decorators: decos, component } = meta;
      // We pass true here to avoid the warning about HMR. It's cool clientApi, we got this
      const kind = clientApi.storiesOf(kindName, true);

      // we should always have a framework, rest optional
      kind.addParameters({
        framework,
        component,
        fileName: currentExports.get(fileExports),
        ...params,
      });

      (decos || []).forEach(decorator => {
        kind.addDecorator(decorator);
      });

      Object.keys(exports).forEach(key => {
        if (isExportStory(key, meta)) {
          const storyFn = exports[key];
          const { name, parameters, decorators } = storyFn.story || {};
          if (parameters && parameters.decorators) {
            deprecate(() => {},
            `${kindName} => ${name || key}: story.parameters.decorators is deprecated; use story.decorators instead.`)();
          }
          const decoratorParams = decorators ? { decorators } : null;
          const displayNameParams = name ? { displayName: name } : {};
          kind.add(storyNameFromExport(key), storyFn, {
            ...parameters,
            ...decoratorParams,
            ...displayNameParams,
          });
        }
      });
    });
    previousExports = currentExports;
  };

  let loaded = false;
  /**
   * Load a collection of stories. If it has a default export, assume that it is a module-style
   * file and process its named exports as stories. If not, assume it's an old-style
   * storiesof file and require it.
   *
   * @param {*} loadable a require.context `req`, an array of `req`s, or a loader function that returns void or an array of exports
   * @param {*} m - ES module object for hot-module-reloading (HMR)
   * @param {*} framework - name of framework in use, e.g. "react"
   */
  const configure = (loadable, m, framework) => {
    if (typeof m === 'string') {
      throw new Error(
        `Invalid module '${m}'. Did you forget to pass \`module\` as the second argument to \`configure\`"?`
      );
    }
    if (m && m.hot && m.hot.dispose) {
      ({ previousExports = new Map() } = m.hot.data || {});

      m.hot.dispose(data => {
        loaded = false;
        // eslint-disable-next-line no-param-reassign
        data.previousExports = previousExports;
      });
    }
    if (loaded) {
      logger.warn('Unexpected loaded state. Did you call `load` twice?');
    }
    loaded = true;
    configApi.configure(loadStories(loadable, framework), m);
  };

  return { configure, context, clientApi, configApi, forceReRender };
}
<|endoftext|>


<commit_before>// -------------------------
// CREATE APPLICATION MODULE
// -------------------------

var vinci = angular.module('vinci', []);

// -------------------------
// FILTERS
// -------------------------
vinci.filter('justName', function () {
	return function(text) {
		var newtext = text.split('/');
		return newtext[newtext.length-1];
	}
});

// -------------------------
// CONTROLLERS
// -------------------------

vinci.controller('Files', function ($scope, $http, Model, $filter) {

	var justNameController = function (url) {
		var newurl = url.split('/');
		return newurl[newurl.length-1];
	};

	// get list of all feeds with news which user is subscribed to
  $http.get( Model.searchurl + Model.current[0] ).
  success(function (data) {
    $scope.files = data.files;
    $scope.folders = data.folders;
    console.log(data.folders);
  }).
    error(function (data, status) {
      console.log(status);
    });

   // update list of files/folders based on url (folder)
   $scope.updateFiles = function (url) {

   	var nameurl = justNameController(url);
   	if ( nameurl !== ".." ) {
   		Model.current.push(nameurl);
   	} else if ( Model.current.length > 1 ) {
   		Model.current.pop();
   	}

		$http.get( Model.searchurl + Model.current.join("/") ).
	  success(function (data) {
	    $scope.files = data.files;

	    if ( Model.current.length == 1) {
	    	$scope.folders = data.folders;
	    } else {
	    	data.folders.unshift("..");
	    	$scope.folders = data.folders;
	    }
	  }).
	    error(function (data, status) {
	      console.log(status);
	    });
	};

});

// -------------------------
// DIRECTIVES
// -------------------------
vinci.directive('files', function ($timeout) {
	return function (scope, element, attrs) {
		if (scope.$last) {
			$timeout (function () {
				$('div[files] a').magnificPopup({
					type:'image',
					gallery: {
						enabled: true
					}
				});
			});
		}
	};
});

// -------------------------
// SERVICES
// -------------------------

vinci.factory('Model', function () {
	return {
		searchurl : 'http://0.0.0.0:7000/search.php?dir=', // url of API
		files : null, // hold list of files from server
		current : ["resources"] // start folder
	};
});<commit_msg>removing console log for list of folders<commit_after>// -------------------------
// CREATE APPLICATION MODULE
// -------------------------

var vinci = angular.module('vinci', []);

// -------------------------
// FILTERS
// -------------------------
vinci.filter('justName', function () {
	return function(text) {
		var newtext = text.split('/');
		return newtext[newtext.length-1];
	}
});

// -------------------------
// CONTROLLERS
// -------------------------

vinci.controller('Files', function ($scope, $http, Model, $filter) {

	var justNameController = function (url) {
		var newurl = url.split('/');
		return newurl[newurl.length-1];
	};

	// get list of all feeds with news which user is subscribed to
  $http.get( Model.searchurl + Model.current[0] ).
  success(function (data) {
    $scope.files = data.files;
    $scope.folders = data.folders;
  }).
    error(function (data, status) {
      console.log(status);
    });

   // update list of files/folders based on url (folder)
   $scope.updateFiles = function (url) {

   	var nameurl = justNameController(url);
   	if ( nameurl !== ".." ) {
   		Model.current.push(nameurl);
   	} else if ( Model.current.length > 1 ) {
   		Model.current.pop();
   	}

		$http.get( Model.searchurl + Model.current.join("/") ).
	  success(function (data) {
	    $scope.files = data.files;

	    if ( Model.current.length == 1) {
	    	$scope.folders = data.folders;
	    } else {
	    	data.folders.unshift("..");
	    	$scope.folders = data.folders;
	    }
	  }).
	    error(function (data, status) {
	      console.log(status);
	    });
	};

});

// -------------------------
// DIRECTIVES
// -------------------------
vinci.directive('files', function ($timeout) {
	return function (scope, element, attrs) {
		if (scope.$last) {
			$timeout (function () {
				$('div[files] a').magnificPopup({
					type:'image',
					gallery: {
						enabled: true
					}
				});
			});
		}
	};
});

// -------------------------
// SERVICES
// -------------------------

vinci.factory('Model', function () {
	return {
		searchurl : 'http://0.0.0.0:7000/search.php?dir=', // url of API
		files : null, // hold list of files from server
		current : ["resources"] // start folder
	};
});<|endoftext|>


<commit_before>'use strict';

function nest(root, pathArray, val) {
  var last = pathArray.pop();
  var tail = pathArray.reduce(function (acc, a) {
      if (!(a in acc)) {
        acc[a] = {};
      }
      return acc[a];
    },
    root
  );

  tail[last] = val;
}

function isStream(stream) {
	return (stream !== null
      && typeof stream === 'object'
      && typeof stream.pipe === 'function');
};

function isStreamWritable(stream) {
	return (isStream(stream)
    && stream.writable !== false
    && typeof stream._write === 'function'
    && typeof stream._writableState === 'object');
};

module.exports = {
  nest: nest,
  isStream: isStream,
  isStreamWritable: isStreamWritable
};
<commit_msg>To work with `http.ServerResponse`. As per node doc: > The response implements, but does not inherit from, the `Writable Stream` interface.<commit_after>'use strict';

function nest(root, pathArray, val) {
  var last = pathArray.pop();
  var tail = pathArray.reduce(function (acc, a) {
      if (!(a in acc)) {
        acc[a] = {};
      }
      return acc[a];
    },
    root
  );

  tail[last] = val;
}

function isStream(stream) {
	return (stream !== null
      && typeof stream === 'object'
      && typeof stream.pipe === 'function');
};

function isStreamWritable(stream) {
	return (isStream(stream)
    && stream.writable !== false);
};

module.exports = {
  nest: nest,
  isStream: isStream,
  isStreamWritable: isStreamWritable
};
<|endoftext|>


<commit_before>$.iphoneStyle = {
  defaults: {
    duration:          200,
    checkedLabel:      'ON',
    uncheckedLabel:    'OFF',
    resizeHandle:      true,
    resizeContainer:   true,
    background:        '#fff',
    containerClass:    'iPhoneCheckContainer',
    labelOnClass:      'iPhoneCheckLabelOn',
    labelOffClass:     'iPhoneCheckLabelOff',
    handleClass:       'iPhoneCheckHandle',
    handleCenterClass: 'iPhoneCheckHandleCenter',
    handleRightClass:  'iPhoneCheckHandleRight'
  }
}

var iPhoneStyle = function(selector_or_elem, options) {
  options = Object.extend(Object.clone($.iphoneStyle.defaults), options || {});

  return $$(selector_or_elem).each(function(elem) {

    if (!elem.match('input[type=checkbox]'))
      return;

    elem.setOpacity(0);
    elem.wrap('div', { 'class': options.containerClass});
    elem.insert({ 'after': '

' })
        .insert({ 'after': ''+ options.uncheckedLabel + '' })
        .insert({ 'after': '' + options.checkedLabel   + '' });

    var handle    = elem.up().down('.' + options.handleClass),
      offlabel  = elem.adjacent('.' + options.labelOffClass).first(),
      onlabel   = elem.adjacent('.' + options.labelOnClass).first(),
      container = elem.up('.' + options.containerClass);

    if (options.resizeHandle) {
      var min = (onlabel.getWidth() < offlabel.getWidth()) ? onlabel.getWidth() : offlabel.getWidth();
      handle.setStyle({width: min - 8 + 'px'});
    }
    if (options.resizeContainer) {
      var max = (onlabel.getWidth() > offlabel.getWidth()) ? onlabel.getWidth() : offlabel.getWidth();
      container.setStyle({width: max + handle.getWidth() + 12 + 'px'});
    }
    offlabel.setStyle({width: container.getWidth() - 12  + 'px'});

    var rightside = container.getWidth() - handle.getWidth() - 4;

    if (elem.checked) {
      handle.setStyle({ left: rightside + 'px' });
      onlabel.setStyle({ width: rightside + 'px' });
    } else {
      handle.setStyle({ left: 0 });
      onlabel.setStyle({ width: 0 });
    }

    container.observe('mouseup', function() {
      var is_onstate = (elem.checked);

      new Effect.Tween(null, (is_onstate) ? 1 : 0, (is_onstate) ? 0 : 1, { duration: options.duration / 1000 }, function(p) {
        handle.setStyle({ left: p * rightside + 'px' });
        onlabel.setStyle({ width: p * rightside + 'px' });
      });

      elem.writeAttribute('checked', !is_onstate);
      return false;
    });

    // Disable text selection
    [container, onlabel, offlabel, handle].invoke('observe', 'mousedown', function(e) { Event.stop(e); return false; });
    if (Prototype.Browser.IE)
      [container, onlabel, offlabel, handle].invoke('observe', 'startselect', function(e) { Event.stop(e); return false; });

  });
};<commit_msg>Support for calling iPhoneStyle with a element(s).<commit_after>$.iphoneStyle = {
  defaults: {
    duration:          200,
    checkedLabel:      'ON',
    uncheckedLabel:    'OFF',
    resizeHandle:      true,
    resizeContainer:   true,
    background:        '#fff',
    containerClass:    'iPhoneCheckContainer',
    labelOnClass:      'iPhoneCheckLabelOn',
    labelOffClass:     'iPhoneCheckLabelOff',
    handleClass:       'iPhoneCheckHandle',
    handleCenterClass: 'iPhoneCheckHandleCenter',
    handleRightClass:  'iPhoneCheckHandleRight'
  }
}

var iPhoneStyle = function(selector_or_elems, options) {
  options = Object.extend(Object.clone($.iphoneStyle.defaults), options || {});

  if (Object.isString(selector_or_elems)) {
    var elems = $$(selector_or_elems);
  } else {
    var elems = [selector_or_elems].flatten();
  }
  return elems.each(function(elem) {

    if (!elem.match('input[type=checkbox]'))
      return;

    elem.setOpacity(0);
    elem.wrap('div', { 'class': options.containerClass});
    elem.insert({ 'after': '

' })
        .insert({ 'after': ''+ options.uncheckedLabel + '' })
        .insert({ 'after': '' + options.checkedLabel   + '' });

    var handle    = elem.up().down('.' + options.handleClass),
      offlabel  = elem.adjacent('.' + options.labelOffClass).first(),
      onlabel   = elem.adjacent('.' + options.labelOnClass).first(),
      container = elem.up('.' + options.containerClass);

    if (options.resizeHandle) {
      var min = (onlabel.getWidth() < offlabel.getWidth()) ? onlabel.getWidth() : offlabel.getWidth();
      handle.setStyle({width: min - 8 + 'px'});
    }
    if (options.resizeContainer) {
      var max = (onlabel.getWidth() > offlabel.getWidth()) ? onlabel.getWidth() : offlabel.getWidth();
      container.setStyle({width: max + handle.getWidth() + 12 + 'px'});
    }
    offlabel.setStyle({width: container.getWidth() - 12  + 'px'});

    var rightside = container.getWidth() - handle.getWidth() - 4;

    if (elem.checked) {
      handle.setStyle({ left: rightside + 'px' });
      onlabel.setStyle({ width: rightside + 'px' });
    } else {
      handle.setStyle({ left: 0 });
      onlabel.setStyle({ width: 0 });
    }

    container.observe('mouseup', function() {
      var is_onstate = (elem.checked);

      new Effect.Tween(null, (is_onstate) ? 1 : 0, (is_onstate) ? 0 : 1, { duration: options.duration / 1000 }, function(p) {
        handle.setStyle({ left: p * rightside + 'px' });
        onlabel.setStyle({ width: p * rightside + 'px' });
      });

      elem.writeAttribute('checked', !is_onstate);
      return false;
    });

    // Disable text selection
    [container, onlabel, offlabel, handle].invoke('observe', 'mousedown', function(e) { Event.stop(e); return false; });
    if (Prototype.Browser.IE)
      [container, onlabel, offlabel, handle].invoke('observe', 'startselect', function(e) { Event.stop(e); return false; });

  });
};<|endoftext|>


<commit_before>// ==UserScript==
// @name         agario_bonus-tabs
// @namespace    ontando.io.agar
// @version      0.1
// @description  Adar.io Bonus tabs with data
// @author       ontando (angal)
// @match        agar.io
// @grant        GM_setClipboard
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==
if (!unsafeWindow.install) {
    unsafeWindow.install = [];
}

unsafeWindow.install.push(["ontando", "bonus-tabs", function() {
    jQuery("body").prepend(
        '
'
        + '
'
        + '
'
        + 'Ontando Blobster mod'
        + '
 '
        + 'Version : ' + this.version.main + ' (' + this.version.script + ')'
        + '
'
        + '
'
        + 'IP: None
 '
        + 'Reconnect || Change || Copy'
        + '
'
        + '
'
        + '
'
    );
    jQuery("body").prepend(
        '
'
          + '
'
            + '
'
              + 'Modules:'
              + '

'
            + '
'
          + '
'
        + '
'

        + '
'
          + '
'
            + '
'
              + 'Last servers:
 '
              + '

'
            + '
'
          + '
'
        + '
'
    );

    this.onMenuHideEvent(function(e) {
        jQuery(".ontando_bonusTabs").hide();
    });
    this.onMenuShowEvent(function(e) {
        jQuery(".ontando_bonusTabs").fadeIn(3000);
    });

    var ip = "";
    var action = this.action;
    jQuery("#angal_server_copy").click(function() {
        GM_setClipboard(ip, "text");
    });
    jQuery("#angal_server_change").click(function() {
        var name = prompt("Server Ip:", ip);
        if (name == null) {
            return;
        }
        action.connect(name);
    });
    jQuery("#angal_server_reconnect").click(function() {
        unsafeWindow.angal_connectDirect(ip);
    });
    this.onConnectingStartEvent(function(e) {
        ip = e.ip;
        jQuery("#angal_server").html(ip);
    });
    var modules = unsafeWindow.ontando.module.list;
    for (var i = 0; i < modules.length; i++) {
        var m = modules[i];
        var state = m.enabled ? "" : "";
        var newState = m.willEnabled == m.enabled ? (!m.willEnabled ? "Enable" : "Disable") : (m.willEnabled ? "Will Enabled" : "Will Disabled");
        $("#ontando_bonusTabs_moduleList").append(
            i + ") "
            + state // ""
              + m.author + ":" + m.name
              + " "
                + "["
                + "" + newState + ""
                + "]"
              + " "
            + ""
            + "
"
        );
    }
    unsafeWindow.ontando_bonusTabs_togleModule = function(id) {
        var m = modules[id];
        m.togleState();
        $("#ontando_bonusTabs_moduleList_e" + id).html(m.willEnabled == m.enabled ? (!m.willEnabled ? "Enable" : "Disable") : (m.willEnabled ? "Will Enabled" : "Will Disabled"));
    };

    this.on
}]);
<commit_msg>Modules options<commit_after>// ==UserScript==
// @name         agario_bonus-tabs
// @namespace    ontando.io.agar
// @version      0.1
// @description  Adar.io Bonus tabs with data
// @author       ontando (angal)
// @match        agar.io
// @grant        GM_setClipboard
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==
if (!unsafeWindow.install) {
    unsafeWindow.install = [];
}

unsafeWindow.install.push(["ontando", "bonus-tabs", function() {
    jQuery("body").prepend(
        '
'
        + '
'
        + '
'
        + 'Ontando Blobster mod'
        + '
 '
        + 'Version : ' + this.version.main + ' (' + this.version.script + ')'
        + '
'
        + '
'
        + 'IP: None
 '
        + 'Reconnect || Change || Copy'
        + '
'
        + '
'
        + '
'
    );
    jQuery("body").prepend(
        '
'
          + '
'
            + '
'
              + 'Modules:'
              + '

'
            + '
'
          + '
'
        + '
'

        + '
'
          + '
'
            + '
'
              + 'Options:
 '
              + 'Module: <select id="ontando_bonusTabs_module" class="form-control" onchange="ontando_bonusTabs_selectModule($(this).val());"><option selected value="-1">Global options</option></select>'
              + '

'
            + '
'
          + '
'
        + '
'
    );

    this.onMenuHideEvent(function(e) {
        jQuery(".ontando_bonusTabs").hide();
    });
    this.onMenuShowEvent(function(e) {
        jQuery(".ontando_bonusTabs").fadeIn(3000);
    });

    var ip = "";
    var action = this.action;
    jQuery("#angal_server_copy").click(function() {
        GM_setClipboard(ip, "text");
    });
    jQuery("#angal_server_change").click(function() {
        var name = prompt("Server Ip:", ip);
        if (name == null) {
            return;
        }
        action.connect(name);
    });
    jQuery("#angal_server_reconnect").click(function() {
        unsafeWindow.angal_connectDirect(ip);
    });
    this.onConnectingStartEvent(function(e) {
        ip = e.ip;
        jQuery("#angal_server").html(ip);
    });
    var modules = unsafeWindow.ontando.module.list;
    for (var i = 0; i < modules.length; i++) {
        var m = modules[i];
        var state = m.enabled ? "" : "";
        var newState = m.willEnabled == m.enabled ? (!m.willEnabled ? "Enable" : "Disable") : (m.willEnabled ? "Will Enabled" : "Will Disabled");
        $("#ontando_bonusTabs_moduleList").append(
            i + ") "
            + state // ""
              + m.author + ":" + m.name
              + " "
                + "["
                + "" + newState + ""
                + "]"
              + " "
            + ""
            + "
"
        );
        $('#ontando_bonusTabs_moduleOptions').append(
            '<option value="' + i + '">' + m.author + ":" + m.name +'</option>'
        );
    }
    unsafeWindow.ontando_bonusTabs_togleModule = function(id) {
        var m = modules[id];
        m.togleState();
        $("#ontando_bonusTabs_moduleList_e" + id).html(m.willEnabled == m.enabled ? (!m.willEnabled ? "Enable" : "Disable") : (m.willEnabled ? "Will Enabled" : "Will Disabled"));
    };

    unsafeWindow.ontando_bonusTabs_selectModule = function(id) {
        var m = modules[id];
        //m.renderOptions(jQuery("#ontando_bonusTabs_moduleOptions" + id)
    };
}]);
<|endoftext|>


<commit_before>/* global define: false */
define([], function() {
  'use strict';
  return [
          '$scope', '$location', 'Notifications', 'ProcessInstanceResource', '$modalInstance', 'processInstance', 'processData',
  function($scope,   $location,   Notifications,   ProcessInstanceResource,   $modalInstance,   processInstance,   processData) {

    var BEFORE_CANCEL = 'beforeCancellation',
        PERFORM_CANCEL = 'performCancellation',
        CANCEL_SUCCESS = 'cancellationSuccess',
        CANCEL_FAILED = 'cancellationFailed',
        LOADING_FAILED = 'loadingFailed';

    $scope.processInstance = processInstance;

    var cancelProcessInstanceData = processData.newChild($scope);

    $scope.$on('$routeChangeStart', function () {
      $modalInstance.close($scope.status);
    });

    cancelProcessInstanceData.provide('subProcessInstances', function () {
      return ProcessInstanceResource.query({
        firstResult: 0,
        maxResults: 5
      }, {
        superProcessInstance:
        processInstance.id
      }).$promise;
    });

    cancelProcessInstanceData.provide('subProcessInstancesCount', function () {
      return ProcessInstanceResource.count({
        superProcessInstance: processInstance.id
      }).$promise;
    });

    cancelProcessInstanceData.observe([ 'subProcessInstancesCount', 'subProcessInstances' ], function (subProcessInstancesCount, subProcessInstances) {
      $scope.subProcessInstancesCount = subProcessInstancesCount.count;
      $scope.subProcessInstances = subProcessInstances;

      $scope.status = BEFORE_CANCEL;
    });

    $scope.cancelProcessInstance = function () {
      $scope.status = PERFORM_CANCEL;

      $scope.processInstance.$delete(function () {
        // success
        $scope.status = CANCEL_SUCCESS;
        Notifications.addMessage({'status': 'Canceled', 'message': 'The cancellation of the process instance was successful.'});

      }, function () {
        // failure
        $scope.status = CANCEL_FAILED;
        Notifications.addError({'status': 'Failed', 'message': 'The cancellation of the process instance failed.', 'exclusive': ['type']});
      });
    };

    $scope.close = function (status) {
      $modalInstance.close(status);

      // if the cancellation of the process instance was successful,
      // then redirect to the corresponding process definition overview.
      if (status === CANCEL_SUCCESS) {
        $location.url('/process-definition/' + processInstance.definitionId);
        $location.replace();
      }
    };
  }];
});
<commit_msg>impr(process cancelation): make error message more meaningful<commit_after>/* global define: false */
define([], function() {
  'use strict';
  return [
          '$scope', '$location', 'Notifications', 'ProcessInstanceResource', '$modalInstance', 'processInstance', 'processData',
  function($scope,   $location,   Notifications,   ProcessInstanceResource,   $modalInstance,   processInstance,   processData) {

    var BEFORE_CANCEL = 'beforeCancellation',
        PERFORM_CANCEL = 'performCancellation',
        CANCEL_SUCCESS = 'cancellationSuccess',
        CANCEL_FAILED = 'cancellationFailed',
        LOADING_FAILED = 'loadingFailed';

    $scope.processInstance = processInstance;

    var cancelProcessInstanceData = processData.newChild($scope);

    $scope.$on('$routeChangeStart', function () {
      $modalInstance.close($scope.status);
    });

    cancelProcessInstanceData.provide('subProcessInstances', function () {
      return ProcessInstanceResource.query({
        firstResult: 0,
        maxResults: 5
      }, {
        superProcessInstance:
        processInstance.id
      }).$promise;
    });

    cancelProcessInstanceData.provide('subProcessInstancesCount', function () {
      return ProcessInstanceResource.count({
        superProcessInstance: processInstance.id
      }).$promise;
    });

    cancelProcessInstanceData.observe([ 'subProcessInstancesCount', 'subProcessInstances' ], function (subProcessInstancesCount, subProcessInstances) {
      $scope.subProcessInstancesCount = subProcessInstancesCount.count;
      $scope.subProcessInstances = subProcessInstances;

      $scope.status = BEFORE_CANCEL;
    });

    $scope.cancelProcessInstance = function () {
      $scope.status = PERFORM_CANCEL;

      $scope.processInstance.$delete(function () {
        // success
        $scope.status = CANCEL_SUCCESS;
        Notifications.addMessage({'status': 'Canceled', 'message': 'The cancellation of the process instance was successful.'});

      }, function (err) {
        // failure
        $scope.status = CANCEL_FAILED;
        Notifications.addError({'status': 'Failed', 'message': 'The cancellation of the process instance failed. ' + err.data.message, 'exclusive': ['type']});
      });
    };

    $scope.close = function (status) {
      $modalInstance.close(status);

      // if the cancellation of the process instance was successful,
      // then redirect to the corresponding process definition overview.
      if (status === CANCEL_SUCCESS) {
        $location.url('/process-definition/' + processInstance.definitionId);
        $location.replace();
      }
    };
  }];
});
<|endoftext|>


<commit_before>import { createAction, createThunkAction } from 'redux/actions';
import moment from 'moment';
import { all, spread } from 'axios';

import { fetchLatestDate } from 'services/latest';
import { statsLatestDecoder } from 'services/stats-latest-decoder';

export const setLatestLoading = createAction('setLatestLoading');
export const setLatestDates = createAction('setLatestDates');

export const getLatest = createThunkAction(
  'getLatest',
  (latestEndpoints) => (dispatch, getState) => {
    const { latest } = getState();
    const currentLatestDates = latest && Object.keys(latest.data);
    const newEndpoints = latestEndpoints.filter(
      (l) => !currentLatestDates.includes(l.id)
    );
    if (newEndpoints && newEndpoints.length) {
      dispatch(setLatestLoading({ loading: true, error: false }));
      all(newEndpoints.map((n) => fetchLatestDate(n.latestUrl)))
        .then(
          spread((...responses) => {
            const latestDates =
              responses &&
              responses.reduce((obj, response, index) => {
                const latestResponse = response.data.data || response.data;
                let date = latestResponse.date || latestResponse.max_date;
                console.log('date', date);

                const { bands } = latestResponse;
                // if the response is from the stats endpoint, get bands key
                if (bands && bands.length) {
                  // TODO: What if we don't get dates properly formatted back?
                  // Can this service return "null" or similar and then we can handle that case here
                  const days = statsLatestDecoder(bands);
                  const endDate = moment('2014-12-31')
                    .add(days, 'days')
                    .format('YYYY-MM-DD');
                  const defaultEndDate = moment()
                    .add(-7, 'days')
                    .format('YYYY-MM-DD');

                  // convert to date
                  date = days && days > 0 ? endDate : defaultEndDate;
                }
                if (!date) {
                  const data = Array.isArray(latestResponse)
                    ? latestResponse[0].attributes
                    : latestResponse.attributes;
                  date =
                    data && (data.date || data.latestResponse || data.latest);
                }
                let latestDate = moment(date).utc();
                if (newEndpoints[index].resolution) {
                  latestDate = latestDate.endOf(newEndpoints[index].resolution);
                }

                return {
                  ...obj,
                  [newEndpoints[index].id]: latestDate.format('YYYY-MM-DD'),
                };
              }, {});
            dispatch(setLatestDates(latestDates));
          })
        )
        .catch(() => {
          dispatch(setLatestLoading({ loading: false, error: true }));
        });
    }
  }
);
<commit_msg>Remove console.log<commit_after>import { createAction, createThunkAction } from 'redux/actions';
import moment from 'moment';
import { all, spread } from 'axios';

import { fetchLatestDate } from 'services/latest';
import { statsLatestDecoder } from 'services/stats-latest-decoder';

export const setLatestLoading = createAction('setLatestLoading');
export const setLatestDates = createAction('setLatestDates');

export const getLatest = createThunkAction(
  'getLatest',
  (latestEndpoints) => (dispatch, getState) => {
    const { latest } = getState();
    const currentLatestDates = latest && Object.keys(latest.data);
    const newEndpoints = latestEndpoints.filter(
      (l) => !currentLatestDates.includes(l.id)
    );
    if (newEndpoints && newEndpoints.length) {
      dispatch(setLatestLoading({ loading: true, error: false }));
      all(newEndpoints.map((n) => fetchLatestDate(n.latestUrl)))
        .then(
          spread((...responses) => {
            const latestDates =
              responses &&
              responses.reduce((obj, response, index) => {
                const latestResponse = response.data.data || response.data;
                let date = latestResponse.date || latestResponse.max_date;

                const { bands } = latestResponse;
                // if the response is from the stats endpoint, get bands key
                if (bands && bands.length) {
                  // TODO: What if we don't get dates properly formatted back?
                  // Can this service return "null" or similar and then we can handle that case here
                  const days = statsLatestDecoder(bands);
                  const endDate = moment('2014-12-31')
                    .add(days, 'days')
                    .format('YYYY-MM-DD');
                  const defaultEndDate = moment()
                    .add(-7, 'days')
                    .format('YYYY-MM-DD');

                  // convert to date
                  date = days && days > 0 ? endDate : defaultEndDate;
                }
                if (!date) {
                  const data = Array.isArray(latestResponse)
                    ? latestResponse[0].attributes
                    : latestResponse.attributes;
                  date =
                    data && (data.date || data.latestResponse || data.latest);
                }
                let latestDate = moment(date).utc();
                if (newEndpoints[index].resolution) {
                  latestDate = latestDate.endOf(newEndpoints[index].resolution);
                }

                return {
                  ...obj,
                  [newEndpoints[index].id]: latestDate.format('YYYY-MM-DD'),
                };
              }, {});
            dispatch(setLatestDates(latestDates));
          })
        )
        .catch(() => {
          dispatch(setLatestLoading({ loading: false, error: true }));
        });
    }
  }
);
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2016 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 */

/**
 * @fileoverview Main script of the PC/SC-Lite server client permissions user
 * prompt dialog window.
 *
 * Once the dialog is finished with some result (either user pressed the allow
 * button or the deny button, or the dialog was canceled), it uses the methods
 * of the GoogleSmartCard library for returning the result to the
 * caller window (i.e. to the App's background page).
 *
 * TODO(emaxx): Implement internationalization using the GoogleSmartCard.I18n
 * library instead of the CSS rules (which is ugly and non a11y friendly).
 */

goog.provide('GoogleSmartCard.PcscLiteServerClientsManagement.PermissionsChecking.UserPromptDialog.Main');

goog.require('GoogleSmartCard.InPopupMainScript');
goog.require('GoogleSmartCard.Logging');
goog.require('GoogleSmartCard.Packaging');
goog.require('goog.asserts');
goog.require('goog.dom');
goog.require('goog.dom.classlist');
goog.require('goog.events');
goog.require('goog.log.Logger');
goog.require('goog.string');

goog.scope(function() {

const UNTRUSTED_CLASS = 'untrusted';

const GSC = GoogleSmartCard;

const urlParams = new URLSearchParams(window.location.search);

/** @type {!goog.log.Logger} */
const logger = GSC.Logging.getScopedLogger(
    'PcscLiteServerClientsManagement.PermissionsChecking.UserPromptDialog.' +
    'Main');

const data = GSC.InPopupMainScript.getData();

function prepareMessage() {
  const isClientKnown = data['is_client_known'];
  GSC.Logging.checkWithLogger(logger, typeof isClientKnown === 'boolean');
  goog.asserts.assertBoolean(isClientKnown);

  const clientInfoLink = data['client_info_link'];
  GSC.Logging.checkWithLogger(logger, typeof clientInfoLink === 'string');
  goog.asserts.assertString(clientInfoLink);

  const clientName = data['client_name'];
  GSC.Logging.checkWithLogger(logger, typeof clientName === 'string');
  goog.asserts.assertString(clientName);

  const linkTitle = chrome.i18n.getMessage(
      'pcscClientHandlingUserPromptDialogMessageClientNamePart', clientName);

  const linkElement = goog.dom.getElement('message-app-link');
  goog.dom.setTextContent(linkElement, linkTitle);
  linkElement['href'] = clientInfoLink;

  if (!isClientKnown) {
    goog.dom.classlist.add(
        goog.dom.getElement('message-prefix'), UNTRUSTED_CLASS);
    goog.dom.classlist.add(
        goog.dom.getElement('message-suffix'), UNTRUSTED_CLASS);
    goog.dom.classlist.remove(goog.dom.getElement('warning-message'), 'hidden');
  }
}

function allowClickListener(event) {
  event.preventDefault();
  GSC.InPopupMainScript.resolveModalDialog(true);
}

function denyClickListener(event) {
  event.preventDefault();
  GSC.InPopupMainScript.resolveModalDialog(false);
}

function closeWindowClickListener() {
  window.close();
}

prepareMessage();

goog.events.listen(goog.dom.getElement('allow'), 'click', allowClickListener);
goog.events.listen(goog.dom.getElement('deny'), 'click', denyClickListener);

goog.events.listen(
    goog.dom.getElement('close-window'), 'click', closeWindowClickListener);

GSC.InPopupMainScript.prepareAndShowAsModalDialog();
});  // goog.scope
<commit_msg>Remove close button in extension mode (#502)<commit_after>/**
 * @license
 * Copyright 2016 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 */

/**
 * @fileoverview Main script of the PC/SC-Lite server client permissions user
 * prompt dialog window.
 *
 * Once the dialog is finished with some result (either user pressed the allow
 * button or the deny button, or the dialog was canceled), it uses the methods
 * of the GoogleSmartCard library for returning the result to the
 * caller window (i.e. to the App's background page).
 *
 * TODO(emaxx): Implement internationalization using the GoogleSmartCard.I18n
 * library instead of the CSS rules (which is ugly and non a11y friendly).
 */

goog.provide('GoogleSmartCard.PcscLiteServerClientsManagement.PermissionsChecking.UserPromptDialog.Main');

goog.require('GoogleSmartCard.InPopupMainScript');
goog.require('GoogleSmartCard.Logging');
goog.require('GoogleSmartCard.Packaging');
goog.require('goog.asserts');
goog.require('goog.dom');
goog.require('goog.dom.classlist');
goog.require('goog.events');
goog.require('goog.log.Logger');
goog.require('goog.string');

goog.scope(function() {

const UNTRUSTED_CLASS = 'untrusted';

const GSC = GoogleSmartCard;

const urlParams = new URLSearchParams(window.location.search);

/** @type {!goog.log.Logger} */
const logger = GSC.Logging.getScopedLogger(
    'PcscLiteServerClientsManagement.PermissionsChecking.UserPromptDialog.' +
    'Main');

const data = GSC.InPopupMainScript.getData();

function prepareMessage() {
  const isClientKnown = data['is_client_known'];
  GSC.Logging.checkWithLogger(logger, typeof isClientKnown === 'boolean');
  goog.asserts.assertBoolean(isClientKnown);

  const clientInfoLink = data['client_info_link'];
  GSC.Logging.checkWithLogger(logger, typeof clientInfoLink === 'string');
  goog.asserts.assertString(clientInfoLink);

  const clientName = data['client_name'];
  GSC.Logging.checkWithLogger(logger, typeof clientName === 'string');
  goog.asserts.assertString(clientName);

  const linkTitle = chrome.i18n.getMessage(
      'pcscClientHandlingUserPromptDialogMessageClientNamePart', clientName);

  const linkElement = goog.dom.getElement('message-app-link');
  goog.dom.setTextContent(linkElement, linkTitle);
  linkElement['href'] = clientInfoLink;

  if (!isClientKnown) {
    goog.dom.classlist.add(
        goog.dom.getElement('message-prefix'), UNTRUSTED_CLASS);
    goog.dom.classlist.add(
        goog.dom.getElement('message-suffix'), UNTRUSTED_CLASS);
    goog.dom.classlist.remove(goog.dom.getElement('warning-message'), 'hidden');
  }
}

function allowClickListener(event) {
  event.preventDefault();
  GSC.InPopupMainScript.resolveModalDialog(true);
}

function denyClickListener(event) {
  event.preventDefault();
  GSC.InPopupMainScript.resolveModalDialog(false);
}

function closeWindowClickListener() {
  window.close();
}

function removeCloseButton() {
  const closeButton = document.getElementById('close-window');
  closeButton.remove();
}

prepareMessage();

goog.events.listen(goog.dom.getElement('allow'), 'click', allowClickListener);
goog.events.listen(goog.dom.getElement('deny'), 'click', denyClickListener);

goog.events.listen(
    goog.dom.getElement('close-window'), 'click', closeWindowClickListener);

if (GSC.Packaging.MODE === GSC.Packaging.Mode.EXTENSION)
  removeCloseButton();

GSC.InPopupMainScript.prepareAndShowAsModalDialog();
});  // goog.scope
<|endoftext|>