<commit_before>"use strict";

function loadTutorial()
{
    // Only download tutorial if it hasn't been obtained already.
    if ( $( html.tutorialContents ).text() === "" ) {
        downloadTutorial();
    }
}

function downloadTutorial()
{
    var tutorialContainerElement = $( html.tutorialContainer )[0];
    var loadingAnimation = new Spinner().spin( tutorialContainerElement );

    $.get( constants.tutorialUrl, function( data ) {

        // Remove the loading animation.
        loadingAnimation.stop();

        // Tutorial downloaded. Paste it.
        $( html.tutorialContents ).html( data );

        // Apply syntax highlighting.
        // But not for things inside the well, which is used for examples.
        $(':not(.well) pre code').each(function(i, block) {
            hljs.highlightBlock(block);
        });

        // Load the table of contents.
        generateTutorialTableOfContents();
    });
}

function generateTutorialTableOfContents()
{
    var parsedTableOfContents = parseHtmlHeaders( html.tutorialContents );

    var tableOfContentsHtml =
        tableOfContentsHtmlFromData( parsedTableOfContents, false );

    $( html.tutorialTableOfContents ).html( tableOfContentsHtml );

    $( 'body' ).scrollspy({
        target: html.sidebarClass,
        offset: 40
    });

    $( html.tutorialTableOfContentsList ).affix({
        offset: {
            top: 100,
        }
    });
}

function parseHtmlHeaders( root )
{
    var tableOfContentsEntries = [];

    $( root ).find( "h1, h2" ).each( function( index, header ) {

        // Get the header properties.
        var level = $( header ).prop( "tagName" );
        var title = $( header ).text();
        var id = $( header ).attr( "id" );

        // Assign ID if none exists.
        if ( !id ) {
            id = "tutorial-header-" + index;
            $( header ).attr( "id", id );
        }

        // Populate the tree.
        if ( level === "H1" ) {
            tableOfContentsEntries.push(
                tableOfContentsEntry( title, id, [] ) );
        } else if ( level === "H2" ) {
            var latestEntryH1 = tableOfContentsEntries.pop();
            latestEntryH1.children.push(
                tableOfContentsEntry( title, id, [] ) );
            tableOfContentsEntries.push( latestEntryH1 );
        }
    });

    return tableOfContentsEntries;
}

function tableOfContentsEntry( title, id, children )
{
    return {
        title: title,
        id: id,
        children: children,
    };
}

function tableOfContentsHtmlFromData( tableOfContents )
{
    var listItems = tableOfContents.map( function( entry ) {
        return '
' +
               '' +
                entry.title +
                tableOfContentsHtmlFromData( entry.children ) +
               '' +
               '
';
    });

    if ( listItems.length > 0 ) {
        return '
' +
                listItems.join( constants.newlineCharacter ) +
                '
';
    }

    return "";
}
<commit_msg>Placement tweak.<commit_after>"use strict";

function loadTutorial()
{
    // Only download tutorial if it hasn't been obtained already.
    if ( $( html.tutorialContents ).text() === "" ) {
        downloadTutorial();
    }
}

function downloadTutorial()
{
    var tutorialContainerElement = $( html.tutorialContainer )[0];
    var loadingAnimation = new Spinner().spin( tutorialContainerElement );

    $.get( constants.tutorialUrl, function( data ) {

        // Remove the loading animation.
        loadingAnimation.stop();

        // Tutorial downloaded. Paste it.
        $( html.tutorialContents ).html( data );

        // Apply syntax highlighting.
        // But not for things inside the well, which is used for examples.
        $(':not(.well) pre code').each(function(i, block) {
            hljs.highlightBlock(block);
        });

        // Load the table of contents.
        generateTutorialTableOfContents();
    });
}

function generateTutorialTableOfContents()
{
    var parsedTableOfContents = parseHtmlHeaders( html.tutorialContents );

    var tableOfContentsHtml =
        tableOfContentsHtmlFromData( parsedTableOfContents, false );

    $( html.tutorialTableOfContents ).html( tableOfContentsHtml );

    $( 'body' ).scrollspy({
        target: html.sidebarClass,
        offset: 100
    });

    $( html.tutorialTableOfContentsList ).affix({
        offset: {
            top: 100,
        }
    });
}

function parseHtmlHeaders( root )
{
    var tableOfContentsEntries = [];

    $( root ).find( "h1, h2" ).each( function( index, header ) {

        // Get the header properties.
        var level = $( header ).prop( "tagName" );
        var title = $( header ).text();
        var id = $( header ).attr( "id" );

        // Assign ID if none exists.
        if ( !id ) {
            id = "tutorial-header-" + index;
            $( header ).attr( "id", id );
        }

        // Populate the tree.
        if ( level === "H1" ) {
            tableOfContentsEntries.push(
                tableOfContentsEntry( title, id, [] ) );
        } else if ( level === "H2" ) {
            var latestEntryH1 = tableOfContentsEntries.pop();
            latestEntryH1.children.push(
                tableOfContentsEntry( title, id, [] ) );
            tableOfContentsEntries.push( latestEntryH1 );
        }
    });

    return tableOfContentsEntries;
}

function tableOfContentsEntry( title, id, children )
{
    return {
        title: title,
        id: id,
        children: children,
    };
}

function tableOfContentsHtmlFromData( tableOfContents )
{
    var listItems = tableOfContents.map( function( entry ) {
        return '
' +
               '' +
                entry.title +
                tableOfContentsHtmlFromData( entry.children ) +
               '' +
               '
';
    });

    if ( listItems.length > 0 ) {
        return '
' +
                listItems.join( constants.newlineCharacter ) +
                '
';
    }

    return "";
}
<|endoftext|>


<commit_before>import * as React from "react";
import { x } from "@xstyled/styled-components";
import { useInView } from "react-cool-inview";
import {
  GitBranchIcon,
  CommitIcon,
  ClockIcon,
  BookmarkIcon,
} from "@primer/octicons-react";
import moment from "moment";
import { gql } from "graphql-tag";
import { getStatusPrimaryColor } from "../../containers/Status";
import {
  Button,
  Container,
  IllustratedText,
  LoadingAlert,
  PrimaryTitle,
  Table,
  Tbody,
  Td,
  TdLink,
  Th,
  Thead,
  Tr,
} from "@argos-ci/app/src/components";
import { useQuery } from "../../containers/Apollo";
import { GettingStarted } from "./GettingStarted";
import { getPossessiveForm } from "../../modules/utils";

const REPOSITORY_BUILDS_QUERY = gql`
  query RepositoryBuilds($ownerLogin: String!, $name: String!, $after: Int!) {
    repository(ownerLogin: $ownerLogin, repositoryName: $name) {
      id
      builds(first: 5, after: $after) {
        pageInfo {
          totalCount
          hasNextPage
          endCursor
        }
        edges {
          id
          createdAt
          number
          status
          name
          compareScreenshotBucket {
            id
            commit
            branch
          }
        }
      }
    }
  }
`;

const EndOfList = (props) => (
  <x.div
    py={1}
    w={250}
    mx="auto"
    borderTop={1}
    textAlign="center"
    mt={3}
    color="secondary-text"
    {...props}
  >
    End of list
  </x.div>
);

