<commit_before>// Import React
import React from "react";

// Import Spectacle Core tags
import {
  Appear,
  CodePane,
  Deck,
  Fit,
  Fill,
  Heading,
  Image,
  Layout,
  Link,
  ListItem,
  List,
  Slide,
  Spectacle,
  Text
} from "spectacle";

import CodeSlide from "spectacle-code-slide";
// Import image preloader util
import preloader from "spectacle/lib/utils/preloader";

// Import theme
import createTheme from "spectacle/lib/themes/default";

// Import custom component
import Interactive from "../assets/interactive";

import AsciinemaPlayer from "./asciinema-player.jsx";

// Require CSS
require("normalize.css");
require("spectacle/lib/themes/default/index.css");
require("font-awesome/css/font-awesome.css");

const images = {
  city: require("../assets/city.jpg"),
  kat: require("../assets/kat.png"),
  logo: require("../assets/formidable-logo.svg"),
  markdown: require("../assets/markdown.png")
};

preloader(images);

function TitleElement({ children }) {
  const style = {
    flex: "0 0 auto",
  };
  return (
    <Fit {...{ style }}>
    <Text margin="20px 0px 0px" textSize="2rem">
    {children}
    </Text>
    </Fit>
  );
}

function Icon({ name, ...rest }) {
  return <i className={`fa fa-${name}`} aria-hidden="true" {...rest} >;
}

const MyListItem = (props) => <ListItem textSize="2rem" {...props} />;
const theme = createTheme({
  primary: "#f9c300",
  secondary: "black",
  tertiary: "black",
  quartenary: "white"
}, {
  primary: "Open Sans Condensed",
  secondary: "PressStart2P",
  tertiary: "Source Code Pro for Powerline",
});

const slideProps = { maxWidth: "100%", maxHeight: "100%" };

// Sections
const talkBackgroundSection = [
  <Slide {...slideProps} >
    <Heading size={3} fit>
      About this talk
    </Heading>
    <Layout style={{ alignItems: "center" }}>
    <Fill style={{ flex: 2 }}>
      <Appear><Image src="../assets/twitter-program-online.png" /></Appear>
      <Appear><Image src="../assets/twitter-switching-jest.png" /></Appear>
    </Fill>
    <Fill style={{ flex: 3 }}>
    <Appear><Text textSize="2rem" >What about chai and its plugins?</Text></Appear>
    <Appear><Text textSize="2rem">What about css modules?</Text></Appear>
    <Appear><Text textSize="2rem">What about webpack-inject-loader / proxyquire?</Text></Appear>
    </Fill>
    </Layout>
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit>
      About this talk
    </Heading>
    <Layout style={{ alignItems: "center" }}>
    <Fill>
      <Image src="../assets/github-jest-pr.png" />
      <Image src="../assets/jest-blog-chai.png" />
    </Fill>
    <Fill>
      <Appear>

        <Image src="../assets/github-usejest.png" />
        <Image src="../assets/test-passed.png" />

      </Appear>
      <Appear><Image src="../assets/twitter-pivot.png" /></Appear>
    </Fill>
    </Layout>
  </Slide>
];

const lessonsLearnedMigrationSection = [
  <Slide {...slideProps} >
    <Heading size={3} fit>Downsides of migration to Jest</Heading>
    <List>
      <MyListItem>Slow (> 10s for a suite) when you:</MyListItem>
      <List margin="0 0 0 3rem">
        <MyListItem>resetModules every test</MyListItem>
        <MyListItem>Start express every test</MyListItem>
        <MyListItem>Run coverage</MyListItem>
        <MyListItem>Don't use the cache</MyListItem>
      </List>
      <MyListItem>Cache sometimes confusing</MyListItem>
      <MyListItem>Migrating existing mock injectors is difficult</MyListItem>
    </List>
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit>
      Upsides of the migration
    </Heading>
    <List>
      <MyListItem>Snapshot tests with CLI integration and cleanup</MyListItem>
      <MyListItem>Mocking which actually works</MyListItem>
      <MyListItem>Fast watch mode</MyListItem>
      <MyListItem>Working stacktraces</MyListItem>
      <MyListItem>Coverage of not imported files</MyListItem>
    </List>
  </Slide>
];

const migrateExpectSection = [
  <Slide {...slideProps} >
    <Heading size={3} fit>
      Alias jasmine and chai
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/alias-jasmine.js")}
      textSize="20pt"
    />
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit>
    Combine jasmine and chai - example
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/combined-expect-example.js")}
    />
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit>
    Combine jasmine and chai
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/combine-jasmine-chai.js")}
      textSize="0.7rem"
    />
  </Slide>
];

const cssModulesSection = [
  <Slide {...slideProps} >
    <Heading size={3} fit>
      Ensure CSS modules still work
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/css-modules-preprocessor.js")}
    />
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit>
      Snapshots with CSS modules
    </Heading>
    <Layout>
      <Fill >
        <CodePane
          lang="jsx"
          source={require("!raw!../includes/App.css")}
          textSize="0.7rem"
          style={{ margin: "0 0 25px 0" }}
        />
        <CodePane
          lang="jsx"
          source={require("!raw!../includes/App.jsx")}
          textSize="0.7rem"
        />
      </Fill>

      <Fill>
        <CodePane
          lang="jsx"
          source={require("!raw!../includes/App.snap.js")}
          textSize="0.7rem"
        />
      </Fill>
    </Layout>
  </Slide>
];

const injectLoaderSection = [
  <Slide {...slideProps} >
    <Heading size={3} fit >
    Webpack inject loader / proxyquire
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/inject-loader.js")}
    />
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit >
    Use a wrapper to make it jest compatible
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/inject-loader-compatibility.js")}
    />
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit >
    Use a VIM macro to automate migration
    </Heading>
    <AsciinemaPlayer src="assets/inject-loader-compatibility-macro.json" autoplay fontSize="big"/>
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit >
    Inject loader compatibility
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/inject-loader-compatibility-implementation.js")}
      textSize="0.7rem"
    />
  </Slide>,
  <CodeSlide
    transition={[]}
    lang="js"
    code={require("!raw!../includes/inject-loader-compatibility-implementation.js")}
    ranges={[
      { loc: [0, 270], title: "injectLoaderCompatibility" },
      { loc: [3, 5], title: "Reset the modules first" },
      { loc: [6, 7], title: "Take the files to inject" },
      { loc: [8, 16], title: "Iterate over the those" },
      { loc: [13, 15], title: "Inject the mock using Jest" },
      { loc: [18, 19], title: "Return the module" },
      { loc: [21, 22], title: "Expose as a global" },
    ]}
    textSize="15pt"
  />,
];

const supertestSection = [
  <Slide {...slideProps} >
    <Heading size={3} fit>
    Supertest
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/supertest.js")}
    />
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit>
    Supertest with Promises
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/supertest-as-promised.js")}
    />
  </Slide>
];

const titleSlide = (
  <Slide {...slideProps} >
    <Heading size={1} fit>
      Snapshot tests
    </Heading>
    <Heading size={2} fit>
      with Mocha in Jest
    </Heading>
    <Layout style={{ justifyContent: "space-between" }}>
    <TitleElement><Icon name="user" /> Ruben Oostinga</TitleElement>
    <TitleElement><Icon name="twitter" /> @RubenOostinga</TitleElement>
    <TitleElement><Icon name="github" /> https://github.com/0xR</TitleElement>
    <TitleElement><Icon name="building" /> Xebia</TitleElement>
    </Layout>
  </Slide>
);

const contentSlide = (
  <Slide {...slideProps} >
    <Heading size={3} >
      Contents
    </Heading>
    <List>
      <MyListItem>What is snapshot testing</MyListItem>
      <MyListItem>Migrating to Jest</MyListItem>
        <List margin="0 0 0 3rem">
          <MyListItem>Porting over expect</MyListItem>
          <MyListItem>CSS modules</MyListItem>
          <MyListItem>Webpack inject loader / proxyquire</MyListItem>
          <MyListItem>Async</MyListItem>
          <MyListItem>Failing tests on React warning</MyListItem>
        </List>
    </List>
  </Slide>
);

const snapshotTestingSection = [
  <Slide {...slideProps} >
    <Heading size={3} fit>
      What is snapshot testing
    </Heading>
    <AsciinemaPlayer src="assets/snapshot-testing.json" autoplay fontSize="big"/>
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit>What problem does snapshot testing solve?</Heading>
    <List>
      <MyListItem>You want to assert everything, but not maintain all assertions</MyListItem>
      <MyListItem>Makes testing easy, so no excuse for no tests</MyListItem>
      <MyListItem>Find unexpected regressions easily</MyListItem>
      <MyListItem>Record of the render output</MyListItem>
    </List>
  </Slide>,
];

const reactWarningsSection = [
  <Slide {...slideProps} >
    <Heading size={3} fit>
    Fail test on React warning
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/make-react-warnings-errors.js")}
    />
  </Slide>
];

const finalSlide = (
  <Slide {...slideProps} >
    <Heading size={3} fit>
    The End
    </Heading>
    <Text>
      Code:
      <Link href="https://github.com/0xR/snapshot-experiments/pull/1" >https://github.com/0xR/snapshot-experiments/pull/1</Link>
    </Text>
    <Text>Link to slides will be posted on <Icon name="twitter" /> @RubenOostinga</Text>
  </Slide>
);

// Should be a proper component to ensure HMR works
export default class Presentation extends React.Component {
  render() {
    return (
      <Spectacle theme={theme}>
        <Deck>
          {[
            titleSlide,
            ...talkBackgroundSection,
            contentSlide,
            ...snapshotTestingSection,
            ...migrateExpectSection,
            ...cssModulesSection,
            ...injectLoaderSection,
            ...supertestSection,
            ...reactWarningsSection,
            ...lessonsLearnedMigrationSection,
            finalSlide,
          ]}
        </Deck>
      </Spectacle>
    );
  }
}

/* what is snapshot testing
 * what problem does it solve
 * Conferencetalk Driven development, not gonna fall for free tool ;)
 * twitter screenshots
 * Christoph worked on it for over a year, some months
 * chai-jest-snapshot
 * disadvantage: no way to hook into the CLI, doesn"t clean up snapshots
 * migrating:
 * combining chai / jest
 * inject loader compatibility layer
 * proptype warnings because of resetModules
 * pro tip: make react proptype warning fail a test
 *
 * disadvantage: slow for integration, increade default timeout, cache sometimes confusing
 * only error: user error
 * pros: nice console output, DX: console.log, watch, rerun failed tests first, nice diff when test fails, buffered console, mocks that work, coverage of not included files
 */

<commit_msg>Add upside<commit_after>// Import React
import React from "react";

// Import Spectacle Core tags
import {
  Appear,
  CodePane,
  Deck,
  Fit,
  Fill,
  Heading,
  Image,
  Layout,
  Link,
  ListItem,
  List,
  Slide,
  Spectacle,
  Text
} from "spectacle";

import CodeSlide from "spectacle-code-slide";
// Import image preloader util
import preloader from "spectacle/lib/utils/preloader";