function BuildsList({ repository }) {
  const { loading, data, fetchMore } = useQuery(REPOSITORY_BUILDS_QUERY, {
    variables: {
      ownerLogin: repository.owner.login,
      name: repository.name,
      after: 0,
    },
  });
  const [moreLoading, setMoreLoading] = React.useState();

  function loadNextPage() {
    setMoreLoading(true);
    fetchMore({
      variables: { after: data.repository.builds.pageInfo.endCursor },
      updateQuery: (prev, { fetchMoreResult }) => {
        if (!fetchMoreResult) return prev;
        return {
          ...prev,
          repository: {
            ...prev.repository,
            builds: {
              ...fetchMoreResult.repository.builds,
              edges: [
                ...prev.repository.builds.edges,
                ...fetchMoreResult.repository.builds.edges,
              ],
            },
          },
        };
      },
    }).finally(() => {
      setMoreLoading(false);
    });
  }

  const { observe } = useInView({
    rootMargin: "50px 0px",
    onEnter: ({ unobserve }) => {
      unobserve();
      loadNextPage();
    },
  });

  if (loading)
    return (
      <LoadingAlert>
        Argos fetch <x.span fontWeight={700}>{repository.name}</x.span> builds.
        It should not take long.
      </LoadingAlert>
    );

  const {
    repository: {
      builds: { pageInfo, edges: builds },
    },
  } = data;

  if (!pageInfo.totalCount) {
    return <GettingStarted repository={repository} />;
  }

  return (
    <>

              <x.div ml={18}>Branch</x.div>

            Build
            Commit
            Date

          {builds.map((build, buildIndex) => {
            const statusColor = getStatusPrimaryColor(build.status);

            return (

                  <TdLink
                    borderRadius="0 md md 0"
                    borderLeft={1}
                    borderLeftColor={{ _: statusColor, hover: statusColor }}
                    px={4}
                    to={`${build.number}`}
                  >
                    <IllustratedText icon={GitBranchIcon}>
                      {build.compareScreenshotBucket.branch}{" "}
                      {build.name !== "default" && (
                        <IllustratedText
                          ml={1}
                          icon={BookmarkIcon}
                          color="secondary-text"
                          field
                        >
                          {build.name}
                        </IllustratedText>
                      )}
                    </IllustratedText>
                  </TdLink>

                  <TdLink to={`${build.number}`} color={statusColor}>
                    #{build.number} {build.status}
                  </TdLink>

                  <TdLink
                    color={{ _: "secondary-text", hover: "primary-text" }}
                    target="_blank"
                    href={`https://github.com/${repository.owner.login}/${repository.name}/commit/${build.compareScreenshotBucket.commit}`}
                  >
                    <IllustratedText icon={CommitIcon}>
                      {build.compareScreenshotBucket.commit.slice(0, 7)}
                    </IllustratedText>
                  </TdLink>

                  <IllustratedText icon={ClockIcon}>
                    {moment(build.createdAt).fromNow()}
                  </IllustratedText>

            );
          })}

      {pageInfo.hasNextPage && !moreLoading && (
        <Button mt={3} mx="auto" onClick={loadNextPage}>
          Load More
        </Button>
      )}

      {moreLoading && (
        <LoadingAlert py={1} mt={4} severity="neutral">
          Loading previous build
        </LoadingAlert>
      )}

      {!pageInfo.hasNextPage && <EndOfList />}
    </>
  );
}

export function RepositoryBuilds({ repository }) {
  return (
    <Container>
      <PrimaryTitle>{getPossessiveForm(repository.name)} Builds</PrimaryTitle>
      <BuildsList repository={repository} />
    </Container>
  );
}
<commit_msg>feat(builds): manual load more<commit_after>import * as React from "react";
import { x } from "@xstyled/styled-components";
import {
  GitBranchIcon,
  CommitIcon,
  ClockIcon,
  BookmarkIcon,
} from "@primer/octicons-react";
import moment from "moment";
import { gql } from "graphql-tag";
import { getStatusPrimaryColor } from "../../containers/Status";
import {
  Button,
  Container,
  IllustratedText,
  LoadingAlert,
  PrimaryTitle,
  Table,
  Tbody,
  Td,
  TdLink,
  Th,
  Thead,
  Tr,
} from "@argos-ci/app/src/components";
import { useQuery } from "../../containers/Apollo";
import { GettingStarted } from "./GettingStarted";
import { getPossessiveForm } from "../../modules/utils";

const REPOSITORY_BUILDS_QUERY = gql`
  query RepositoryBuilds($ownerLogin: String!, $name: String!, $after: Int!) {
    repository(ownerLogin: $ownerLogin, repositoryName: $name) {
      id
      builds(first: 10, after: $after) {
        pageInfo {
          totalCount
          hasNextPage
          endCursor
        }
        edges {
          id
          createdAt
          number
          status
          name
          compareScreenshotBucket {
            id
            commit
            branch
          }
        }
      }
    }
  }
`;

const EndOfList = (props) => (
  <x.div
    py={1}
    w={250}
    mx="auto"
    borderTop={1}
    textAlign="center"
    mt={3}
    color="secondary-text"
    {...props}
  >
    End of list
  </x.div>
);

function BuildsList({ repository }) {
  const { loading, data, fetchMore } = useQuery(REPOSITORY_BUILDS_QUERY, {
    variables: {
      ownerLogin: repository.owner.login,
      name: repository.name,
      after: 0,
    },
  });
  const [moreLoading, setMoreLoading] = React.useState();

  function loadNextPage() {
    setMoreLoading(true);
    fetchMore({
      variables: { after: data.repository.builds.pageInfo.endCursor },
      updateQuery: (prev, { fetchMoreResult }) => {
        if (!fetchMoreResult) return prev;
        return {
          ...prev,
          repository: {
            ...prev.repository,
            builds: {
              ...fetchMoreResult.repository.builds,
              edges: [
                ...prev.repository.builds.edges,
                ...fetchMoreResult.repository.builds.edges,
              ],
            },
          },
        };
      },
    }).finally(() => {
      setMoreLoading(false);
    });
  }

  if (loading)
    return (
      <LoadingAlert>
        Argos fetch <x.span fontWeight={700}>{repository.name}</x.span> builds.
        It should not take long.
      </LoadingAlert>
    );

  const {
    repository: {
      builds: { pageInfo, edges: builds },
    },
  } = data;

  if (!pageInfo.totalCount) {
    return <GettingStarted repository={repository} />;
  }

  return (
    <>

              <x.div ml={18}>Branch</x.div>

            Build
            Commit
            Date

          {builds.map((build) => {
            const statusColor = getStatusPrimaryColor(build.status);

            return (

                  <TdLink
                    borderRadius="0 md md 0"
                    borderLeft={1}
                    borderLeftColor={{ _: statusColor, hover: statusColor }}
                    px={4}
                    to={`${build.number}`}
                  >
                    <IllustratedText icon={GitBranchIcon}>
                      {build.compareScreenshotBucket.branch}{" "}
                      {build.name !== "default" && (
                        <IllustratedText
                          ml={1}
                          icon={BookmarkIcon}
                          color="secondary-text"
                          field
                        >
                          {build.name}
                        </IllustratedText>
                      )}
                    </IllustratedText>
                  </TdLink>

                  <TdLink to={`${build.number}`} color={statusColor}>
                    #{build.number} {build.status}
                  </TdLink>

                  <TdLink
                    color={{ _: "secondary-text", hover: "primary-text" }}
                    target="_blank"
                    href={`https://github.com/${repository.owner.login}/${repository.name}/commit/${build.compareScreenshotBucket.commit}`}
                  >
                    <IllustratedText icon={CommitIcon}>
                      {build.compareScreenshotBucket.commit.slice(0, 7)}
                    </IllustratedText>
                  </TdLink>

                  <IllustratedText icon={ClockIcon}>
                    {moment(build.createdAt).fromNow()}
                  </IllustratedText>

            );
          })}

      {pageInfo.hasNextPage && (
        <Button mt={3} mx="auto" onClick={loadNextPage} disabled={moreLoading}>
          Load More
        </Button>
      )}

      {!pageInfo.hasNextPage && <EndOfList />}
    </>
  );
}

export function RepositoryBuilds({ repository }) {
  return (
    <Container>
      <PrimaryTitle>{getPossessiveForm(repository.name)} Builds</PrimaryTitle>
      <BuildsList repository={repository} />
    </Container>
  );
}
<|endoftext|>


<commit_before>// Node.js API.
var http = require('http')

// Control-flow utilities.
var cadence = require('cadence')
var delta = require('delta')

// Route Sencha Connect middleware based on request method and URL patterns.
var dispatch = require('dispatch')

// Exceptions that you can catch by type.
var interrupt = require('interrupt').createInterrupter('reactor')

// Contextualized callbacks and event handlers.
var Operation = require('operation/variadic')

// Evented work queue.
var Turnstile = require('turnstile')
Turnstile.Queue = require('turnstile/queue')

// Catch exceptions based on a regex match of an error message or property.
var rescue = require('rescue')

// Return the first not null-like value.
var coalesce = require('extant')

// Do nothing.
var nop = require('nop')

function Constructor (object, dispatch) {
    this._object = object
    this._dispatch = dispatch
    this._use = []
    this._defaultUse = true
}

Constructor.prototype.useDefault = function () {
    this.use(require('express-auth-parser'))
    this.use(require('body-parser').urlencoded({ extended: false, limit: '64mb' }))
    this.use(require('body-parser').json({ limit: '64mb' }))
}

Constructor.prototype.use = function () {
    var vargs = Array.prototype.slice.call(arguments)
    this._defaultUse = false
    while (vargs.length) {
        var varg = vargs.shift()
        if (Array.isArray(varg)) {
            vargs.unshift(varg)
        } else {
            this._use.push(varg)
        }
    }
}

Constructor.prototype.dispatch = function () {
    var vargs = Array.prototype.slice.call(arguments)
    this._dispatch[vargs.shift()] = Operation(vargs, { object: this._object })
}

function handler (queue, before, operation) {
    return function (request, response, next) {
        var vargs = Array.prototype.slice.call(arguments, 3)
        request.entry = {
            when: {
                push: Date.now(),
                start: null,
                headers: null,
                finish: null
            },
            health: {
                push: JSON.parse(JSON.stringify(queue.turnstile.health)),
                start: null,
                finish: null
            },
            duration: {
                start: null,
                headers: null,
                finish: null,
            },
            request: {
                method: request.method,
                header: request.headers,
                url: request.url,
                vargs: vargs
            }
        }
        before(request, response, function (error) {
            queue.push({
                error: coalesce(error),
                operation: operation,
                request: request,
                response: response,
                vargs: vargs
            })
        })
    }
}

function Reactor (object, configurator) {
    var constructor = new Constructor(object, this._dispatch = {})
    configurator(constructor)
    this.turnstile = new Turnstile({
        Date: coalesce(constructor.Date, Date),
        turnstiles: coalesce(constructor.turnstiles, 24),
        timeout: coalesce(constructor.timeout)
    })
    this._queue = new Turnstile.Queue(this, '_respond', this.turnstile)
    this._logger = coalesce(constructor.logger, function (entry) {
        if (entry.error) {
            console.log(entry.error.stack)
        }
    })
    this._completed = coalesce(constructor.completed, nop)
    this._object = object
    if (constructor._defaultUse) {
        constructor.useDefault()
    }
    var before = require('connect')()
    constructor._use.forEach(function (middleware) {
        before.use(middleware)
    })
    var dispatcher = {}
    for (var pattern in this._dispatch) {
        dispatcher[pattern] = handler(this._queue, before, this._dispatch[pattern])
    }
    this.middleware = require('connect')().use(dispatch(dispatcher))
}

Reactor.prototype._timeout = cadence(function () { throw 503 })

function createProperties (properties) {
    return {
        statusCode: properties.statusCode,
        headers: coalesce(properties.headers, {}),
        description: coalesce(properties.description)
    }
}

function raise (statusCode, description, headers) {
    throw interrupt('http', createProperties({
        statusCode: statusCode,
        description: description,
        headers: headers
    }))
}

Reactor.prototype._respond = cadence(function (async, envelope) {
    var work = envelope.body
    var next = work.next

    var entry = work.request.entry

    entry.when.start = Date.now()
    entry.health.start = JSON.parse(JSON.stringify(this.turnstile.health))

    work.request.entry = entry
    work.request.raise = raise

    if (envelope.timedout) {
        work.operation = Operation([ this, '_timeout' ])
    }

    var finish

    async(function () {
        async(function () {
            async([function () {
                async(function () {
                    if (work.error) {
                        throw { cause: work.error, statusCode: coalesce(work.error.statusCode) }
                    }
                    work.operation.apply(null, [ work.request ].concat(work.vargs, async()))
                }, function () {
                    var vargs = Array.prototype.slice.call(arguments)

                    var result = vargs.shift()
                    var statusCode = (typeof vargs[0] == 'number') ? vargs.shift() : 200
                    var description = coalesce(http.STATUS_CODES[statusCode])
                    if (typeof vargs[0] == 'string') {
                        description = vargs.shift()
                    }
                    if (vargs[0] == null) {
                        vargs.shift()
                    }
                    var headers = coalesce(vargs.shift(), {})

                    interrupt.assert(description != null, 'unknown.http.status', { statusCode: statusCode })

                    return [ result, statusCode, description, headers ]
                })
            }, function (caught) {
                for (;;) {
                    try {
                        return rescue(/^reactor#http$/m, function (error) {
                            var statusCode = error.statusCode
                            var description = coalesce(error.description, http.STATUS_CODES[statusCode])
                            var body = coalesce(error.body, description)
                            var headers = coalesce(error.headers, {})

                            entry.error = coalesce(error.cause)

                            interrupt.assert(description != null, 'unknown.http.status', { statusCode: statusCode })

                            headers['content-type'] = 'application/json'

                            return [ description, statusCode, description, headers ]
                        })(caught)
                    } catch (error) {
                        if (
                            typeof error == 'number' &&
                            !isNaN(error) &&
                            (error | 0) === error &&
                            Math.floor(error / 100) <= 5 &&
                            Math.floor(error / 100) >= 3
                        ) {
                            error = { statusCode: error }
                        } else if (typeof error == 'string') {
                            error = { statusCode: 307, location: error }
                        }
                        if (Array.isArray(error)) {
                            error = error.slice()
                            var needBody = true
                            if (typeof error[1] == 'number') {
                                var body = error.shift()
                                needBody = false
                            }
                            var statusCode = typeof error[0] == 'number' ? error.shift() : 503
                            var description = coalesce(http.STATUS_CODES[statusCode])
                            if (typeof vargs[0] == 'string') {
                                description = error.shift()
                            }
                            error = {
                                statusCode: statusCode,
                                description: description,
                                body: needBody ? description : body,
                                headers: coalesce(error.shift(), {})
                            }
                        }
                        if (
                            ! (error instanceof Error) &&
                            typeof error == 'object' &&
                            typeof error.statusCode == 'number' &&
                            !isNaN(error.statusCode) &&
                            (error.statusCode | 0) === error.statusCode &&
                            Math.floor(error.statusCode / 100) <= 5 &&
                            Math.floor(error.statusCode / 100) >= 3
                        ) {
                            var properties = createProperties(error)
                            if (error.location) {
                                properties.headers.location = error.location
                            }
                            error = interrupt('http', properties, { cause: coalesce(error.cause) })
                        } else {
                            error = { statusCode: 500, cause: error }
                        }
                        caught = error
                    }
                }
            }])
        }, function (result, statusCode, description, headers) {
            var body, f
            if (typeof result == 'function') {
                f = result
            } else {
                if (typeof result == 'string') {
                    if (!('content-type' in headers)) {
                        headers['content-type'] = 'text/plain'
                        result = new Buffer(result)
                    } else if (headers['content-type'] == 'application/json') {
                        result = new Buffer(JSON.stringify(result) + '\n')
                    }
                } else if (!('content-type' in headers)) {
                    headers['content-type'] = 'application/json'
                    result = new Buffer(JSON.stringify(result) + '\n')
                }
                f = function (response) {
                    response.end(result)
                }
            }

            work.response.writeHead(statusCode, description, headers)

            entry.when.headers = Date.now()

            entry.statusCode = statusCode
            entry.description = description
            entry.headers = headers

            var finish = delta(async()).ee(work.response).on('finish')

            async([function () {
                async(function () {
                    if (f.length == 2) {
                        f.call(work.operation.object, work.response, async())
                    } else {
                        return [ f.call(work.operation.object, work.response) ]
                    }
                }, function () {
                    return []
                })
            }, function (error) {
                entry.error = error
                work.response.end()
                finish.cancel()
            }])
        })
    }, function () {
        entry.health.done = JSON.parse(JSON.stringify(this.turnstile.health))
        entry.when.finish = Date.now()
        entry.duration = {
            start: entry.when.start - entry.when.push,
            headers: entry.when.headers - entry.when.push,
            finish: entry.when.finish - entry.when.push
        }
        this._logger.call(null, entry)
        this._completed.call(null, entry)
    })
})

Reactor.resend = function (statusCode, headers, body) {
    return Reactor.send({ statusCode: statusCode, headers: headers }, body)
}

Reactor.send = function (properties, buffer) {
    var headers = JSON.parse(JSON.stringify(properties.headers))
    delete headers['content-length']
    delete headers['transfer-encoding']
    return [ buffer, properties.statusCode, properties.statusMessage, headers ]
}

Reactor.string = function (statusCode, contentType, text) {
    return [ new Buffer(text), statusCode, { 'content-type': contentType } ]
}

Reactor.stream = function (properties, stream) {
    var headers = JSON.parse(JSON.stringify(properties.headers))
    delete headers['content-length']
    headers['transfer-encoding'] = 'chunked'
    return [ function (response) {
        stream.pipe(response)
    }, properties.statusCode, properties.statusMessage, headers ]
}

module.exports = Reactor
<commit_msg>Do not abend on missing status code.<commit_after>// Node.js API.
var http = require('http')

// Control-flow utilities.
var cadence = require('cadence')
var delta = require('delta')

// Route Sencha Connect middleware based on request method and URL patterns.
var dispatch = require('dispatch')

// Exceptions that you can catch by type.
var interrupt = require('interrupt').createInterrupter('reactor')

// Contextualized callbacks and event handlers.
var Operation = require('operation/variadic')

// Evented work queue.
var Turnstile = require('turnstile')
Turnstile.Queue = require('turnstile/queue')

// Catch exceptions based on a regex match of an error message or property.
var rescue = require('rescue')

// Return the first not null-like value.
var coalesce = require('extant')

// Do nothing.
var nop = require('nop')

function Constructor (object, dispatch) {
    this._object = object
    this._dispatch = dispatch
    this._use = []
    this._defaultUse = true
}

Constructor.prototype.useDefault = function () {
    this.use(require('express-auth-parser'))
    this.use(require('body-parser').urlencoded({ extended: false, limit: '64mb' }))
    this.use(require('body-parser').json({ limit: '64mb' }))
}