// Import theme
import createTheme from "spectacle/lib/themes/default";

// Import custom component
import Interactive from "../assets/interactive";

import AsciinemaPlayer from "./asciinema-player.jsx";

// Require CSS
require("normalize.css");
require("spectacle/lib/themes/default/index.css");
require("font-awesome/css/font-awesome.css");

const images = {
  city: require("../assets/city.jpg"),
  kat: require("../assets/kat.png"),
  logo: require("../assets/formidable-logo.svg"),
  markdown: require("../assets/markdown.png")
};

preloader(images);

function TitleElement({ children }) {
  const style = {
    flex: "0 0 auto",
  };
  return (
    <Fit {...{ style }}>
    <Text margin="20px 0px 0px" textSize="2rem">
    {children}
    </Text>
    </Fit>
  );
}

function Icon({ name, ...rest }) {
  return <i className={`fa fa-${name}`} aria-hidden="true" {...rest} >;
}

const MyListItem = (props) => <ListItem textSize="2rem" {...props} />;
const theme = createTheme({
  primary: "#f9c300",
  secondary: "black",
  tertiary: "black",
  quartenary: "white"
}, {
  primary: "Open Sans Condensed",
  secondary: "PressStart2P",
  tertiary: "Source Code Pro for Powerline",
});

const slideProps = { maxWidth: "100%", maxHeight: "100%" };

// Sections
const talkBackgroundSection = [
  <Slide {...slideProps} >
    <Heading size={3} fit>
      About this talk
    </Heading>
    <Layout style={{ alignItems: "center" }}>
    <Fill style={{ flex: 2 }}>
      <Appear><Image src="../assets/twitter-program-online.png" /></Appear>
      <Appear><Image src="../assets/twitter-switching-jest.png" /></Appear>
    </Fill>
    <Fill style={{ flex: 3 }}>
    <Appear><Text textSize="2rem" >What about chai and its plugins?</Text></Appear>
    <Appear><Text textSize="2rem">What about css modules?</Text></Appear>
    <Appear><Text textSize="2rem">What about webpack-inject-loader / proxyquire?</Text></Appear>
    </Fill>
    </Layout>
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit>
      About this talk
    </Heading>
    <Layout style={{ alignItems: "center" }}>
    <Fill>
      <Image src="../assets/github-jest-pr.png" />
      <Image src="../assets/jest-blog-chai.png" />
    </Fill>
    <Fill>
      <Appear>

        <Image src="../assets/github-usejest.png" />
        <Image src="../assets/test-passed.png" />

      </Appear>
      <Appear><Image src="../assets/twitter-pivot.png" /></Appear>
    </Fill>
    </Layout>
  </Slide>
];

const lessonsLearnedMigrationSection = [
  <Slide {...slideProps} >
    <Heading size={3} fit>Downsides of migration to Jest</Heading>
    <List>
      <MyListItem>Slow (> 10s for a suite) when you:</MyListItem>
      <List margin="0 0 0 3rem">
        <MyListItem>resetModules every test</MyListItem>
        <MyListItem>Start express every test</MyListItem>
        <MyListItem>Run coverage</MyListItem>
        <MyListItem>Don't use the cache</MyListItem>
      </List>
      <MyListItem>Cache sometimes confusing</MyListItem>
      <MyListItem>Migrating existing mock injectors is difficult</MyListItem>
    </List>
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit>
      Upsides of the migration
    </Heading>
    <List>
      <MyListItem>Snapshot tests with CLI integration and cleanup</MyListItem>
      <MyListItem>Mocking which actually works</MyListItem>
      <MyListItem>Fast watch mode</MyListItem>
      <MyListItem>Tests affected by your changes run first</MyListItem>
      <MyListItem>Working stacktraces</MyListItem>
      <MyListItem>Coverage of not imported files</MyListItem>
    </List>
  </Slide>
];

const migrateExpectSection = [
  <Slide {...slideProps} >
    <Heading size={3} fit>
      Alias jasmine and chai
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/alias-jasmine.js")}
      textSize="20pt"
    />
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit>
    Combine jasmine and chai - example
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/combined-expect-example.js")}
    />
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit>
    Combine jasmine and chai
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/combine-jasmine-chai.js")}
      textSize="0.7rem"
    />
  </Slide>
];

const cssModulesSection = [
  <Slide {...slideProps} >
    <Heading size={3} fit>
      Ensure CSS modules still work
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/css-modules-preprocessor.js")}
    />
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit>
      Snapshots with CSS modules
    </Heading>
    <Layout>
      <Fill >
        <CodePane
          lang="jsx"
          source={require("!raw!../includes/App.css")}
          textSize="0.7rem"
          style={{ margin: "0 0 25px 0" }}
        />
        <CodePane
          lang="jsx"
          source={require("!raw!../includes/App.jsx")}
          textSize="0.7rem"
        />
      </Fill>

      <Fill>
        <CodePane
          lang="jsx"
          source={require("!raw!../includes/App.snap.js")}
          textSize="0.7rem"
        />
      </Fill>
    </Layout>
  </Slide>
];

const injectLoaderSection = [
  <Slide {...slideProps} >
    <Heading size={3} fit >
    Webpack inject loader / proxyquire
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/inject-loader.js")}
    />
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit >
    Use a wrapper to make it jest compatible
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/inject-loader-compatibility.js")}
    />
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit >
    Use a VIM macro to automate migration
    </Heading>
    <AsciinemaPlayer src="assets/inject-loader-compatibility-macro.json" autoplay fontSize="big"/>
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit >
    Inject loader compatibility
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/inject-loader-compatibility-implementation.js")}
      textSize="0.7rem"
    />
  </Slide>,
  <CodeSlide
    transition={[]}
    lang="js"
    code={require("!raw!../includes/inject-loader-compatibility-implementation.js")}
    ranges={[
      { loc: [0, 270], title: "injectLoaderCompatibility" },
      { loc: [3, 5], title: "Reset the modules first" },
      { loc: [6, 7], title: "Take the files to inject" },
      { loc: [8, 16], title: "Iterate over the those" },
      { loc: [13, 15], title: "Inject the mock using Jest" },
      { loc: [18, 19], title: "Return the module" },
      { loc: [21, 22], title: "Expose as a global" },
    ]}
    textSize="15pt"
  />,
];

const supertestSection = [
  <Slide {...slideProps} >
    <Heading size={3} fit>
    Supertest
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/supertest.js")}
    />
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit>
    Supertest with Promises
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/supertest-as-promised.js")}
    />
  </Slide>
];

const titleSlide = (
  <Slide {...slideProps} >
    <Heading size={1} fit>
      Snapshot tests
    </Heading>
    <Heading size={2} fit>
      with Mocha in Jest
    </Heading>
    <Layout style={{ justifyContent: "space-between" }}>
    <TitleElement><Icon name="user" /> Ruben Oostinga</TitleElement>
    <TitleElement><Icon name="twitter" /> @RubenOostinga</TitleElement>
    <TitleElement><Icon name="github" /> https://github.com/0xR</TitleElement>
    <TitleElement><Icon name="building" /> Xebia</TitleElement>
    </Layout>
  </Slide>
);

const contentSlide = (
  <Slide {...slideProps} >
    <Heading size={3} >
      Contents
    </Heading>
    <List>
      <MyListItem>What is snapshot testing</MyListItem>
      <MyListItem>Migrating to Jest</MyListItem>
        <List margin="0 0 0 3rem">
          <MyListItem>Porting over expect</MyListItem>
          <MyListItem>CSS modules</MyListItem>
          <MyListItem>Webpack inject loader / proxyquire</MyListItem>
          <MyListItem>Async</MyListItem>
          <MyListItem>Failing tests on React warning</MyListItem>
        </List>
    </List>
  </Slide>
);

const snapshotTestingSection = [
  <Slide {...slideProps} >
    <Heading size={3} fit>
      What is snapshot testing
    </Heading>
    <AsciinemaPlayer src="assets/snapshot-testing.json" autoplay fontSize="big"/>
  </Slide>,
  <Slide {...slideProps} >
    <Heading size={3} fit>What problem does snapshot testing solve?</Heading>
    <List>
      <MyListItem>You want to assert everything, but not maintain all assertions</MyListItem>
      <MyListItem>Makes testing easy, so no excuse for no tests</MyListItem>
      <MyListItem>Find unexpected regressions easily</MyListItem>
      <MyListItem>Record of the render output</MyListItem>
    </List>
  </Slide>,
];

const reactWarningsSection = [
  <Slide {...slideProps} >
    <Heading size={3} fit>
    Fail test on React warning
    </Heading>
    <CodePane
      lang="jsx"
      source={require("!raw!../includes/make-react-warnings-errors.js")}
    />
  </Slide>
];

const finalSlide = (
  <Slide {...slideProps} >
    <Heading size={3} fit>
    The End
    </Heading>
    <Text>
      Code:
      <Link href="https://github.com/0xR/snapshot-experiments/pull/1" >https://github.com/0xR/snapshot-experiments/pull/1</Link>
    </Text>
    <Text>Link to slides will be posted on <Icon name="twitter" /> @RubenOostinga</Text>
  </Slide>
);

// Should be a proper component to ensure HMR works
export default class Presentation extends React.Component {
  render() {
    return (
      <Spectacle theme={theme}>
        <Deck>
          {[
            titleSlide,
            ...talkBackgroundSection,
            contentSlide,
            ...snapshotTestingSection,
            ...migrateExpectSection,
            ...cssModulesSection,
            ...injectLoaderSection,
            ...supertestSection,
            ...reactWarningsSection,
            ...lessonsLearnedMigrationSection,
            finalSlide,
          ]}
        </Deck>
      </Spectacle>
    );
  }
}

/* what is snapshot testing
 * what problem does it solve
 * Conferencetalk Driven development, not gonna fall for free tool ;)
 * twitter screenshots
 * Christoph worked on it for over a year, some months
 * chai-jest-snapshot
 * disadvantage: no way to hook into the CLI, doesn"t clean up snapshots
 * migrating:
 * combining chai / jest
 * inject loader compatibility layer
 * proptype warnings because of resetModules
 * pro tip: make react proptype warning fail a test
 *
 * disadvantage: slow for integration, increade default timeout, cache sometimes confusing
 * only error: user error
 * pros: nice console output, DX: console.log, watch, rerun failed tests first, nice diff when test fails, buffered console, mocks that work, coverage of not included files
 */

<|endoftext|>


<commit_before>import path from 'path'
import favicon from 'serve-favicon'
import compress from 'compression'
import helmet from 'helmet'
import dotenv from 'dotenv'
import feathers from '@feathersjs/feathers'
import configuration from '@feathersjs/configuration'
import express from '@feathersjs/express'
import envHelpers from 'feathers-envhelpers'
import { iff } from 'feathers-hooks-common'
import { authenticate } from '@feathersjs/authentication'