Constructor.prototype.use = function () {
    var vargs = Array.prototype.slice.call(arguments)
    this._defaultUse = false
    while (vargs.length) {
        var varg = vargs.shift()
        if (Array.isArray(varg)) {
            vargs.unshift(varg)
        } else {
            this._use.push(varg)
        }
    }
}

Constructor.prototype.dispatch = function () {
    var vargs = Array.prototype.slice.call(arguments)
    this._dispatch[vargs.shift()] = Operation(vargs, { object: this._object })
}

function handler (queue, before, operation) {
    return function (request, response, next) {
        var vargs = Array.prototype.slice.call(arguments, 3)
        request.entry = {
            when: {
                push: Date.now(),
                start: null,
                headers: null,
                finish: null
            },
            health: {
                push: JSON.parse(JSON.stringify(queue.turnstile.health)),
                start: null,
                finish: null
            },
            duration: {
                start: null,
                headers: null,
                finish: null,
            },
            request: {
                method: request.method,
                header: request.headers,
                url: request.url,
                vargs: vargs
            }
        }
        before(request, response, function (error) {
            queue.push({
                error: coalesce(error),
                operation: operation,
                request: request,
                response: response,
                vargs: vargs
            })
        })
    }
}

function Reactor (object, configurator) {
    var constructor = new Constructor(object, this._dispatch = {})
    configurator(constructor)
    this.turnstile = new Turnstile({
        Date: coalesce(constructor.Date, Date),
        turnstiles: coalesce(constructor.turnstiles, 24),
        timeout: coalesce(constructor.timeout)
    })
    this._queue = new Turnstile.Queue(this, '_respond', this.turnstile)
    this._logger = coalesce(constructor.logger, function (entry) {
        if (entry.error) {
            console.log(entry.error.stack)
        }
    })
    this._completed = coalesce(constructor.completed, nop)
    this._object = object
    if (constructor._defaultUse) {
        constructor.useDefault()
    }
    var before = require('connect')()
    constructor._use.forEach(function (middleware) {
        before.use(middleware)
    })
    var dispatcher = {}
    for (var pattern in this._dispatch) {
        dispatcher[pattern] = handler(this._queue, before, this._dispatch[pattern])
    }
    this.middleware = require('connect')().use(dispatch(dispatcher))
}

Reactor.prototype._timeout = cadence(function () { throw 503 })

function createProperties (properties) {
    return {
        statusCode: properties.statusCode,
        headers: coalesce(properties.headers, {}),
        description: coalesce(properties.description)
    }
}

function raise (statusCode, description, headers) {
    throw interrupt('http', createProperties({
        statusCode: statusCode,
        description: description,
        headers: headers
    }))
}

Reactor.prototype._respond = cadence(function (async, envelope) {
    var work = envelope.body
    var next = work.next

    var entry = work.request.entry

    entry.when.start = Date.now()
    entry.health.start = JSON.parse(JSON.stringify(this.turnstile.health))

    work.request.entry = entry
    work.request.raise = raise

    if (envelope.timedout) {
        work.operation = Operation([ this, '_timeout' ])
    }

    var finish

    async(function () {
        async(function () {
            async([function () {
                async(function () {
                    if (work.error) {
                        throw { cause: work.error, statusCode: coalesce(work.error.statusCode) }
                    }
                    work.operation.apply(null, [ work.request ].concat(work.vargs, async()))
                }, function () {
                    var vargs = Array.prototype.slice.call(arguments)

                    var result = vargs.shift()
                    var statusCode = (typeof vargs[0] == 'number') ? vargs.shift() : 200
                    var description = coalesce(http.STATUS_CODES[statusCode], 'unknown')
                    if (typeof vargs[0] == 'string') {
                        description = vargs.shift()
                    }
                    if (vargs[0] == null) {
                        vargs.shift()
                    }
                    var headers = coalesce(vargs.shift(), {})

                    return [ result, statusCode, description, headers ]
                })
            }, function (caught) {
                for (;;) {
                    try {
                        return rescue(/^reactor#http$/m, function (error) {
                            var statusCode = error.statusCode
                            var description = coalesce(error.description, http.STATUS_CODES[statusCode])
                            var body = coalesce(error.body, description)
                            var headers = coalesce(error.headers, {})

                            entry.error = coalesce(error.cause)

                            interrupt.assert(description != null, 'unknown.http.status', { statusCode: statusCode })

                            headers['content-type'] = 'application/json'

                            return [ description, statusCode, description, headers ]
                        })(caught)
                    } catch (error) {
                        if (
                            typeof error == 'number' &&
                            !isNaN(error) &&
                            (error | 0) === error &&
                            Math.floor(error / 100) <= 5 &&
                            Math.floor(error / 100) >= 3
                        ) {
                            error = { statusCode: error }
                        } else if (typeof error == 'string') {
                            error = { statusCode: 307, location: error }
                        }
                        if (Array.isArray(error)) {
                            error = error.slice()
                            var needBody = true
                            if (typeof error[1] == 'number') {
                                var body = error.shift()
                                needBody = false
                            }
                            var statusCode = typeof error[0] == 'number' ? error.shift() : 503
                            var description = coalesce(http.STATUS_CODES[statusCode])
                            if (typeof vargs[0] == 'string') {
                                description = error.shift()
                            }
                            error = {
                                statusCode: statusCode,
                                description: description,
                                body: needBody ? description : body,
                                headers: coalesce(error.shift(), {})
                            }
                        }
                        if (
                            ! (error instanceof Error) &&
                            typeof error == 'object' &&
                            typeof error.statusCode == 'number' &&
                            !isNaN(error.statusCode) &&
                            (error.statusCode | 0) === error.statusCode &&
                            Math.floor(error.statusCode / 100) <= 5 &&
                            Math.floor(error.statusCode / 100) >= 3
                        ) {
                            var properties = createProperties(error)
                            if (error.location) {
                                properties.headers.location = error.location
                            }
                            error = interrupt('http', properties, { cause: coalesce(error.cause) })
                        } else {
                            error = { statusCode: 500, cause: error }
                        }
                        caught = error
                    }
                }
            }])
        }, function (result, statusCode, description, headers) {
            var body, f
            if (typeof result == 'function') {
                f = result
            } else {
                if (typeof result == 'string') {
                    if (!('content-type' in headers)) {
                        headers['content-type'] = 'text/plain'
                        result = new Buffer(result)
                    } else if (headers['content-type'] == 'application/json') {
                        result = new Buffer(JSON.stringify(result) + '\n')
                    }
                } else if (!('content-type' in headers)) {
                    headers['content-type'] = 'application/json'
                    result = new Buffer(JSON.stringify(result) + '\n')
                }
                f = function (response) {
                    response.end(result)
                }
            }

            work.response.writeHead(statusCode, description, headers)

            entry.when.headers = Date.now()

            entry.statusCode = statusCode
            entry.description = description
            entry.headers = headers

            var finish = delta(async()).ee(work.response).on('finish')

            async([function () {
                async(function () {
                    if (f.length == 2) {
                        f.call(work.operation.object, work.response, async())
                    } else {
                        return [ f.call(work.operation.object, work.response) ]
                    }
                }, function () {
                    return []
                })
            }, function (error) {
                entry.error = error
                work.response.end()
                finish.cancel()
            }])
        })
    }, function () {
        entry.health.done = JSON.parse(JSON.stringify(this.turnstile.health))
        entry.when.finish = Date.now()
        entry.duration = {
            start: entry.when.start - entry.when.push,
            headers: entry.when.headers - entry.when.push,
            finish: entry.when.finish - entry.when.push
        }
        this._logger.call(null, entry)
        this._completed.call(null, entry)
    })
})

Reactor.resend = function (statusCode, headers, body) {
    return Reactor.send({ statusCode: statusCode, headers: headers }, body)
}

Reactor.send = function (properties, buffer) {
    var headers = JSON.parse(JSON.stringify(properties.headers))
    delete headers['content-length']
    delete headers['transfer-encoding']
    return [ buffer, properties.statusCode, properties.statusMessage, headers ]
}

Reactor.string = function (statusCode, contentType, text) {
    return [ new Buffer(text), statusCode, { 'content-type': contentType } ]
}

Reactor.stream = function (properties, stream) {
    var headers = JSON.parse(JSON.stringify(properties.headers))
    delete headers['content-length']
    headers['transfer-encoding'] = 'chunked'
    return [ function (response) {
        stream.pipe(response)
    }, properties.statusCode, properties.statusMessage, headers ]
}

module.exports = Reactor
<|endoftext|>


<commit_before>/**
 * RedisPool. A database specific redis pooling lib
 *
 */

var redis  = require('redis')
  , _      = require('underscore')
  , Pool   = require('generic-pool').Pool;

// constructor.
//
// - `opts` {Object} optional config for redis and pooling
var RedisPool = function(opts){
  var opts = opts || {};
  var defaults = {
    host: '127.0.0.1',
    port: '6379',
    max: 50,
    idleTimeoutMillis: 10000,
    reapIntervalMillis: 1000,
    log: false
  };
  var options = _.defaults(opts, defaults)

  var me = {
    pools: {} // cached pools by DB name
  };

  // Acquire resource.
  //
  // - `database` {String} redis database name
  // - `callback` {Function} callback to call once acquired. Takes the form
  //   `callback(err, resource)`
  me.acquire = function(database, callback) {
      if (!this.pools[database]) {
        this.pools[database] = this.makePool(database);
      }
      this.pools[database].acquire(function(err,resource) {
        callback(err, resource);
      });
  };

  // Release resource.
  //
  // - `database` {String} redis database name
  // - `resource` {Object} resource object to release
  me.release = function(database, resource) {
      this.pools[database] && this.pools[database].release(resource);
  };

  // Factory for pool objects.
  me.makePool = function(database) {
    return Pool({
      name: database,
      create: function(callback){
        var client = redis.createClient(options.port, options.host);
        client.on('connect', function () {
          client.send_anyway = true;
          client.select(database);
          client.send_anyway = false;
        });
        return callback(null, client);
      },
      destroy: function(client) {
        return client.quit();
      },
      max: options.max,
      idleTimeoutMillis: options.idleTimeoutMillis,
      reapIntervalMillis: options.reapIntervalMillis,
      log: options.log
    });
  };

  return me;
};

module.exports = RedisPool;<commit_msg>Check redis connection at pool creation time<commit_after>/**
 * RedisPool. A database specific redis pooling lib
 *
 */

var redis  = require('redis')
  , _      = require('underscore')
  , Pool   = require('generic-pool').Pool;

// constructor.
//
// - `opts` {Object} optional config for redis and pooling
var RedisPool = function(opts){
  var opts = opts || {};
  var defaults = {
    host: '127.0.0.1',
    port: '6379',
    max: 50,
    idleTimeoutMillis: 10000,
    reapIntervalMillis: 1000,
    log: false
  };
  var options = _.defaults(opts, defaults)

  var me = {
    pools: {} // cached pools by DB name
  };

  // Acquire resource.
  //
  // - `database` {String} redis database name
  // - `callback` {Function} callback to call once acquired. Takes the form
  //   `callback(err, resource)`
  me.acquire = function(database, callback) {
      if (!this.pools[database]) {
        this.pools[database] = this.makePool(database);
      }
      this.pools[database].acquire(function(err,resource) {
        callback(err, resource);
      });
  };

  // Release resource.
  //
  // - `database` {String} redis database name
  // - `resource` {Object} resource object to release
  me.release = function(database, resource) {
      this.pools[database] && this.pools[database].release(resource);
  };

  // Factory for pool objects.
  me.makePool = function(database) {
    return Pool({
      name: database,
      create: function(callback){
        var client = redis.createClient(options.port, options.host);
        client.on('connect', function () {
          client.send_anyway = true;
          client.select(database);
          client.send_anyway = false;
          callback(null, client);
        });
        client.on('error', function (err) {
          callback(err, null);
        });
      },
      destroy: function(client) {
        return client.quit();
      },
      max: options.max,
      idleTimeoutMillis: options.idleTimeoutMillis,
      reapIntervalMillis: options.reapIntervalMillis,
      log: options.log
    });
  };

  return me;
};

module.exports = RedisPool;<|endoftext|>