import db from './db'
import middleware from './middleware'
import cors from './middleware/cors'
import logger, { loggerHook } from './hooks/logger'
import { authorize } from './hooks/authorization'
import services from './services'
import jobs from './jobs'
import errorHandler from './hooks/errors'

dotenv.config({ path: path.resolve(__dirname, '..', '.env') })

const startApp = (configurationOverrides = {}) => {
  const app = express(feathers())
  app.disable('x-powered-by')
  app.configure(express.rest())

  app.configure(envHelpers())
  app.configure(logger)

  const conf = configuration()
  app.configure(conf)
  Object.keys(configurationOverrides).forEach((key) => {
    app.set(key, configurationOverrides[key])
  })
  app.info(conf(), 'App configuration')
  app.info(configurationOverrides, 'application overrides')
  app.configure(cors)

  app.use(helmet())
  app.use(compress())
  app.use(express.json())
  app.use(express.urlencoded({ extended: true }))

  app.configure(middleware)
  app.configure(db)
  app.configure(jobs)

  app.configure(services)

  app.use(favicon(path.join(app.get('public'), 'favicon.ico')))
  app.use('/', express.static(app.get('public')))
  app.use(express.notFound())
  app.use(express.errorHandler(app.get('errorhandler')))

  app.hooks({
    before: {
      all: [
        loggerHook,
        // temporary workaround to allow username/password authentication
        // without specifying strategy:local in the request.
        (ctx) => {
          app.info(ctx.data)
          if (ctx.data && ctx.data.email && !ctx.data.strategy) {
            ctx.data.strategy = 'local'
          }
        },
        iff(
          (ctx) => ctx.params.provider && ctx.path !== 'authentication',
          iff((ctx) => ctx.params.headers.authorization, authenticate('jwt')),
          authorize
        ),
      ],
      find: [],
      get: [],
      create: [],
      update: [],
      patch: [],
      remove: [],
    },
    after: {
      all: [loggerHook],
      find: [],
      get: [],
      create: [],
      update: [],
      patch: [],
      remove: [],
    },

    error: {
      all: [loggerHook, errorHandler],
      find: [],
      get: [],
      create: [],
      update: [],
      patch: [],
      remove: [],
    },
  })
  return app
}

const appLauncher = {
  startApp,
}

export default appLauncher
<commit_msg>Use workaround only for authentication service.<commit_after>import path from 'path'
import favicon from 'serve-favicon'
import compress from 'compression'
import helmet from 'helmet'
import dotenv from 'dotenv'
import feathers from '@feathersjs/feathers'
import configuration from '@feathersjs/configuration'
import express from '@feathersjs/express'
import envHelpers from 'feathers-envhelpers'
import { iff } from 'feathers-hooks-common'
import { authenticate } from '@feathersjs/authentication'

import db from './db'
import middleware from './middleware'
import cors from './middleware/cors'
import logger, { loggerHook } from './hooks/logger'
import { authorize } from './hooks/authorization'
import services from './services'
import jobs from './jobs'
import errorHandler from './hooks/errors'

dotenv.config({ path: path.resolve(__dirname, '..', '.env') })

const startApp = (configurationOverrides = {}) => {
  const app = express(feathers())
  app.disable('x-powered-by')
  app.configure(express.rest())

  app.configure(envHelpers())
  app.configure(logger)

  const conf = configuration()
  app.configure(conf)
  Object.keys(configurationOverrides).forEach((key) => {
    app.set(key, configurationOverrides[key])
  })
  app.info(conf(), 'App configuration')
  app.info(configurationOverrides, 'application overrides')
  app.configure(cors)

  app.use(helmet())
  app.use(compress())
  app.use(express.json())
  app.use(express.urlencoded({ extended: true }))

  app.configure(middleware)
  app.configure(db)
  app.configure(jobs)

  app.configure(services)

  app.use(favicon(path.join(app.get('public'), 'favicon.ico')))
  app.use('/', express.static(app.get('public')))
  app.use(express.notFound())
  app.use(express.errorHandler(app.get('errorhandler')))

  app.hooks({
    before: {
      all: [
        loggerHook,
        // temporary workaround to allow username/password authentication
        // without specifying strategy:local in the request.
        (ctx) => {
          if (
            ctx.path === 'authentication' &&
            ctx.data &&
            ctx.data.email &&
            !ctx.data.strategy
          ) {
            ctx.data.strategy = 'local'
          }
        },
        iff(
          (ctx) => ctx.params.provider && ctx.path !== 'authentication',
          iff((ctx) => ctx.params.headers.authorization, authenticate('jwt')),
          authorize
        ),
      ],
      find: [],
      get: [],
      create: [],
      update: [],
      patch: [],
      remove: [],
    },
    after: {
      all: [loggerHook],
      find: [],
      get: [],
      create: [],
      update: [],
      patch: [],
      remove: [],
    },

    error: {
      all: [loggerHook, errorHandler],
      find: [],
      get: [],
      create: [],
      update: [],
      patch: [],
      remove: [],
    },
  })
  return app
}

const appLauncher = {
  startApp,
}

export default appLauncher
<|endoftext|>


<commit_before>//  ███████╗██╗███╗   ██╗██████╗      ██████╗ █████╗ ███████╗ ██████╗ █████╗ ██████╗ ███████╗
//  ██╔════╝██║████╗  ██║██╔══██╗    ██╔════╝██╔══██╗██╔════╝██╔════╝██╔══██╗██╔══██╗██╔════╝
//  █████╗  ██║██╔██╗ ██║██║  ██║    ██║     ███████║███████╗██║     ███████║██║  ██║█████╗
//  ██╔══╝  ██║██║╚██╗██║██║  ██║    ██║     ██╔══██║╚════██║██║     ██╔══██║██║  ██║██╔══╝
//  ██║     ██║██║ ╚████║██████╔╝    ╚██████╗██║  ██║███████║╚██████╗██║  ██║██████╔╝███████╗
//  ╚═╝     ╚═╝╚═╝  ╚═══╝╚═════╝      ╚═════╝╚═╝  ╚═╝╚══════╝ ╚═════╝╚═╝  ╚═╝╚═════╝ ╚══════╝
//
//  ██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ██████╗ ███████╗
//  ██╔══██╗██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔══██╗██╔════╝
//  ██████╔╝█████╗  ██║     ██║   ██║██████╔╝██║  ██║███████╗
//  ██╔══██╗██╔══╝  ██║     ██║   ██║██╔══██╗██║  ██║╚════██║
//  ██║  ██║███████╗╚██████╗╚██████╔╝██║  ██║██████╔╝███████║
//  ╚═╝  ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝  ╚═╝╚═════╝ ╚══════╝
//

var _ = require('@sailshq/lodash');

module.exports = function findCascadeRecords(stageThreeQuery, model, cb) {
  // Build the select using the column name of the primary key attribute
  var primaryKeyAttrName = model.primaryKey;
  var primaryKeyDef = model.schema[primaryKeyAttrName];

  // Build a find query that selects the primary key
  var findQuery = {
    method: 'find',
    using: stageThreeQuery.using,
    criteria: {
      where: stageThreeQuery.criteria.where,
      skip: stageThreeQuery.criteria.skip,
      limit: stageThreeQuery.criteria.limit,
      sort: stageThreeQuery.criteria.sort,
      select: [primaryKeyDef.columnName]
    },
    meta: stageThreeQuery.meta
  };

  //  ╔═╗╔═╗╔╗╔╔╦╗  ┌┬┐┌─┐  ┌─┐┌┬┐┌─┐┌─┐┌┬┐┌─┐┬─┐
  //  ╚═╗║╣ ║║║ ║║   │ │ │  ├─┤ ││├─┤├─┘ │ ├┤ ├┬┘
  //  ╚═╝╚═╝╝╚╝═╩╝   ┴ └─┘  ┴ ┴─┴┘┴ ┴┴   ┴ └─┘┴└─

  // Grab the adapter to perform the query on
  var datastoreName = model.adapterDictionary.find;
  var adapter = model.datastores[datastoreName].adapter;

  // Run the operation
  adapter.find(datastoreName, findQuery, function findCb(err, values) {
    if (err) {
      return cb(err);
    }

    // Map out an array of primary keys
    var primaryKeys = _.map(values, function mapValues(record) {
      return record[primaryKeyDef.columnName];
    });

    return cb(undefined, primaryKeys);
  }, stageThreeQuery.meta);
};
<commit_msg>remove extra callback<commit_after>//  ███████╗██╗███╗   ██╗██████╗      ██████╗ █████╗ ███████╗ ██████╗ █████╗ ██████╗ ███████╗
//  ██╔════╝██║████╗  ██║██╔══██╗    ██╔════╝██╔══██╗██╔════╝██╔════╝██╔══██╗██╔══██╗██╔════╝
//  █████╗  ██║██╔██╗ ██║██║  ██║    ██║     ███████║███████╗██║     ███████║██║  ██║█████╗
//  ██╔══╝  ██║██║╚██╗██║██║  ██║    ██║     ██╔══██║╚════██║██║     ██╔══██║██║  ██║██╔══╝
//  ██║     ██║██║ ╚████║██████╔╝    ╚██████╗██║  ██║███████║╚██████╗██║  ██║██████╔╝███████╗
//  ╚═╝     ╚═╝╚═╝  ╚═══╝╚═════╝      ╚═════╝╚═╝  ╚═╝╚══════╝ ╚═════╝╚═╝  ╚═╝╚═════╝ ╚══════╝
//
//  ██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ██████╗ ███████╗
//  ██╔══██╗██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔══██╗██╔════╝
//  ██████╔╝█████╗  ██║     ██║   ██║██████╔╝██║  ██║███████╗
//  ██╔══██╗██╔══╝  ██║     ██║   ██║██╔══██╗██║  ██║╚════██║
//  ██║  ██║███████╗╚██████╗╚██████╔╝██║  ██║██████╔╝███████║
//  ╚═╝  ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝  ╚═╝╚═════╝ ╚══════╝
//

var _ = require('@sailshq/lodash');

module.exports = function findCascadeRecords(stageThreeQuery, model, cb) {
  // Build the select using the column name of the primary key attribute
  var primaryKeyAttrName = model.primaryKey;
  var primaryKeyDef = model.schema[primaryKeyAttrName];

  // Build a find query that selects the primary key
  var findQuery = {
    method: 'find',
    using: stageThreeQuery.using,
    criteria: {
      where: stageThreeQuery.criteria.where,
      skip: stageThreeQuery.criteria.skip,
      limit: stageThreeQuery.criteria.limit,
      sort: stageThreeQuery.criteria.sort,
      select: [primaryKeyDef.columnName]
    },
    meta: stageThreeQuery.meta
  };

  //  ╔═╗╔═╗╔╗╔╔╦╗  ┌┬┐┌─┐  ┌─┐┌┬┐┌─┐┌─┐┌┬┐┌─┐┬─┐
  //  ╚═╗║╣ ║║║ ║║   │ │ │  ├─┤ ││├─┤├─┘ │ ├┤ ├┬┘
  //  ╚═╝╚═╝╝╚╝═╩╝   ┴ └─┘  ┴ ┴─┴┘┴ ┴┴   ┴ └─┘┴└─

  // Grab the adapter to perform the query on
  var datastoreName = model.adapterDictionary.find;
  var adapter = model.datastores[datastoreName].adapter;

  // Run the operation
  adapter.find(datastoreName, findQuery, function findCb(err, values) {
    if (err) {
      return cb(err);
    }

    // Map out an array of primary keys
    var primaryKeys = _.map(values, function mapValues(record) {
      return record[primaryKeyDef.columnName];
    });

    return cb(undefined, primaryKeys);
  });
};
<|endoftext|>