<commit_before>$(function() {

  function submitFilterForm() {
    $(".mdl-layout").addClass("is-submitting");
    $(".page-filter__form").submit();
  }

  function initPageFilter() {
    var $pageFilter = $(".page-filter");
    if ($pageFilter.length) {
      var checkForActiveFilters = function() {
            var $filterInputs = $pageFilter.find(".mdl-textfield__input, .mdl-switch__input"),
                activeFilters = $filterInputs.filter(function() {
                  var $this = $(this);
                  if ($this.is(".mdl-switch__input")) {
                    return $this.prop("checked");
                  } else {
                    return $this.val();
                  }
                });
            if (activeFilters.length) {
              $pageFilter.addClass("is-active");
            } else {
              $pageFilter.removeClass("is-active");
            }
          };

      $(".toggle-button").on("click", function(e) {
        e.preventDefault();
        if ($pageFilter.hasClass("is-visible")) {
          $pageFilter.removeClass("is-visible");
        } else {
          $pageFilter.addClass("is-visible");
        }

        checkForActiveFilters();
      });

      var $filterForm = $(".page-filter__form");
      $filterForm.on("change", "input[type='checkbox']", function() {
        submitFilterForm();
      });

    checkForActiveFilters();
    initAuthorFilter();
    initOrderBy();
    }
  }

  function initSelectize() {
    var $selectField = $(".mdl-selectfield__select");
    if ($selectField.length) {
      Selectize.define("active_css_classes", function(options) {
        var self = this;

        this.onFocus = (function() {
          var original = self.onFocus;
            return function() {
              var $select_field = self.$control.parents(".mdl-selectfield");
              $select_field.addClass("is-active");
              return original.apply(this, arguments);
            }
        })();

        this.onBlur = (function() {
          var original = self.onBlur;
            return function() {
              var $select_field = self.$control.parents(".mdl-selectfield");
              $select_field.removeClass("is-active");
              return original.apply(this, arguments);
            }
        })();

        this.onChange = (function() {
          var original = self.onBlur;
            return function(value) {
              var $select_field = self.$control.parents(".mdl-selectfield");
              if (value.length) {
                $select_field.addClass("is-dirty");
              } else {
                $select_field.removeClass("is-dirty");
              }
              return original.apply(this, arguments);
            }
        })();
      });

      var $selectizedFields = $selectField.selectize({
        allowEmptyOption: true,
        plugins: ["active_css_classes"]
      });

      window.selectizedFields = [];
      $selectizedFields.each(function() {
        window.selectizedFields.push($(this)[0].selectize);
      });
    }
  }

  function initFixedScrollSearchHeader() {
    var $searchFormHeader = $(".search-form-header");
    if ($searchFormHeader.length) {
      var headerHeight = $searchFormHeader.height();
      $("body").on("scroll", function() {
        var scrollTop = $(this).scrollTop(),
            cutoff = $searchFormHeader.position().top + headerHeight;
        if (scrollTop > cutoff) {
          $searchFormHeader.addClass("is-fixed");
        } else {
          $searchFormHeader.removeClass("is-fixed");
        }
      });
    }
  }

  function initSearchForm() {
    initSelectize();
    initFixedScrollSearchHeader();
    var $searchForm = $(".search-form-header");
    if ($searchForm.length) {
      $("[data-action=toggle-search-form]").on("click", function() {
        $searchForm.toggleClass("is-hidden");
      });
    }
  }

  function initCustomActions() {
    var $itemImageLinks = $(".item__image__link");
    if ($itemImageLinks.length) {
      $itemImageLinks.on("mouseenter", function() {
        $(this).parents(".collection__item").find(".item__heading .item__link").addClass("is-hovered");
      }).on("mouseleave", function() {
        $(this).parents(".collection__item").find(".item__heading .item__link").removeClass("is-hovered");
      });
    }

    var $drawerCloseButton = $(".mdl-layout__drawer__close_button");
    if ($drawerCloseButton.length) {
      $drawerCloseButton.on("click", function(e) {
        e.preventDefault();
        $(".search-form-header").addClass("is-hidden");
        $(".mdl-layout__drawer.is-visible, .mdl-layout__obfuscator.is-visible").removeClass("is-visible");
      });
    }
  }

  function initBookHeader() {
    var $bookHeader = $("#book-header");
    if (! $bookHeader.length) {
      return false;
    }
    $bookHeader.stickySidebar({
      topSpacing: 20,
      containerSelector: "#books-detail article",
      minWidth: 649,
      resizeSensor: false
    });

    var $body = $("body"),
        $navLinks = $(".item-navigation-link"),
        activeClass = "item-navigation-link--active";

    $navLinks.on("click", function(e) {
      var $this = $(this),
          hash = $this.attr("href"),
          $target = $("[name=" + hash.slice(1) + "]");

      if ($target.length) {
        e.preventDefault();
        $this.siblings().removeClass(activeClass);
        $this.addClass(activeClass);
        $this.blur();

        $body.animate({
          scrollTop: $target.position().top
        }, 500);
      }
    });

    var navLinkTargets = [],
        navLinkSelectors = [];
    $navLinks.each(function() {
      navLinkTargets.push($(this).attr("href"));
    });

    if (navLinkTargets.length) {
      $.each(navLinkTargets, function() {
        navLinkSelectors.push(".item-gallery__title a[name=" + this.slice(1) + "]");
      })
    }

    $body.scroll(function() {
        clearTimeout($.data(this, "scrollTimer"));
        $.data(this, "scrollTimer", setTimeout(function() {
            var activeTab = "",
                offset = 64;
            if (navLinkSelectors.length) {
              if ($body.scrollTop() < offset) {
                var $this = $(navLinkSelectors[0]);
                $(".item-navigation-link").removeClass(activeClass);
                $(".item-navigation-link[href=#"+$this.attr("name")+"]").addClass(activeClass);
              } else {
                $(navLinkSelectors.join(",")).each(function() {
                  var $this = $(this);
                  if ($this.position().top < $body.scrollTop() + offset ) {
                    $(".item-navigation-link").removeClass(activeClass);
                    $(".item-navigation-link[href=#"+$this.attr("name")+"]").addClass(activeClass);
                  }
                });
              }
            }
        }, 250));
    });
  }

  function initVisualization() {
    var $visualizationMarkers = $(".visualization-chapter-marker");
    if ($visualizationMarkers.length) {
      $visualizationMarkers.webuiPopover({
        trigger: "hover",
        animation: "fade",
        placement: "auto-top",
        arrow: true,
        delay: {
          show: 300,
          hide: 1000
        },
        style: "visualization",
        type: "async",
        async: {
           error: function(that, xhr, data) {
             that.$contentElement.children(".icon-refresh").addClass("error");
           }
        }
      });
    }
  }

  function initAuthorFilter() {
    var $authorFilter = $(".filter.filter--author");
    if (! $authorFilter.length) {
      return false;
    }

    //transform list items
    var $oldLabels = $(".filter__check-list--authors label"),
        $newLabels = $("<div/>"),
        sortLetters = [];

    $oldLabels.remove();
    $oldLabels.each(function() {
      var $this = $(this),
          $countLabel = $this.children("span"),
          count = $countLabel.text();
      $countLabel.remove();

      var authorName = $this.text().trim(),
          $input = $this.find("input"),
          $label = $("<label/>")
            .addClass("mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect")
            .append(
              $("<input/>").attr({
                id: $input.attr("id"),
                name: $input.attr("name"),
                value: $input.attr("value"),
                checked: $input.attr("checked"),
                type: "checkbox"
              }).addClass("mdl-checkbox__input"))
            .append($("<span/>").addClass("name").text(authorName))
            .append($("<span/>").addClass("filter__count").text(count));

        $newLabels.append($label);
        sortLetters.push(authorName.substr(0, 1));
    });

    $(".filter__check-list--authors").append($newLabels.html());

    var $filterNav = $(".filter__nav"),
        alphabetArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""),
        unavailableLetters = alphabetArray.filter(function(i) { return $.unique(sortLetters).indexOf(i) < 0 });

    $.each(alphabetArray, function() {
      var $filterLink = (unavailableLetters.indexOf(this[0]) > -1) ?
        $("<span/>").addClass("filter__nav-link--disabled") :
        $("<a/>").attr({ href: "#" });

      $filterNav.append($filterLink.addClass("filter__nav-link").text(this));
    });

    var authorList = new List("authors", {
      valueNames: [ "name" ],
      listClass: "filter__check-list--authors",
      searchClass: "filter__search-field--authors"
    });

    $(".filter__nav a").on("click", function(e) {
      e.preventDefault();
      var $this = $(this),
          letter = $this.text();
      if ($this.hasClass("is-active")) {
        $this.removeClass("is-active");
        authorList.filter();
      } else {
        $this.addClass("is-active").siblings(".is-active").removeClass("is-active")
        authorList.filter(function(item) {
          var name = item.values().name.toLowerCase();
          return name.substr(0, 1) == letter.toLowerCase();
        });
      }
    });

    var $authorSelectionInput = $("#author-selection"),
        clearSelectionInput = function() {
          $authorSelectionInput.val("");
          $authorSelectionInput.parent().removeClass("is-dirty");
        };

    $(".filter--author .clear-link").on("click", function(e) {
      e.preventDefault();
      var $checkboxes = $(this).parents(".filter").find(".mdl-checkbox__input");
      $checkboxes.each(function() {
        var $checkbox = $(this);
        $checkbox.removeProp("checked");
        $checkbox.parent().removeClass("is-checked");
      });
      authorList.filter();
      clearSelectionInput();
    });

    $authorFilter.hide();

    $authorSelectionInput
      .on("focus", function() {
        $(this).parent().addClass("is-open");
        $authorFilter.slideDown();
      })
      .on("blur", function(e) {
        e.preventDefault();
        var isOpen = $(this).parent().hasClass("is-open");
        if (! isOpen) {
          $authorFilter.slideUp();
        }
      });

    var setSelectedOptionsValues = function(context) {
      var $elem = $(context),
          optionText = $elem.val(),
          authorSelectionVal = $authorSelectionInput.val() ? $authorSelectionInput.val().split("; ") : [];
      if ($elem.prop("checked")) {
        authorSelectionVal.push(optionText)
      } else {
        authorSelectionVal = $.grep(authorSelectionVal, function(value) {
          return value != optionText;
        });
      }
      if (authorSelectionVal.length) {
        $authorSelectionInput.parent().addClass("is-dirty");
      }
      $authorSelectionInput.val(authorSelectionVal.join("; "));
    }

    $(".filter__check-list--authors input:checked").each(function() {
      setSelectedOptionsValues(this);
    });

    $(".filter__check-list--authors input").on("change", function() {
      setSelectedOptionsValues(this);
    });

    var initialValue = $authorSelectionInput.val();
    var closeFilter = function($openInput) {
      $authorFilter.slideUp();
      $openInput.removeClass("is-open").removeClass("is-focused");

      if ($authorSelectionInput.val() !== initialValue) {
        submitFilterForm();
      }
    }

    $("body").on("click.filter--author", function(e) {
      var $target = $(e.target),
          filterSelector = ".filter--author",
          $openInput = $authorFilter.prev(".is-open"),
          isOpenText = $target.is(".is-open") || $target.parents(".is-open").length,
          $filter = $target.is(filterSelector) ? $target : $target.parents(filterSelector).first();

      if (! $filter.length && ! isOpenText && $openInput.length) {
        closeFilter($openInput);
      } else if ($openInput.length && ! $target.parent().next().is(filterSelector) && ! $target.parents(filterSelector).length) {
        closeFilter($openInput);
      } else if ($openInput.length) {
        $openInput.addClass("is-focused");
      }
    });
  }

  function initOrderBy() {
    var $orderbyLabels = $(".order_by #id_order_by label");
    if (! $orderbyLabels.length) {
      return false;
    }

    $orderbyLabels.each(function() {
      var $this = $(this),
          $parent = $this.parent(),
          $checkbox = $this.children("input").addClass("hidden"),
          $label = $("<span/>").text($.trim($this.text()));
      $this.text("");
      $this.append($checkbox).append($label);

      $parent.addClass("sort-link");
      if ($checkbox.prop("checked")) {
        $parent.addClass("sort-link--active");
      }
    });

    $("form.order_by .sort-link").on("click", function(e) {
      e.preventDefault();
      $(this).find("input").prop("checked", "checked");
      $("form.order_by").submit();
    });

    $("form.order_by input[type='radio']").on("change", function() {
      $("form.order_by").submit();
    });
  }

  function initAnnotatorDropdown() {
    var $marginContainer = $(".margin-container");

    if ($marginContainer.length) {
      $marginContainer.on("click", ".dropdown-toggle", function() {
        var $menu = $(this).parent().find(".dropdown-menu");
        if ($menu.css("display") === "none") {
          $menu.css({ display: "block" });
        } else {
          $menu.css({ display: "none" });
        }
      });
    }
  }

  initSearchForm();
  initPageFilter();
  initBookHeader();
  initVisualization();
  initCustomActions();
  initAnnotatorDropdown();
});
<commit_msg>Focus on search input when toggled visible<commit_after>$(function() {

  function submitFilterForm() {
    $(".mdl-layout").addClass("is-submitting");
    $(".page-filter__form").submit();
  }

  function initPageFilter() {
    var $pageFilter = $(".page-filter");
    if ($pageFilter.length) {
      var checkForActiveFilters = function() {
            var $filterInputs = $pageFilter.find(".mdl-textfield__input, .mdl-switch__input"),
                activeFilters = $filterInputs.filter(function() {
                  var $this = $(this);
                  if ($this.is(".mdl-switch__input")) {
                    return $this.prop("checked");
                  } else {
                    return $this.val();
                  }
                });
            if (activeFilters.length) {
              $pageFilter.addClass("is-active");
            } else {
              $pageFilter.removeClass("is-active");
            }
          };

      $(".toggle-button").on("click", function(e) {
        e.preventDefault();
        if ($pageFilter.hasClass("is-visible")) {
          $pageFilter.removeClass("is-visible");
        } else {
          $pageFilter.addClass("is-visible");
        }

        checkForActiveFilters();
      });

      var $filterForm = $(".page-filter__form");
      $filterForm.on("change", "input[type='checkbox']", function() {
        submitFilterForm();
      });

    checkForActiveFilters();
    initAuthorFilter();
    initOrderBy();
    }
  }

  function initSelectize() {
    var $selectField = $(".mdl-selectfield__select");
    if ($selectField.length) {
      Selectize.define("active_css_classes", function(options) {
        var self = this;

        this.onFocus = (function() {
          var original = self.onFocus;
            return function() {
              var $select_field = self.$control.parents(".mdl-selectfield");
              $select_field.addClass("is-active");
              return original.apply(this, arguments);
            }
        })();

        this.onBlur = (function() {
          var original = self.onBlur;
            return function() {
              var $select_field = self.$control.parents(".mdl-selectfield");
              $select_field.removeClass("is-active");
              return original.apply(this, arguments);
            }
        })();

        this.onChange = (function() {
          var original = self.onBlur;
            return function(value) {
              var $select_field = self.$control.parents(".mdl-selectfield");
              if (value.length) {
                $select_field.addClass("is-dirty");
              } else {
                $select_field.removeClass("is-dirty");
              }
              return original.apply(this, arguments);
            }
        })();
      });

      var $selectizedFields = $selectField.selectize({
        allowEmptyOption: true,
        plugins: ["active_css_classes"]
      });

      window.selectizedFields = [];
      $selectizedFields.each(function() {
        window.selectizedFields.push($(this)[0].selectize);
      });
    }
  }

  function initFixedScrollSearchHeader() {
    var $searchFormHeader = $(".search-form-header");
    if ($searchFormHeader.length) {
      var headerHeight = $searchFormHeader.height();
      $("body").on("scroll", function() {
        var scrollTop = $(this).scrollTop(),
            cutoff = $searchFormHeader.position().top + headerHeight;
        if (scrollTop > cutoff) {
          $searchFormHeader.addClass("is-fixed");
        } else {
          $searchFormHeader.removeClass("is-fixed");
        }
      });
    }
  }

  function initSearchForm() {
    initSelectize();
    initFixedScrollSearchHeader();
    var $searchForm = $(".search-form-header");
    if ($searchForm.length) {
      $("[data-action=toggle-search-form]").on("click", function() {
        $searchForm.toggleClass("is-hidden");
        if (! $searchForm.hasClass("is-hidden")) {
          $("#id_query").focus();
        }
      });
    }
  }

  function initCustomActions() {
    var $itemImageLinks = $(".item__image__link");
    if ($itemImageLinks.length) {
      $itemImageLinks.on("mouseenter", function() {
        $(this).parents(".collection__item").find(".item__heading .item__link").addClass("is-hovered");
      }).on("mouseleave", function() {
        $(this).parents(".collection__item").find(".item__heading .item__link").removeClass("is-hovered");
      });
    }

    var $drawerCloseButton = $(".mdl-layout__drawer__close_button");
    if ($drawerCloseButton.length) {
      $drawerCloseButton.on("click", function(e) {
        e.preventDefault();
        $(".search-form-header").addClass("is-hidden");
        $(".mdl-layout__drawer.is-visible, .mdl-layout__obfuscator.is-visible").removeClass("is-visible");
      });
    }
  }

  function initBookHeader() {
    var $bookHeader = $("#book-header");
    if (! $bookHeader.length) {
      return false;
    }
    $bookHeader.stickySidebar({
      topSpacing: 20,
      containerSelector: "#books-detail article",
      minWidth: 649,
      resizeSensor: false
    });

    var $body = $("body"),
        $navLinks = $(".item-navigation-link"),
        activeClass = "item-navigation-link--active";

    $navLinks.on("click", function(e) {
      var $this = $(this),
          hash = $this.attr("href"),
          $target = $("[name=" + hash.slice(1) + "]");

      if ($target.length) {
        e.preventDefault();
        $this.siblings().removeClass(activeClass);
        $this.addClass(activeClass);
        $this.blur();

        $body.animate({
          scrollTop: $target.position().top
        }, 500);
      }
    });

    var navLinkTargets = [],
        navLinkSelectors = [];
    $navLinks.each(function() {
      navLinkTargets.push($(this).attr("href"));
    });

    if (navLinkTargets.length) {
      $.each(navLinkTargets, function() {
        navLinkSelectors.push(".item-gallery__title a[name=" + this.slice(1) + "]");
      })
    }

    $body.scroll(function() {
        clearTimeout($.data(this, "scrollTimer"));
        $.data(this, "scrollTimer", setTimeout(function() {
            var activeTab = "",
                offset = 64;
            if (navLinkSelectors.length) {
              if ($body.scrollTop() < offset) {
                var $this = $(navLinkSelectors[0]);
                $(".item-navigation-link").removeClass(activeClass);
                $(".item-navigation-link[href=#"+$this.attr("name")+"]").addClass(activeClass);
              } else {
                $(navLinkSelectors.join(",")).each(function() {
                  var $this = $(this);
                  if ($this.position().top < $body.scrollTop() + offset ) {
                    $(".item-navigation-link").removeClass(activeClass);
                    $(".item-navigation-link[href=#"+$this.attr("name")+"]").addClass(activeClass);
                  }
                });
              }
            }
        }, 250));
    });
  }

  function initVisualization() {
    var $visualizationMarkers = $(".visualization-chapter-marker");
    if ($visualizationMarkers.length) {
      $visualizationMarkers.webuiPopover({
        trigger: "hover",
        animation: "fade",
        placement: "auto-top",
        arrow: true,
        delay: {
          show: 300,
          hide: 1000
        },
        style: "visualization",
        type: "async",
        async: {
           error: function(that, xhr, data) {
             that.$contentElement.children(".icon-refresh").addClass("error");
           }
        }
      });
    }
  }

  function initAuthorFilter() {
    var $authorFilter = $(".filter.filter--author");
    if (! $authorFilter.length) {
      return false;
    }

    //transform list items
    var $oldLabels = $(".filter__check-list--authors label"),
        $newLabels = $("<div/>"),
        sortLetters = [];

    $oldLabels.remove();
    $oldLabels.each(function() {
      var $this = $(this),
          $countLabel = $this.children("span"),
          count = $countLabel.text();
      $countLabel.remove();

      var authorName = $this.text().trim(),
          $input = $this.find("input"),
          $label = $("<label/>")
            .addClass("mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect")
            .append(
              $("<input/>").attr({
                id: $input.attr("id"),
                name: $input.attr("name"),
                value: $input.attr("value"),
                checked: $input.attr("checked"),
                type: "checkbox"
              }).addClass("mdl-checkbox__input"))
            .append($("<span/>").addClass("name").text(authorName))
            .append($("<span/>").addClass("filter__count").text(count));

        $newLabels.append($label);
        sortLetters.push(authorName.substr(0, 1));
    });

    $(".filter__check-list--authors").append($newLabels.html());

    var $filterNav = $(".filter__nav"),
        alphabetArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""),
        unavailableLetters = alphabetArray.filter(function(i) { return $.unique(sortLetters).indexOf(i) < 0 });

    $.each(alphabetArray, function() {
      var $filterLink = (unavailableLetters.indexOf(this[0]) > -1) ?
        $("<span/>").addClass("filter__nav-link--disabled") :
        $("<a/>").attr({ href: "#" });

      $filterNav.append($filterLink.addClass("filter__nav-link").text(this));
    });

    var authorList = new List("authors", {
      valueNames: [ "name" ],
      listClass: "filter__check-list--authors",
      searchClass: "filter__search-field--authors"
    });

    $(".filter__nav a").on("click", function(e) {
      e.preventDefault();
      var $this = $(this),
          letter = $this.text();
      if ($this.hasClass("is-active")) {
        $this.removeClass("is-active");
        authorList.filter();
      } else {
        $this.addClass("is-active").siblings(".is-active").removeClass("is-active")
        authorList.filter(function(item) {
          var name = item.values().name.toLowerCase();
          return name.substr(0, 1) == letter.toLowerCase();
        });
      }
    });

    var $authorSelectionInput = $("#author-selection"),
        clearSelectionInput = function() {
          $authorSelectionInput.val("");
          $authorSelectionInput.parent().removeClass("is-dirty");
        };

    $(".filter--author .clear-link").on("click", function(e) {
      e.preventDefault();
      var $checkboxes = $(this).parents(".filter").find(".mdl-checkbox__input");
      $checkboxes.each(function() {
        var $checkbox = $(this);
        $checkbox.removeProp("checked");
        $checkbox.parent().removeClass("is-checked");
      });
      authorList.filter();
      clearSelectionInput();
    });

    $authorFilter.hide();

    $authorSelectionInput
      .on("focus", function() {
        $(this).parent().addClass("is-open");
        $authorFilter.slideDown();
      })
      .on("blur", function(e) {
        e.preventDefault();
        var isOpen = $(this).parent().hasClass("is-open");
        if (! isOpen) {
          $authorFilter.slideUp();
        }
      });

    var setSelectedOptionsValues = function(context) {
      var $elem = $(context),
          optionText = $elem.val(),
          authorSelectionVal = $authorSelectionInput.val() ? $authorSelectionInput.val().split("; ") : [];
      if ($elem.prop("checked")) {
        authorSelectionVal.push(optionText)
      } else {
        authorSelectionVal = $.grep(authorSelectionVal, function(value) {
          return value != optionText;
        });
      }
      if (authorSelectionVal.length) {
        $authorSelectionInput.parent().addClass("is-dirty");
      }
      $authorSelectionInput.val(authorSelectionVal.join("; "));
    }

    $(".filter__check-list--authors input:checked").each(function() {
      setSelectedOptionsValues(this);
    });

    $(".filter__check-list--authors input").on("change", function() {
      setSelectedOptionsValues(this);
    });

    var initialValue = $authorSelectionInput.val();
    var closeFilter = function($openInput) {
      $authorFilter.slideUp();
      $openInput.removeClass("is-open").removeClass("is-focused");

      if ($authorSelectionInput.val() !== initialValue) {
        submitFilterForm();
      }
    }

    $("body").on("click.filter--author", function(e) {
      var $target = $(e.target),
          filterSelector = ".filter--author",
          $openInput = $authorFilter.prev(".is-open"),
          isOpenText = $target.is(".is-open") || $target.parents(".is-open").length,
          $filter = $target.is(filterSelector) ? $target : $target.parents(filterSelector).first();

      if (! $filter.length && ! isOpenText && $openInput.length) {
        closeFilter($openInput);
      } else if ($openInput.length && ! $target.parent().next().is(filterSelector) && ! $target.parents(filterSelector).length) {
        closeFilter($openInput);
      } else if ($openInput.length) {
        $openInput.addClass("is-focused");
      }
    });
  }

  function initOrderBy() {
    var $orderbyLabels = $(".order_by #id_order_by label");
    if (! $orderbyLabels.length) {
      return false;
    }

    $orderbyLabels.each(function() {
      var $this = $(this),
          $parent = $this.parent(),
          $checkbox = $this.children("input").addClass("hidden"),
          $label = $("<span/>").text($.trim($this.text()));
      $this.text("");
      $this.append($checkbox).append($label);

      $parent.addClass("sort-link");
      if ($checkbox.prop("checked")) {
        $parent.addClass("sort-link--active");
      }
    });

    $("form.order_by .sort-link").on("click", function(e) {
      e.preventDefault();
      $(this).find("input").prop("checked", "checked");
      $("form.order_by").submit();
    });

    $("form.order_by input[type='radio']").on("change", function() {
      $("form.order_by").submit();
    });
  }

  function initAnnotatorDropdown() {
    var $marginContainer = $(".margin-container");

    if ($marginContainer.length) {
      $marginContainer.on("click", ".dropdown-toggle", function() {
        var $menu = $(this).parent().find(".dropdown-menu");
        if ($menu.css("display") === "none") {
          $menu.css({ display: "block" });
        } else {
          $menu.css({ display: "none" });
        }
      });
    }
  }

  initSearchForm();
  initPageFilter();
  initBookHeader();
  initVisualization();
  initCustomActions();
  initAnnotatorDropdown();
});
<|endoftext|>