<commit_before>import React from "react";

import {
    Appear,
    BlockQuote,
    Cite,
    CodePane,
    Deck,
    Fill,
    Heading,
    Image,
    Layout,
    ListItem,
    List,
    Quote,
    Slide,
    Spectacle,
    Text
} from "spectacle";

import preloader from "spectacle/lib/utils/preloader";
import createTheme from "spectacle/lib/themes/default";

require("normalize.css");
require("spectacle/lib/themes/default/index.css");

const images = {
    runningTests: require("../assets/running_tests.gif")
};

preloader(images);

const theme = createTheme({
    primary: "#5a5255",
    blue: "#1b85b8"
});

const imageSrc = (name) => images[name].replace("/", "");

export default class Presentation extends React.Component {
    render() {
        return (
            <Spectacle theme={theme}>
                <Deck transition={["zoom", "slide"]} transitionDuration={500}>

                    <Slide transition={["slide"]} bgColor="primary" notes="Some notes for the slide">
                        <Heading size={3} caps textColor="white">Enzyme</Heading>
                        <Image src={imageSrc("runningTests")} margin="0px auto 40px" width="850px" height="537px"/>
                    </Slide>

                    <Slide transition={["slide"]} bgColor="primary" textColor="white">
                        <Heading size={3} caps textColor="white">Why?</Heading>
                        <List>
                            <Appear><ListItem textSize="60px">Make tests more readable</ListItem></Appear>
                            <Appear><ListItem textSize="60px">Less boilerplate</ListItem></Appear>
                            <Appear><ListItem textSize="60px">Simplify common use cases</ListItem></Appear>
                        </List>
                    </Slide>

                    <Slide transition={["zoom", "fade"]} bgColor="primary" textColor="white">
                        <CodePane
                            source={require("raw!../assets/code_snippets/import_enzyme.js.example")}
                            lang="jsx"
                            textSize="20px" />
                        <List>
                            <Appear>
                                <ListItem textSize="40px">
                                    Shallow rendering is the preferable and the fastest way of rendering
                                </ListItem>
                            </Appear>
                            <Appear>
                                <ListItem textSize="38px" margin="40px 0">
                                    mount() does a full rendering, alternative to our renderIntoDocument
                                </ListItem>
                            </Appear>
                            <Appear>
                                <ListItem textSize="40px">
                                    render() performs rendering of react components to static HTML
                                </ListItem>
                            </Appear>
                        </List>
                    </Slide>

                    <Slide transition={["zoom", "fade"]} bgColor="primary" textColor="white">
                        <Text textAlign="left" textColor="white" margin="20px 10px">Different interfaces for rendering with TestUtils and ShallowTestUtils.
                        Method names for finders are not consistent and sometimes cryptical:</Text>
                        <CodePane lang="js" textSize="20px">TestUtils.scryRenderedComponentsWithType()</CodePane>
                        <CodePane lang="js" textSize="20px">ShallowTestUtils.findAllWithClass()</CodePane>
                    </Slide>

                    <Slide transition={["zoom", "fade"]} bgColor="primary" textColor="white">
                        <Text textColor="white" fit margin="20px 10px">In Enzyme its all covered with method find:</Text>
                        <CodePane lang="js" textSize="20px">searchForm.find('PackageSearch'); // find by type name</CodePane>
                        <CodePane lang="js" textSize="20px">searchForm.find(PackageSearch); // find by type</CodePane>
                        <CodePane lang="js" textSize="20px">searchForm.find('li > a.foo'); // find using selector</CodePane>
                    </Slide>

                    <Slide transition={["zoom", "fade"]} bgColor="primary" textColor="white">
                        <Text textColor="white" fit margin="20px 10px">All return values are wrappers:</Text>
                        <CodePane lang="js" textSize="20px">find(filter(map()))</CodePane>
                        ||

                        V
                        <CodePane lang="js" textSize="20px">map().filter().find()</CodePane>
                    </Slide>

                    <Slide transition={["zoom", "fade"]} bgColor="primary" textColor="white">
                        <Text textColor="white" fit margin="20px 10px">Chain finders and combine with other methods:</Text>
                        <CodePane lang="js" textSize="20px">listComponent.find('.item span').find('a').children().first();</CodePane>
                    </Slide>

                    <Slide transition={["zoom", "fade"]} bgColor="primary" textColor="white">
                        <Text textColor="white" fit margin="20px 10px">Make sure that element is on the page:</Text>
                        <CodePane lang="js" textSize="17px" source={require("raw!../assets/code_snippets/expect_not_throw.js.example")} />
                    </Slide>

                    <Slide transition={["zoom", "fade"]} bgColor="primary" textColor="white">
                        <Text textColor="white" fit margin="20px 10px">Another way of doing this:</Text>
                        <CodePane lang="js" textSize="17px" source={require("raw!../assets/code_snippets/find_all.js.example")} />
                    </Slide>

                    <Slide transition={["slide"]}>
                        <Appear fid="1">
                            <Heading size={1} caps fit textColor="primary">
                                Full Width
                            </Heading>
                        </Appear>
                        <Appear fid="2">
                            <Heading size={1} caps fit textColor="tertiary">
                                Adjustable Darkness
                            </Heading>
                        </Appear>
                        <Appear fid="3">
                            <Heading size={1} caps fit textColor="primary">
                                Background Imagery
                            </Heading>
                        </Appear>
                    </Slide>

                    <Slide transition={["zoom", "fade"]} bgColor="primary">
                        <Heading caps fit>Flexible Layouts</Heading>
                        <Layout>
                        <Fill>
                        <Heading size={4} caps textColor="secondary" bgColor="white" margin={10}>
                        Left
                        </Heading>
                        </Fill>
                        <Fill>
                        <Heading size={4} caps textColor="secondary" bgColor="white" margin={10}>
                        Right
                        </Heading>
                        </Fill>
                        </Layout>
                    </Slide>

                    <Slide transition={["slide"]} bgColor="black">

                        <Quote>Wonderfully formatted quotes</Quote>
                        Ken Wheeler

                    </Slide>

                    <Slide transition={["slide", "spin"]} bgColor="primary">
                        <Heading caps fit size={1} textColor="tertiary">
                            Smooth
                        </Heading>
                        <Heading caps fit size={1} textColor="secondary">
                            Combinable Transitions
                        </Heading>
                    </Slide>

                    <Slide transition={["fade"]} bgColor="secondary" textColor="primary">
                        <List>
                            <Appear><ListItem>Inline style based theme system</ListItem></Appear>
                            <Appear><ListItem>Autofit text</ListItem></Appear>
                            <Appear><ListItem>Flexbox layout system</ListItem></Appear>
                            <Appear><ListItem>React-Router navigation</ListItem></Appear>
                            <Appear><ListItem>PDF export</ListItem></Appear>
                            <Appear><ListItem>And...</ListItem></Appear>
                        </List>
                    </Slide>

                </Deck>
            </Spectacle>
        );
    }
}
<commit_msg>Duplicate Slide for find chain, to avoid backward navigation<commit_after>import React from "react";

import {
    Appear,
    BlockQuote,
    Cite,
    CodePane,
    Deck,
    Fill,
    Heading,
    Image,
    Layout,
    ListItem,
    List,
    Quote,
    Slide,
    Spectacle,
    Text
} from "spectacle";

import preloader from "spectacle/lib/utils/preloader";
import createTheme from "spectacle/lib/themes/default";

require("normalize.css");
require("spectacle/lib/themes/default/index.css");

const images = {
    runningTests: require("../assets/running_tests.gif")
};

preloader(images);

const theme = createTheme({
    primary: "#5a5255",
    blue: "#1b85b8"
});

const imageSrc = (name) => images[name].replace("/", "");

export default class Presentation extends React.Component {
    render() {
        return (
            <Spectacle theme={theme}>
                <Deck transition={["zoom", "slide"]} transitionDuration={500}>

                    <Slide transition={["slide"]} bgColor="primary" notes="Some notes for the slide">
                        <Heading size={3} caps textColor="white">Enzyme</Heading>
                        <Image src={imageSrc("runningTests")} margin="0px auto 40px" width="850px" height="537px"/>
                    </Slide>

                    <Slide transition={["slide"]} bgColor="primary" textColor="white">
                        <Heading size={3} caps textColor="white">Why?</Heading>
                        <List>
                            <Appear><ListItem textSize="60px">Make tests more readable</ListItem></Appear>
                            <Appear><ListItem textSize="60px">Less boilerplate</ListItem></Appear>
                            <Appear><ListItem textSize="60px">Simplify common use cases</ListItem></Appear>
                        </List>
                    </Slide>

                    <Slide transition={["zoom", "fade"]} bgColor="primary" textColor="white">
                        <CodePane
                            source={require("raw!../assets/code_snippets/import_enzyme.js.example")}
                            lang="jsx"
                            textSize="20px" />
                        <List>
                            <Appear>
                                <ListItem textSize="40px">
                                    Shallow rendering is the preferable and the fastest way of rendering
                                </ListItem>
                            </Appear>
                            <Appear>
                                <ListItem textSize="38px" margin="40px 0">
                                    mount() does a full rendering, alternative to our renderIntoDocument
                                </ListItem>
                            </Appear>
                            <Appear>
                                <ListItem textSize="40px">
                                    render() performs rendering of react components to static HTML
                                </ListItem>
                            </Appear>
                        </List>
                    </Slide>

                    <Slide transition={["zoom", "fade"]} bgColor="primary" textColor="white">
                        <Text textAlign="left" textColor="white" margin="20px 10px">Different interfaces for rendering with TestUtils and ShallowTestUtils.
                        Method names for finders are not consistent and sometimes cryptical:</Text>
                        <CodePane lang="js" textSize="20px">TestUtils.scryRenderedComponentsWithType()</CodePane>
                        <CodePane lang="js" textSize="20px">ShallowTestUtils.findAllWithClass()</CodePane>
                    </Slide>

                    <Slide transition={["zoom", "fade"]} bgColor="primary" textColor="white">
                        <Text textColor="white" fit margin="20px 10px">In Enzyme its all covered with method find:</Text>
                        <CodePane lang="js" textSize="20px">searchForm.find('PackageSearch'); // find by type name</CodePane>
                        <CodePane lang="js" textSize="20px">searchForm.find(PackageSearch); // find by type</CodePane>
                        <CodePane lang="js" textSize="20px">searchForm.find('li > a.foo'); // find using selector</CodePane>
                    </Slide>

                    <Slide transition={["zoom", "fade"]} bgColor="primary" textColor="white">
                        <Text textColor="white" fit margin="20px 10px">All return values are wrappers:</Text>
                        <CodePane lang="js" textSize="20px">find(filter(map()))</CodePane>
                        ||

                        V
                        <CodePane lang="js" textSize="20px">map().filter().find()</CodePane>
                    </Slide>

                    <Slide transition={["zoom", "fade"]} bgColor="primary" textColor="white">
                        <Text textColor="white" fit margin="20px 10px">Chain finders and combine with other methods:</Text>
                        <CodePane lang="js" textSize="20px">listComponent.find('.item span').find('a').children().first();</CodePane>
                    </Slide>

                    <Slide transition={["zoom", "fade"]} bgColor="primary" textColor="white">
                        <Text textColor="white" fit margin="20px 10px">Make sure that element is on the page:</Text>
                        <CodePane lang="js" textSize="17px" source={require("raw!../assets/code_snippets/expect_not_throw.js.example")} />
                    </Slide>

                    <Slide transition={["zoom", "fade"]} bgColor="primary" textColor="white">
                        <Text textColor="white" fit margin="20px 10px">Another way of doing this:</Text>
                        <CodePane lang="js" textSize="17px" source={require("raw!../assets/code_snippets/find_all.js.example")} />
                    </Slide>

                    <Slide transition={["zoom", "fade"]} bgColor="primary" textColor="white">
                        <Text textColor="white" fit margin="20px 10px">Chain won't throw and always return a wrapper:</Text>
                        <CodePane lang="js" textSize="20px">listComponent.find('.item span').find('a').children().first();</CodePane>
                    </Slide>

                    <Slide transition={["slide"]}>
                        <Appear fid="1">
                            <Heading size={1} caps fit textColor="primary">
                                Full Width
                            </Heading>
                        </Appear>
                        <Appear fid="2">
                            <Heading size={1} caps fit textColor="tertiary">
                                Adjustable Darkness
                            </Heading>
                        </Appear>
                        <Appear fid="3">
                            <Heading size={1} caps fit textColor="primary">
                                Background Imagery
                            </Heading>
                        </Appear>
                    </Slide>

                    <Slide transition={["zoom", "fade"]} bgColor="primary">
                        <Heading caps fit>Flexible Layouts</Heading>
                        <Layout>
                        <Fill>
                        <Heading size={4} caps textColor="secondary" bgColor="white" margin={10}>
                        Left
                        </Heading>
                        </Fill>
                        <Fill>
                        <Heading size={4} caps textColor="secondary" bgColor="white" margin={10}>
                        Right
                        </Heading>
                        </Fill>
                        </Layout>
                    </Slide>

                    <Slide transition={["slide"]} bgColor="black">

                        <Quote>Wonderfully formatted quotes</Quote>
                        Ken Wheeler

                    </Slide>

                    <Slide transition={["slide", "spin"]} bgColor="primary">
                        <Heading caps fit size={1} textColor="tertiary">
                            Smooth
                        </Heading>
                        <Heading caps fit size={1} textColor="secondary">
                            Combinable Transitions
                        </Heading>
                    </Slide>

                    <Slide transition={["fade"]} bgColor="secondary" textColor="primary">
                        <List>
                            <Appear><ListItem>Inline style based theme system</ListItem></Appear>
                            <Appear><ListItem>Autofit text</ListItem></Appear>
                            <Appear><ListItem>Flexbox layout system</ListItem></Appear>
                            <Appear><ListItem>React-Router navigation</ListItem></Appear>
                            <Appear><ListItem>PDF export</ListItem></Appear>
                            <Appear><ListItem>And...</ListItem></Appear>
                        </List>
                    </Slide>

                </Deck>
            </Spectacle>
        );
    }
}
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';

export default class FilePreview extends Component {

  handleClickDelete(path) {
    const { onClickDelete } = this.props;
    const confirm = window.confirm("Are you sure that you want to delete this file?");
    if (confirm) {
      const filename = path.substring(path.lastIndexOf('/') + 1);
      onClickDelete(filename);
    }
  }

  render() {
    const { file } = this.props;
    const extension = file.extname.substring(1);
    const image = /png|jpg|gif|jpeg/.test(extension);
    return (

        {
          image && <img src={`data:image/${extension};base64,${file.encoded_content}`} />
        }
        {
          !image &&

        }

        {file.path}
        <button onClick={() => this.handleClickDelete(file.path)} className="delete" title="Delete file">x</button>

    );
  }
}

FilePreview.propTypes = {
  file: PropTypes.object.isRequired,
  onClickDelete: PropTypes.func.isRequired
};
<commit_msg>show filename when deleting a static file<commit_after>import React, { Component, PropTypes } from 'react';

export default class FilePreview extends Component {

  handleClickDelete(path) {
    const { onClickDelete } = this.props;
    const filename = path.substring(path.lastIndexOf('/') + 1);
    const confirm = window.confirm(`Are you sure that you want to delete "${filename}"?`);
    if (confirm) {
      onClickDelete(filename);
    }
  }

  render() {
    const { file } = this.props;
    const extension = file.extname.substring(1);
    const image = /png|jpg|gif|jpeg/.test(extension);
    return (

        {
          image && <img src={`data:image/${extension};base64,${file.encoded_content}`} />
        }
        {
          !image &&

        }

        {file.path}
        <button onClick={() => this.handleClickDelete(file.path)} className="delete" title="Delete file">x</button>

    );
  }
}

FilePreview.propTypes = {
  file: PropTypes.object.isRequired,
  onClickDelete: PropTypes.func.isRequired
};
<|endoftext|>


<commit_before>

function Lecture(lecturer_name, name, text, url, cost) {
	this.lecturer_name = lecturer_name;
    this.name = name;
    this.text = text;
    this.url = url;
	this.cost = cost;
    this.patience = (500 - Player.volunteers_memory) * 0.1 + Lecture.hype + Player.knowledge;
    this.is_performed = 0;
}

	Lecture.hype = 0;
	Lecture.accepted_lectures_counter = 0;

 Lecture.generateLecture = function(old_lecturer) {
 	var lecturer_name = "";
 	if (old_lecturer) {
 		lecturer_name = old_lecturer;
 	}
 	else {
	 	var first_name = ['Екатерина', 'Оксана', 'Александр', 'Максим', 'Евгений', 'Григорий', 'Николай'];
	 	var second_name = ['Хомяк', 'Морж', 'Бро', 'Зло', 'Добро', 'Сыч', 'Попович'];
	 	lecturer_name = first_name[Math.floor(Math.random() * first_name.length)] + " " +
	 						second_name[Math.floor(Math.random() * second_name.length)];
 	}

 	var noun = ["Гарри Поттер", "15х4", "Биологическое оружие", "Космическая станция", "Атомные реакторы", "Садоводство", "Дзен", "Зомби", "Наркотики", "ГМО", "Хофштадтер"];
 	var second_noun = ["методы", "фунции", "генератор", "оружие", "открытие", "создание", "искусство", "принципы", "основы", "попытка", "метафизика"];
 	var adjective = ["рационального", "социального", "случайного", "массового", "наименьшего", "сознательного", "принципиального", "нормального", "культурного", "медленного", "качественного"];
 	var supplement = ["мышления", "менеджмента", "значения", "поражения", "котика", "существования", "управления", "генератора", "употребления", "обьяснения", "познания"];

 	var name = noun[Math.floor(Math.random() * noun.length)] + " как " +
 			second_noun[Math.floor(Math.random() * second_noun.length)] + " " +
 			adjective[Math.floor(Math.random() * adjective.length)] + " " +
 			supplement[Math.floor(Math.random() * supplement.length)];

 			//message(name + ". " + lecturer_name);
 	var cost = Lecture.generate_offered_lecture_cost();

 	var new_lecture = new Lecture(name, lecturer_name, " ", "https://15x4.org/lecture/random/", cost);
 	if (!old_lecturer) lectures.offered.push(new_lecture);

 	return new_lecture;
 };

 Lecture.accept_lecture = function(lecture_id) {
 	if (Player.action_points < 1 ) {
        message("Not enough action points.");
        return false;
	}

 	if (Player.withdrawArray(lectures.offered[lecture_id].cost)) {
	    Player.action_points--;
	    lectures.db.push(lectures.offered[lecture_id]);
	 	lectures.offered.splice(lecture_id, 1);
	 	console.log("Lecture has accepted");
	 	Lecture.accepted_lectures_counter++;
 	}
 }

 Lecture.skip_lecture = function(lecture_id) {
 	if (Player.action_points < 1) {
        message("Not enough action points.");
        return false;
    }
    else {
    	Player.action_points--;
	 	var lecture = lectures.offered[lecture_id];
	 	var name = lecture.lecturer_name;
	 	lectures.offered[lecture_id] = Lecture.generateLecture(name);
 	}
 }

 Lecture.generate_offered_lecture_cost = function () {
 	var random_resource = resources[Math.floor(Math.random() * resources.length)];
 	var random_resource_cost = resources_rates[random_resource] * (1 + Lecture.accepted_lectures_counter);
 	var offered_lecture_cost = {};

 	offered_lecture_cost[random_resource] = random_resource_cost;
 	console.log(offered_lecture_cost);
	return offered_lecture_cost;

 }

 Lecture.tick = function () {
 	lectures.offered.forEach(function (lecture, id) {
 		if (lectures.offered[id].patience > 0) lectures.offered[id].patience--;
 		else {
 			message("Lecturer has disappointed and gone");
 			lectures.offered.splice(id, 1);
 		}
 	});

 	if (Lecture.hype > 0) {
 		if (rand(0, 100) < Lecture.hype * 0.1) {
 			Lecture.generateLecture();
 			message("New lecturer had come");
 			Player.revealSecret('offered_lecture');
 		}
 		Lecture.hype--;
 	}
 }<commit_msg>add sintax<commit_after>