<commit_before>/**
 * @flow
 * @file
 */
import express from 'express'
import spdy from 'spdy'
import chalk from 'chalk'
//
import server from './server'
import {serverOptions as options} from './config'
const app: express$Application = express()
const PORT: number = +process.env.PORT || 3000

server(app)

spdy.createServer(options, app).listen(PORT, () => {
	console.log(chalk.green(`SERVER IS LISTENING ON ${PORT}`))
})
<commit_msg>style(server): fix variable names<commit_after>/**
 * @flow
 * @file
 */
import express from 'express'
import spdy from 'spdy'
import chalk from 'chalk'
//
import server from './server'
import {serverOptions as options} from './config'
const app: express$Application = express()
const PORT: number = +process.env.PORT || 3000

const decoratedProductionServer = server(app)

spdy.createServer(options, decoratedProductionServer).listen(PORT, () => {
	console.log(chalk.green(`SERVER IS LISTENING ON ${PORT}`))
})
<|endoftext|>


<commit_before>// file: layout/index.js
import React from 'react';
// import { Link } from 'react-router';
import LogoutLink from 'shared/LogoutLink';
import mdlUpgrade from 'lib/mdlUpgrade';
import Layout, {
  LayoutHeader,
  LayoutIcon,
  LayoutHeaderRow,
  LayoutTitle,
  LayoutSpacer,
  Navigation,
  NavigationLink,
  LayoutDrawer,
  LayoutContent,
} from 'react-to-mdl/layout';