function Lecture(lecturer_name, name, text, url, cost) {
	this.lecturer_name = lecturer_name;
    this.name = name;
    this.text = text;
    this.url = url;
	this.cost = cost;
    this.patience = (500 - Player.volunteers_memory) * 0.1 + Lecture.hype + Player.knowledge;
    this.is_performed = 0;
};

	Lecture.hype = 0;
	Lecture.accepted_lectures_counter = 0;

 Lecture.generateLecture = function(old_lecturer) {
 	var lecturer_name = "";
 	if (old_lecturer) {
 		lecturer_name = old_lecturer;
 	}
 	else {
	 	var first_name = ['Екатерина', 'Оксана', 'Александр', 'Максим', 'Евгений', 'Григорий', 'Николай'];
	 	var second_name = ['Хомяк', 'Морж', 'Бро', 'Зло', 'Добро', 'Сыч', 'Попович'];
	 	lecturer_name = first_name[Math.floor(Math.random() * first_name.length)] + " " +
	 						second_name[Math.floor(Math.random() * second_name.length)];
 	}

 	var noun = ["Гарри Поттер", "15х4", "Биологическое оружие", "Космическая станция", "Атомные реакторы", "Садоводство", "Дзен", "Зомби", "Наркотики", "ГМО", "Хофштадтер"];
 	var second_noun = ["методы", "фунции", "генератор", "оружие", "открытие", "создание", "искусство", "принципы", "основы", "попытка", "метафизика"];
 	var adjective = ["рационального", "социального", "случайного", "массового", "наименьшего", "сознательного", "принципиального", "нормального", "культурного", "медленного", "качественного"];
 	var supplement = ["мышления", "менеджмента", "значения", "поражения", "котика", "существования", "управления", "генератора", "употребления", "обьяснения", "познания"];

 	var name = noun[Math.floor(Math.random() * noun.length)] + " как " +
 			second_noun[Math.floor(Math.random() * second_noun.length)] + " " +
 			adjective[Math.floor(Math.random() * adjective.length)] + " " +
 			supplement[Math.floor(Math.random() * supplement.length)];

 			//message(name + ". " + lecturer_name);
 	var cost = Lecture.generate_offered_lecture_cost();

 	var new_lecture = new Lecture(name, lecturer_name, " ", "https://15x4.org/lecture/random/", cost);
 	if (!old_lecturer) lectures.offered.push(new_lecture);

 	return new_lecture;
 };

 Lecture.accept_lecture = function(lecture_id) {
 	if (Player.action_points < 1 ) {
        message("Not enough action points.");
        return false;
	}

 	if (Player.withdrawArray(lectures.offered[lecture_id].cost)) {
	    Player.action_points--;
	    lectures.db.push(lectures.offered[lecture_id]);
	 	lectures.offered.splice(lecture_id, 1);
	 	console.log("Lecture has accepted");
	 	Lecture.accepted_lectures_counter++;
 	}
 }

 Lecture.skip_lecture = function(lecture_id) {
 	if (Player.action_points < 1) {
        message("Not enough action points.");
        return false;
    }
    else {
    	Player.action_points--;
	 	var lecture = lectures.offered[lecture_id];
	 	var name = lecture.lecturer_name;
	 	lectures.offered[lecture_id] = Lecture.generateLecture(name);
 	}
 }

 Lecture.generate_offered_lecture_cost = function () {
 	var random_resource = resources[Math.floor(Math.random() * resources.length)];
 	var random_resource_cost = resources_rates[random_resource] * (1 + Lecture.accepted_lectures_counter);
 	var offered_lecture_cost = {};

 	offered_lecture_cost[random_resource] = random_resource_cost;
 	console.log(offered_lecture_cost);
	return offered_lecture_cost;

 }

 Lecture.tick = function () {
 	lectures.offered.forEach(function (lecture, id) {
 		if (lectures.offered[id].patience > 0) lectures.offered[id].patience--;
 		else {
 			message("Lecturer has disappointed and gone");
 			lectures.offered.splice(id, 1);
 		}
 	});

 	if (Lecture.hype > 0) {
 		if (rand(0, 100) < Lecture.hype * 0.1) {
 			Lecture.generateLecture();
 			message("New lecturer had come");
 			Player.revealSecret('offered_lecture');
 		}
 		Lecture.hype--;
 	}
 }<|endoftext|>


<commit_before>var conn = require('./conn.js');
var logger = (require('../logging/vip-winston')).Logger;

var endOfLine = require('os').EOL;
var delim = ',';