import '!style!css!react-select/dist/react-select.css';

export default class extends React.Component {
  render() {
    return (
      <Layout id="pwr2-home">
        <LayoutHeader>
          <LayoutIcon />
          <LayoutHeaderRow>
            <LayoutTitle>pwr2-docker</LayoutTitle>
            <LayoutSpacer />
            <Navigation>
              <NavigationLink to="/admin">Inicio</NavigationLink>
              <NavigationLink to="/admin/star-wars">Star Wars Examples</NavigationLink>
              <NavigationLink to="/admin/graphiql">GraphiQL</NavigationLink>
            </Navigation>
          </LayoutHeaderRow>
        </LayoutHeader>

        <LayoutDrawer>
          <Navigation>
            <NavigationLink to="/">Inicio</NavigationLink>
            <NavigationLink to="/admin/users">Users</NavigationLink>
            <NavigationLink to="/admin/star-wars">Star Wars Examples</NavigationLink>
            <NavigationLink to="/admin/graphiql">GraphiQL</NavigationLink>
            <NavigationLink to="/docs">Documentation</NavigationLink>
            <LogoutLink />
          </Navigation>
        </LayoutDrawer>

        <LayoutContent>
          { this.props.children }
        </LayoutContent>
      </Layout>
    );
  }
}
<commit_msg>Use  instead of <NavigationLink /> to avoid react-router until https://github.com/iporaitech/react-to-mdl/issues/2 is DONE<commit_after>// file: layout/index.js
import React from 'react';
// import { Link } from 'react-router';
import LogoutLink from 'shared/LogoutLink';
import mdlUpgrade from 'lib/mdlUpgrade';
import Layout, {
  LayoutHeader,
  LayoutIcon,
  LayoutHeaderRow,
  LayoutTitle,
  LayoutSpacer,
  Navigation,
  NavigationLink,
  LayoutDrawer,
  LayoutContent,
} from 'react-to-mdl/layout';

import '!style!css!react-select/dist/react-select.css';

export default class extends React.Component {
  render() {
    return (
      <Layout id="pwr2-home">
        <LayoutHeader>
          <LayoutIcon />
          <LayoutHeaderRow>
            <LayoutTitle>pwr2-docker</LayoutTitle>
            <LayoutSpacer />
            <Navigation>
              <NavigationLink to="/admin">Inicio</NavigationLink>
              Star Wars
              <NavigationLink to="/admin/graphiql">GraphiQL</NavigationLink>
            </Navigation>
          </LayoutHeaderRow>
        </LayoutHeader>

        <LayoutDrawer>
          <Navigation>
            <NavigationLink to="/">Inicio</NavigationLink>
            <NavigationLink to="/admin/users">Users</NavigationLink>
            <NavigationLink to="/admin/star-wars">Star Wars Examples</NavigationLink>
            <NavigationLink to="/admin/graphiql">GraphiQL</NavigationLink>
            <NavigationLink to="/docs">Documentation</NavigationLink>
            <LogoutLink />
          </Navigation>
        </LayoutDrawer>

        <LayoutContent>
          { this.props.children }
        </LayoutContent>
      </Layout>
    );
  }
}
<|endoftext|>


<commit_before>import {combineReducers} from "redux";

import app from './appReducers.ios.js';
import addIngredient from './addIngredientReducers.ios.js';
import facebook from './facebookReducer.js';

export default combineReducers({
  app,
  addIngredient,
  facebook
})
<commit_msg>need to add facebook reducer<commit_after>import {combineReducers} from "redux";

import app from './appReducers.ios.js';
import addIngredient from './addIngredientReducers.ios.js';
import facebook from './facebookReducer.ios.js';

export default combineReducers({
  app,
  addIngredient,
  facebook
})

// import AddRecipe from './AddRecipe.ios.js';

//<AddRecipe info={this.props.recipe} ingredients={this.state.ingredients}/>
<|endoftext|>