var makeCSVSafe = function(value){
  value = value && value.toString() || '';
  // the delim is in our value we need to put quotes around our value
  if(value.indexOf(delim)!==-1){

    // if we are putting quotes around our value, we need to escape any existing quotes first
    value = value.replace(/"/g, '""');

    value = '"' + value + '"';
  }

  return value;
}

var makeCSVRow = function(values) {
  return values.map(makeCSVSafe).join(delim) + endOfLine;
}

var header = ["Feed", "Severity", "Scope", "ID", "Error Type", "Error Data"];

var csvFilename = function(feedId, scope) {
  scopeName = scope || "Full";
  return feedId.replace(/ /g, '-') + "-" + scopeName + "ErrorReport.csv";
}

var errorReport = function(innerJoins, where, params, scope) {
  var errorQuery = "SELECT v.* FROM validations v INNER JOIN results r ON r.id = v.results_id " +
      innerJoins +
      " WHERE r.public_id=$1 " +
      (where ? " AND " + where : "") +
      " ORDER BY v.scope, v.identifier";
  return function(req, res) {
    var feedid = decodeURIComponent(req.params.feedid);

    try {
      conn.query(function(client) {
        var queryParams = ['feedid'].concat(params).map(function(param) { return decodeURIComponent(req.params[param]); });

        res.header("Content-Disposition", "attachment; filename=" + csvFilename(feedid, scope));
        res.setHeader('Content-type', 'text/csv');
        res.charset = 'UTF-8';

        res.write(makeCSVRow(header));

        var query = client.query(errorQuery, queryParams);

        query.on("row", function(row, result) {
          res.write(makeCSVRow([feedid, row.severity, row.scope, row.identifier, row.error_type, row.error_data]));
        });

        query.on("end", function(result) {
          res.end();
        });

        query.on("error", function(e) {
          logger.error("Generating an error report for '" + feedid + "' caused " + e.message);
          // If the query doesn't return anything before we hit our connection's
          // timeout, we'll only have added CSV headers to the response.
          res.end();
        });
      });
    }
    catch (e) {}
  }
}

var xmlTreeValidationQuery =
"SELECT v.severity, v.scope, v.path, v.parent_element_id AS identifier, \
        v.error_type, v.error_data \
 FROM xml_tree_validations v \
 INNER JOIN results r ON r.id = v.results_id \
 WHERE r.public_id = $1";

var scopedXmlTreeValidationQuery = function(elementTypes) {
  return "SELECT v.severity, v.scope, v.path, v.parent_element_id AS identifier, \
        v.error_type, v.error_data \
 FROM xml_tree_validations v \
 INNER JOIN results r ON r.id = v.results_id \
 WHERE r.public_id = $1 AND v.path ~ 'VipObject.0." + elementTypes.join("|") + ".*'";
}

var elementTypeAndScopeXmlTreeValidationQuery = function(elementType, scope) {
  return "SELECT v.severity, v.scope, v.path, v.parent_element_id AS identifier, \
        v.error_type, v.error_data \
 FROM xml_tree_validations v \
 INNER JOIN results r ON r.id = v.results_id \
 WHERE r.public_id = $1 AND (v.path ~ 'VipObject.0."+ elementType + ".*' or v.scope like '" + scope + "%')";
}

var elementTypeAndScopeXmlTreeValidationErrorReport = function(elementType, scope) {
  // var elementTypes = Array.prototype.slice.call(arguments);

  return function(req, res) {
    var header = ["Feed", "Severity", "Scope", "Path", "ID", "Error Type", "Error Data"];
    var feedid = decodeURIComponent(req.params.feedid);

    conn.query(function(client) {
      res.header("Content-Disposition", "attachment; filename=" + csvFilename(feedid, elementType));
      res.setHeader('Content-type', 'text/csv');
      res.charset = 'UTF-8';

      res.write(makeCSVRow(header));
      // res.end();

      var query = client.query(elementTypeAndScopeXmlTreeValidationQuery(elementType, scope), [feedid]);

      query.on("row", function(row, result) {
        res.write(makeCSVRow([feedid,
                              row.severity,
                              row.scope,
                              row.path,
                              row.identifier,
                              row.error_type,
                              row.error_data]));
      });

      query.on("end", function(result) {
        res.end();
      });
    });
  };
}

var scopedXmlTreeValidationErrorReport = function() {
  var elementTypes = Array.prototype.slice.call(arguments);

  return function(req, res) {
    var header = ["Feed", "Severity", "Scope", "Path", "ID", "Error Type", "Error Data"];
    var feedid = decodeURIComponent(req.params.feedid);

    conn.query(function(client) {
      res.header("Content-Disposition", "attachment; filename=" + csvFilename(feedid, elementTypes[0]));
      res.setHeader('Content-type', 'text/csv');
      res.charset = 'UTF-8';

      res.write(makeCSVRow(header));

      var query = client.query(scopedXmlTreeValidationQuery(elementTypes), [feedid]);

      query.on("row", function(row, result) {
        res.write(makeCSVRow([feedid,
                              row.severity,
                              row.scope,
                              row.path,
                              row.identifier,
                              row.error_type,
                              row.error_data]));
      });

      query.on("end", function(result) {
        res.end();
      });
    });
  };
}

var xmlTreeValidationErrorReport = function(req, res) {
  var header = ["Feed", "Severity", "Scope", "Path", "ID", "Error Type", "Error Data"];
  var feedid = decodeURIComponent(req.params.feedid);

  conn.query(function(client) {
    res.header("Content-Disposition", "attachment; filename=" + csvFilename(feedid));
    res.setHeader('Content-type', 'text/csv');
    res.charset = 'UTF-8';

    res.write(makeCSVRow(header));

    var query = client.query(xmlTreeValidationQuery, [feedid]);

    query.on("row", function(row, result) {
      res.write(makeCSVRow([feedid,
                            row.severity,
                            row.scope,
                            row.path,
                            row.identifier,
                            row.error_type,
                            row.error_data]));
    });

    query.on("end", function(result) {
      res.end();
    });
  });
}

var xmlTreeLocalityErrorReport = function(req, res) {
  var header = ["Feed", "Severity", "Scope", "Path", "ID", "Error Type", "Error Data"];
  var feedid = decodeURIComponent(req.params.feedid);
  var localityid = decodeURIComponent(req.params.localityId)
  conn.query(function(client) {

    res.header("Content-Disposition", "attachment; filename=" + csvFilename(feedid));
    res.setHeader('Content-type', 'text/csv');
    res.charset = 'UTF-8';

    res.write(makeCSVRow(header));

    var query = client.query('select * from v5_dashboard.locality_error_report($1, $2)', [feedid, localityid]);

    query.on("row", function(row, result) {
      res.write(makeCSVRow([feedid,
                            row.severity,
                            row.scope,
                            row.path,
                            row.identifier,
                            row.error_type,
                            row.error_data]));
    });

    query.on("end", function(result) {
      res.end();
    });
  });

}

var pollingLocationAddressReport = function(req, res) {
  var header = ["Locality Name", "Precinct Name", "Address Location Name", "Address Line 1", "Address Line 2", "Address Line 3", "Address City", "Address State",  "Address Zip", "Polling Location Id"];
  var feedid = decodeURIComponent(req.params.feedid);
  conn.query(function(client) {

    res.header("Content-Disposition", "attachment; filename=" + csvFilename(feedid, 'PollingLocationAddress'));
    res.setHeader('Content-type', 'text/csv');
    res.charset = 'UTF-8';

    res.write(makeCSVRow(header));

    var query = client.query('select * from v3_dashboard.polling_location_readable_report($1)', [feedid]);

    query.on("row", function(row, result) {
      res.write(makeCSVRow([row.locality_name,
                            row.precinct_name,
                            row.address_location_name,
                            row.address_line1,
                            row.address_line2,
                            row.address_line3,
                            row.address_city,
                            row.address_state,
                            row.address_zip,
                            row.polling_location_id]));
    });

    query.on("end", function(result) {
      res.end();
    });
  });
}

var earlyVoteSiteAddressReport = function(req, res) {
  var header = ["Locality Name", "Early Vote Site Name", "Address Location Name", "Address Line 1", "Address Line 2", "Address Line 3", "Address City", "Address State",  "Address Zip", "Polling Location Id"];
  var feedid = decodeURIComponent(req.params.feedid);
  conn.query(function(client) {

    res.header("Content-Disposition", "attachment; filename=" + csvFilename(feedid, 'EarlyVoteSiteAddress'));
    res.setHeader('Content-type', 'text/csv');
    res.charset = 'UTF-8';

    res.write(makeCSVRow(header));

    var query = client.query('select * from v3_dashboard.early_vote_location_address_report($1)', [feedid]);

    query.on("row", function(row, result) {
      res.write(makeCSVRow([row.locality_name,
                            row.early_vote_site_name,
                            row.address_location_name,
                            row.address_line1,
                            row.address_line2,
                            row.address_line3,
                            row.address_city,
                            row.address_state,
                            row.address_zip,
                            row.polling_location_id]));
    });

    query.on("end", function(result) {
      res.end();
    });
  });
}

module.exports = {
  xmlTreeLocalityErrorReport: xmlTreeLocalityErrorReport,
  errorReport: errorReport,
  fullErrorReport: errorReport("", "", []),
  scopedErrorReport: function(scope) {
    return errorReport("", "v.scope = '" + scope + "'", [], scope);
  },
  xmlTreeValidationErrorReport: xmlTreeValidationErrorReport,
  scopedXmlTreeValidationErrorReport: scopedXmlTreeValidationErrorReport,
  pollingLocationAddressReport: pollingLocationAddressReport,
  earlyVoteSiteAddressReport: earlyVoteSiteAddressReport,
  elementTypeAndScopeXmlTreeValidationErrorReport: elementTypeAndScopeXmlTreeValidationErrorReport
}
<commit_msg>removing comments<commit_after>var conn = require('./conn.js');
var logger = (require('../logging/vip-winston')).Logger;

var endOfLine = require('os').EOL;
var delim = ',';

var makeCSVSafe = function(value){
  value = value && value.toString() || '';
  // the delim is in our value we need to put quotes around our value
  if(value.indexOf(delim)!==-1){

    // if we are putting quotes around our value, we need to escape any existing quotes first
    value = value.replace(/"/g, '""');

    value = '"' + value + '"';
  }

  return value;
}

var makeCSVRow = function(values) {
  return values.map(makeCSVSafe).join(delim) + endOfLine;
}

var header = ["Feed", "Severity", "Scope", "ID", "Error Type", "Error Data"];

var csvFilename = function(feedId, scope) {
  scopeName = scope || "Full";
  return feedId.replace(/ /g, '-') + "-" + scopeName + "ErrorReport.csv";
}

var errorReport = function(innerJoins, where, params, scope) {
  var errorQuery = "SELECT v.* FROM validations v INNER JOIN results r ON r.id = v.results_id " +
      innerJoins +
      " WHERE r.public_id=$1 " +
      (where ? " AND " + where : "") +
      " ORDER BY v.scope, v.identifier";
  return function(req, res) {
    var feedid = decodeURIComponent(req.params.feedid);

    try {
      conn.query(function(client) {
        var queryParams = ['feedid'].concat(params).map(function(param) { return decodeURIComponent(req.params[param]); });

        res.header("Content-Disposition", "attachment; filename=" + csvFilename(feedid, scope));
        res.setHeader('Content-type', 'text/csv');
        res.charset = 'UTF-8';

        res.write(makeCSVRow(header));

        var query = client.query(errorQuery, queryParams);

        query.on("row", function(row, result) {
          res.write(makeCSVRow([feedid, row.severity, row.scope, row.identifier, row.error_type, row.error_data]));
        });

        query.on("end", function(result) {
          res.end();
        });

        query.on("error", function(e) {
          logger.error("Generating an error report for '" + feedid + "' caused " + e.message);
          // If the query doesn't return anything before we hit our connection's
          // timeout, we'll only have added CSV headers to the response.
          res.end();
        });
      });
    }
    catch (e) {}
  }
}

var xmlTreeValidationQuery =
"SELECT v.severity, v.scope, v.path, v.parent_element_id AS identifier, \
        v.error_type, v.error_data \
 FROM xml_tree_validations v \
 INNER JOIN results r ON r.id = v.results_id \
 WHERE r.public_id = $1";

var scopedXmlTreeValidationQuery = function(elementTypes) {
  return "SELECT v.severity, v.scope, v.path, v.parent_element_id AS identifier, \
        v.error_type, v.error_data \
 FROM xml_tree_validations v \
 INNER JOIN results r ON r.id = v.results_id \
 WHERE r.public_id = $1 AND v.path ~ 'VipObject.0." + elementTypes.join("|") + ".*'";
}

var elementTypeAndScopeXmlTreeValidationQuery = function(elementType, scope) {
  return "SELECT v.severity, v.scope, v.path, v.parent_element_id AS identifier, \
        v.error_type, v.error_data \
 FROM xml_tree_validations v \
 INNER JOIN results r ON r.id = v.results_id \
 WHERE r.public_id = $1 AND (v.path ~ 'VipObject.0."+ elementType + ".*' or v.scope like '" + scope + "%')";
}

var elementTypeAndScopeXmlTreeValidationErrorReport = function(elementType, scope) {

  return function(req, res) {
    var header = ["Feed", "Severity", "Scope", "Path", "ID", "Error Type", "Error Data"];
    var feedid = decodeURIComponent(req.params.feedid);

    conn.query(function(client) {
      res.header("Content-Disposition", "attachment; filename=" + csvFilename(feedid, elementType));
      res.setHeader('Content-type', 'text/csv');
      res.charset = 'UTF-8';

      res.write(makeCSVRow(header));

      var query = client.query(elementTypeAndScopeXmlTreeValidationQuery(elementType, scope), [feedid]);

      query.on("row", function(row, result) {
        res.write(makeCSVRow([feedid,
                              row.severity,
                              row.scope,
                              row.path,
                              row.identifier,
                              row.error_type,
                              row.error_data]));
      });

      query.on("end", function(result) {
        res.end();
      });
    });
  };
}

var scopedXmlTreeValidationErrorReport = function() {
  var elementTypes = Array.prototype.slice.call(arguments);

  return function(req, res) {
    var header = ["Feed", "Severity", "Scope", "Path", "ID", "Error Type", "Error Data"];
    var feedid = decodeURIComponent(req.params.feedid);

    conn.query(function(client) {
      res.header("Content-Disposition", "attachment; filename=" + csvFilename(feedid, elementTypes[0]));
      res.setHeader('Content-type', 'text/csv');
      res.charset = 'UTF-8';

      res.write(makeCSVRow(header));

      var query = client.query(scopedXmlTreeValidationQuery(elementTypes), [feedid]);

      query.on("row", function(row, result) {
        res.write(makeCSVRow([feedid,
                              row.severity,
                              row.scope,
                              row.path,
                              row.identifier,
                              row.error_type,
                              row.error_data]));
      });

      query.on("end", function(result) {
        res.end();
      });
    });
  };
}

var xmlTreeValidationErrorReport = function(req, res) {
  var header = ["Feed", "Severity", "Scope", "Path", "ID", "Error Type", "Error Data"];
  var feedid = decodeURIComponent(req.params.feedid);

  conn.query(function(client) {
    res.header("Content-Disposition", "attachment; filename=" + csvFilename(feedid));
    res.setHeader('Content-type', 'text/csv');
    res.charset = 'UTF-8';

    res.write(makeCSVRow(header));

    var query = client.query(xmlTreeValidationQuery, [feedid]);

    query.on("row", function(row, result) {
      res.write(makeCSVRow([feedid,
                            row.severity,
                            row.scope,
                            row.path,
                            row.identifier,
                            row.error_type,
                            row.error_data]));
    });

    query.on("end", function(result) {
      res.end();
    });
  });
}

var xmlTreeLocalityErrorReport = function(req, res) {
  var header = ["Feed", "Severity", "Scope", "Path", "ID", "Error Type", "Error Data"];
  var feedid = decodeURIComponent(req.params.feedid);
  var localityid = decodeURIComponent(req.params.localityId)
  conn.query(function(client) {

    res.header("Content-Disposition", "attachment; filename=" + csvFilename(feedid));
    res.setHeader('Content-type', 'text/csv');
    res.charset = 'UTF-8';

    res.write(makeCSVRow(header));

    var query = client.query('select * from v5_dashboard.locality_error_report($1, $2)', [feedid, localityid]);

    query.on("row", function(row, result) {
      res.write(makeCSVRow([feedid,
                            row.severity,
                            row.scope,
                            row.path,
                            row.identifier,
                            row.error_type,
                            row.error_data]));
    });

    query.on("end", function(result) {
      res.end();
    });
  });

}

var pollingLocationAddressReport = function(req, res) {
  var header = ["Locality Name", "Precinct Name", "Address Location Name", "Address Line 1", "Address Line 2", "Address Line 3", "Address City", "Address State",  "Address Zip", "Polling Location Id"];
  var feedid = decodeURIComponent(req.params.feedid);
  conn.query(function(client) {

    res.header("Content-Disposition", "attachment; filename=" + csvFilename(feedid, 'PollingLocationAddress'));
    res.setHeader('Content-type', 'text/csv');
    res.charset = 'UTF-8';

    res.write(makeCSVRow(header));

    var query = client.query('select * from v3_dashboard.polling_location_readable_report($1)', [feedid]);

    query.on("row", function(row, result) {
      res.write(makeCSVRow([row.locality_name,
                            row.precinct_name,
                            row.address_location_name,
                            row.address_line1,
                            row.address_line2,
                            row.address_line3,
                            row.address_city,
                            row.address_state,
                            row.address_zip,
                            row.polling_location_id]));
    });

    query.on("end", function(result) {
      res.end();
    });
  });
}

var earlyVoteSiteAddressReport = function(req, res) {
  var header = ["Locality Name", "Early Vote Site Name", "Address Location Name", "Address Line 1", "Address Line 2", "Address Line 3", "Address City", "Address State",  "Address Zip", "Polling Location Id"];
  var feedid = decodeURIComponent(req.params.feedid);
  conn.query(function(client) {

    res.header("Content-Disposition", "attachment; filename=" + csvFilename(feedid, 'EarlyVoteSiteAddress'));
    res.setHeader('Content-type', 'text/csv');
    res.charset = 'UTF-8';

    res.write(makeCSVRow(header));

    var query = client.query('select * from v3_dashboard.early_vote_location_address_report($1)', [feedid]);

    query.on("row", function(row, result) {
      res.write(makeCSVRow([row.locality_name,
                            row.early_vote_site_name,
                            row.address_location_name,
                            row.address_line1,
                            row.address_line2,
                            row.address_line3,
                            row.address_city,
                            row.address_state,
                            row.address_zip,
                            row.polling_location_id]));
    });

    query.on("end", function(result) {
      res.end();
    });
  });
}

module.exports = {
  xmlTreeLocalityErrorReport: xmlTreeLocalityErrorReport,
  errorReport: errorReport,
  fullErrorReport: errorReport("", "", []),
  scopedErrorReport: function(scope) {
    return errorReport("", "v.scope = '" + scope + "'", [], scope);
  },
  xmlTreeValidationErrorReport: xmlTreeValidationErrorReport,
  scopedXmlTreeValidationErrorReport: scopedXmlTreeValidationErrorReport,
  pollingLocationAddressReport: pollingLocationAddressReport,
  earlyVoteSiteAddressReport: earlyVoteSiteAddressReport,
  elementTypeAndScopeXmlTreeValidationErrorReport: elementTypeAndScopeXmlTreeValidationErrorReport
}
<|endoftext|>


<commit_before>const Bignumber = require("bignumber.js")
const randomstring = require("randomstring");
const steamconst = "76561197960265728";
const resolveVanityURL = require("../../util/resolveVanityURL");

async function exec(ctx) {
    if (!ctx.client.steam_connected) {
        return ctx.failure(ctx.strings.get("register_steam_down"));
    }

    let search = ctx.options.join(" ");
    let ID = false;

    if (search.includes("dotabuff.com/players") || search.includes("opendota.com/players")) {
        ID = search.split("/").slice(-1)[0];
    }

    if (search.includes("steamcommunity.com/profiles/")) {
        let search2 = search.split("/").slice(-1)[0];
        if (isNaN(search2)) {
            ID = false;
        } else {
            ID = new Bignumber().minus(steamconst);
        }
    }

    if (search.includes("steamcommunity.com/id/")) {
        try {
            ID = search.split("/").slice(-1)[0];
            if (!ID) ID = search.split("/").slice(-2)[0];
            ID = await resolveVanityURL(ID);
            ID = new Bignumber(ID).minus(steamconst);
        } catch (err) {
            console.error(err);
            return ctx.failure(ctx.strings.get("register_bad_vanity"));
        }
    }

    if (ID === false || isNaN(ID)) {
        return ctx.failure(ctx.strings.get("register_no_id"));
    }

    let res;
    try {
        res = await ctx.client.mika.getPlayer(ID);
    } catch (err) {
        console.error(err);
        return ctx.failure(ctx.strings.get("bot_generic_error"));
    }

    if (!res.profile) {
        return ctx.failure(ctx.strings.get("register_private_account"));
    }

    if (!res.profile.steamid) {
        return ctx.failure(ctx.strings.get("register_no_steam_id"));
    }

    try {
        let rand = randomstring.generate(6);
        await ctx.client.redis.setexAsync(`register:${res.profile.steamid}`, 900, `${rand}:${ctx.author.id}`);

        ctx.client.redis.publish("discord", JSON.stringify({
            code: 3,
            message: "registering a user",
            steam_id: res.profile.steamid
        }));

        let channel = await ctx.author.getDMChannel();
        await channel.createMessage(ctx.strings.all("register_dm", "\n", rand, ctx.client.config.steam_acc_url));
        try { await ctx.message.addReaction("✅") } catch (err) {}
        return Promise.resolve();
    } catch (err) {
        console.error(err);
        return ctx.failure(ctx.strings.get("bot_generic_error"));
    }
}

module.exports = {
    name: "register",
    category: "personal",
    exec
};
<commit_msg>fix register AGASIN<commit_after>const Bignumber = require("bignumber.js")
const randomstring = require("randomstring");
const steamconst = "76561197960265728";
const resolveVanityURL = require("../../util/resolveVanityURL");

async function exec(ctx) {
    if (!ctx.client.steam_connected) {
        return ctx.failure(ctx.strings.get("register_steam_down"));
    }

    let search = ctx.options.join(" ");
    let ID = false;

    if (search.includes("dotabuff.com/players") || search.includes("opendota.com/players")) {
        ID = search.split("/").slice(-1)[0];
    }

    if (search.includes("steamcommunity.com/profiles/")) {
        let search2 = search.split("/").slice(-1)[0];
        if (!search2) search2 = search.split("/").slice(-2)[0];
        if (isNaN(search2)) {
            ID = false;
        } else {
            ID = new Bignumber().minus(steamconst);
        }
    }

    if (search.includes("steamcommunity.com/id/")) {
        try {
            ID = search.split("/").slice(-1)[0];
            if (!ID) ID = search.split("/").slice(-2)[0];
            ID = await resolveVanityURL(ID);
            ID = new Bignumber(ID).minus(steamconst);
        } catch (err) {
            console.error(err);
            return ctx.failure(ctx.strings.get("register_bad_vanity"));
        }
    }

    if (ID === false || isNaN(ID)) {
        return ctx.failure(ctx.strings.get("register_no_id"));
    }

    let res;
    try {
        res = await ctx.client.mika.getPlayer(ID);
    } catch (err) {
        console.error(err);
        return ctx.failure(ctx.strings.get("bot_generic_error"));
    }

    if (!res.profile) {
        return ctx.failure(ctx.strings.get("register_private_account"));
    }

    if (!res.profile.steamid) {
        return ctx.failure(ctx.strings.get("register_no_steam_id"));
    }

    try {
        let rand = randomstring.generate(6);
        await ctx.client.redis.setexAsync(`register:${res.profile.steamid}`, 900, `${rand}:${ctx.author.id}`);

        ctx.client.redis.publish("discord", JSON.stringify({
            code: 3,
            message: "registering a user",
            steam_id: res.profile.steamid
        }));

        let channel = await ctx.author.getDMChannel();
        await channel.createMessage(ctx.strings.all("register_dm", "\n", rand, ctx.client.config.steam_acc_url));
        try { await ctx.message.addReaction("✅") } catch (err) {}
        return Promise.resolve();
    } catch (err) {
        console.error(err);
        return ctx.failure(ctx.strings.get("bot_generic_error"));
    }
}

module.exports = {
    name: "register",
    category: "personal",
    exec
};
<|endoftext|>


<commit_before>angular
    .module(
        'smartHouseGroceryList',
        [
            'ionic',
            'smartHouseGroceryList.home',
            'smartHouseGroceryList.dashboard',
            'smartHouseGroceryList.stockManager',
            'smartHouseGroceryList.buyMode',
            'smartHouseGroceryList.trashMode',
        ]
    )
    .constant(
        'API_URL',
        'https://localhost/bitbucket/bobalazek/silex-web-application-boilerplate/web/api/v1' // WITHOUT leading slash!
    )
    .constant(
        'IS_DESKTOP',
        window.location.protocol !== 'file:'
    )
    .config( function($urlRouterProvider) {
        // Routes
        $urlRouterProvider.otherwise('/');
    })
    .run( function($ionicPlatform) {
        $ionicPlatform.ready(function() {
            if(window.cordova && window.cordova.plugins.Keyboard) {
                cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
            }

            if(window.StatusBar) {
                StatusBar.styleDefault();
            }
        });
    })
    .controller (
        'ApplicationController',
        function ApplicationController($rootScope, $scope) {
            var vm = this;

            return vm;
        }
    )
    .config( function($httpProvider) {
        // Use x-www-form-urlencoded Content-Type
        $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';

        /**
        * The workhorse; converts an object to x-www-form-urlencoded serialization.
        * @param {Object} obj
        * @return {String}
        */
        var param = function(obj) {
            var query = '', name, value, fullSubName, subName, subValue, innerObj, i;

            for(name in obj) {
              value = obj[name];

              if(value instanceof Array) {
                for(i=0; i<value.length; ++i) {
                  subValue = value[i];
                  fullSubName = name + '[' + i + ']';
                  innerObj = {};
                  innerObj[fullSubName] = subValue;
                  query += param(innerObj) + '&';
                }
              }
              else if(value instanceof Object) {
                for(subName in value) {
                  subValue = value[subName];
                  fullSubName = name + '[' + subName + ']';
                  innerObj = {};
                  innerObj[fullSubName] = subValue;
                  query += param(innerObj) + '&';
                }
              }
              else if(value !== undefined && value !== null)
                query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
            }

            return query.length ? query.substr(0, query.length - 1) : query;
        };

        // Override $http service's default transformRequest
        $httpProvider.defaults.transformRequest = [function(data) {
            return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
        }];
    })
;
<commit_msg>Minor fixes on url-encode inzerceptor<commit_after>angular
    .module(
        'smartHouseGroceryList',
        [
            'ionic',
            'smartHouseGroceryList.home',
            'smartHouseGroceryList.dashboard',
            'smartHouseGroceryList.stockManager',
            'smartHouseGroceryList.buyMode',
            'smartHouseGroceryList.trashMode',
        ]
    )
    .constant(
        'API_URL',
        'https://localhost/bitbucket/bobalazek/silex-web-application-boilerplate/web/api/v1' // WITHOUT leading slash!
    )
    .constant(
        'IS_DESKTOP',
        window.location.protocol !== 'file:'
    )
    .config( function($urlRouterProvider) {
        // Routes
        $urlRouterProvider.otherwise('/');
    })
    .run( function($ionicPlatform) {
        $ionicPlatform.ready(function() {
            if(window.cordova && window.cordova.plugins.Keyboard) {
                cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
            }

            if(window.StatusBar) {
                StatusBar.styleDefault();
            }
        });
    })
    .controller (
        'ApplicationController',
        function ApplicationController($rootScope, $scope) {
            var vm = this;

            return vm;
        }
    )
    .config( function($httpProvider) {
        // Use x-www-form-urlencoded Content-Type
        $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';

        /**
        * The workhorse; converts an object to x-www-form-urlencoded serialization.
        * @param {Object} obj
        * @return {String}
        */
        var param = function(obj) {
            var query = '', name, value, fullSubName, subName, subValue, innerObj, i;

            for(name in obj) {
                value = obj[name];

                if(value instanceof Array) {
                    for(i=0; i<value.length; ++i) {
                        subValue = value[i];
                        fullSubName = name + '[' + i + ']';
                        innerObj = {};
                        innerObj[fullSubName] = subValue;
                        query += param(innerObj) + '&';
                    }
                }
                else if(value instanceof Object) {
                    for(subName in value) {
                        subValue = value[subName];
                        fullSubName = name + '[' + subName + ']';
                        innerObj = {};
                        innerObj[fullSubName] = subValue;
                        query += param(innerObj) + '&';
                    }
                }
                else if(value !== undefined && value !== null) {
                    query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
                }
            }

            return query.length ? query.substr(0, query.length - 1) : query;
        };

        // Override $http service's default transformRequest
        $httpProvider.defaults.transformRequest = [function(data) {
            return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
        }];
    })
;
<|endoftext|>