<commit_before>/**
 * Shows taxonomic lineage.
 *
 */
define(['jquery', 'uuid', 'kb_lib/html', 'kb_lib/jsonRpc/dynamicServiceClient', 'kbaseUI/widget/legacy/widget'], function ($, Uuid, html, DynamicServiceClient) {
    'use strict';

    const t = html.tag;
    const a = t('a');
    const div = t('div');
    const span = t('span');
    const table = t('table');
    const tr = t('tr');
    const th = t('th');
    const td = t('td');

    $.KBWidget({
        name: 'KBaseGenomeRELineage',
        parent: 'kbaseWidget',
        version: '1.0.0',
        options: {
            width: 600,
            genomeInfo: null,
            genomeID: null,
            timestamp: null
        },
        genome: null,
        token: null,

        init: function (options) {
            this._super(options);
            if (!this.options.genomeInfo) {
                this.renderError('Genome information not supplied');
                return;
            }
            this.genome = options.genomeInfo.data;
            this.genomeID = options.genomeID;

            this.render();
            return this;
        },

        renderLineageTable(lineage, taxonRef, scientificName) {
            const taxonURL = `/#review/taxonomy/${taxonRef.ns}/${taxonRef.id}/${taxonRef.ts}`;
            this.$elem.empty().append(
                table(
                    {
                        class: 'table table-bordered'
                    },
                    [
                        tr([
                            th(
                                {
                                    style: {
                                        width: '11em'
                                    }
                                },
                                'Scientific Name'
                            ),
                            td(
                                {
                                    dataField: 'scientific-name',
                                    style: {
                                        fontStyle: 'italic'
                                    }
                                },
                                a(
                                    {
                                        href: taxonURL,
                                        target: '_blank'
                                    },
                                    scientificName
                                )
                            )
                        ]),
                        tr([th('Taxonomic Lineage'), td(this.buildLineage(lineage))])
                    ]
                )
            );
        },

        fetchRELineage: function (genomeRef) {
            const taxonomyAPI = new DynamicServiceClient({
                url: this.runtime.config('services.service_wizard.url'),
                module: 'taxonomy_re_api',
                token: this.runtime.service('session').getAuthToken()
            });
            let timestamp = this.options.timestamp;
            // console.warn('ts?', timestamp, Date.now());
            // TODO: important, remove the following line after the demo! Currently things
            //       break due to the database being incomplete, so there is not complete
            //       coverage over time, and queries which should never fail, do.
            // TODO: the actual timestamp should be ... based on the timestamp associated
            //       with ... the taxon linked to the object?
            //            ... the time the taxon was linked to the object?
            timestamp = Date.now();

            // TODO: resolve the usage of 'ts' in 'get_taxon...'. It should not be necessary
            // since the taxon assignment to an object is not dependent upon some reference time,
            // it is fixed in that respect.
            return taxonomyAPI.callFunc('get_taxon_from_ws_obj', [{
                obj_ref: genomeRef,
                ns: 'ncbi_taxonomy'
            }])
                .then(([result]) => {
                    if (result.results.length === 0) {
                        throw new Error('No taxon found for this object');
                    }
                    const [taxon] = result.results;
                    const taxonRef = {
                        ns: taxon.ns,
                        id: taxon.id,
                        ts: timestamp
                    };
                    return Promise.all([
                        taxonomyAPI.callFunc('get_lineage', [taxonRef]),
                        taxonomyAPI.callFunc('get_taxon', [taxonRef])
                    ])
                        .then(([[{results: lineageResults}], [{results: [taxon]}]]) => {
                            if (!taxon) {
                                throw new Error('Taxon not found');
                            }
                            const {scientific_name: scientificName} = taxon;
                            this.renderLineageTable(lineageResults, taxonRef, scientificName);
                        });
                });

        },

        buildLineage: function (lineage) {
            // Trim off the "root" which is always at the top of the lineage.
            lineage = lineage.slice(1);
            return div(
                {
                    style: {
                        whiteSpace: 'nowrap',
                        overflowX: 'auto'
                    }
                },
                lineage.map((taxon) => {
                    const url = `/#review/taxonomy/${taxon.ns}/${taxon.id}`;
                    return div(
                        a(
                            {
                                href: url,
                                target: '_blank'
                            },
                            taxon.scientific_name
                        )
                    );
                })
            );
        },

        renderLoading: function () {
            this.$elem.empty();
            this.$elem.append(div({
                style: {
                    textAlign: 'left',
                    marginBottom: '10px',
                    color: 'rgba(150, 150, 150, 1)'
                }
            }, [
                span({
                    class: 'fa fa-spinner fa-pulse'
                }),
                span({
                    style: {
                        marginLeft: '4px'
                    }
                }, 'Loading lineage...')
            ]));
        },

        renderError: function (error) {
            var errorMessage;
            if (typeof error === 'string') {
                errorMessage = error;
            } else if (error.error && error.error.message) {
                errorMessage = error.error.message;
            } else {
                errorMessage = 'Sorry, an unknown error occurred';
            }

            var errorAlert = div(
                {
                    class: 'alert alert-danger'
                },
                [
                    span(
                        {
                            textWeight: 'bold'
                        },
                        'Error: '
                    ),
                    span(errorMessage)
                ]
            );
            this.$elem.empty();
            this.$elem.append(errorAlert);
        },

        render: function () {
            const {ws, id, ver} = this.options.genomeRef;
            const genomeRef = [ws, id, ver].join('/');
            this.renderLoading();
            this.fetchRELineage(genomeRef)
                .catch((err) => {
                    console.error('ERROR', err);
                    this.renderError('Error fetching lineage: ' + err.message);
                });
        },

    });
});
<commit_msg>update re landing page url<commit_after>/**
 * Shows taxonomic lineage.
 *
 */
define(['jquery', 'uuid', 'kb_lib/html', 'kb_lib/jsonRpc/dynamicServiceClient', 'kbaseUI/widget/legacy/widget'], function ($, Uuid, html, DynamicServiceClient) {
    'use strict';

    const t = html.tag;
    const a = t('a');
    const div = t('div');
    const span = t('span');
    const table = t('table');
    const tr = t('tr');
    const th = t('th');
    const td = t('td');

    $.KBWidget({
        name: 'KBaseGenomeRELineage',
        parent: 'kbaseWidget',
        version: '1.0.0',
        options: {
            width: 600,
            genomeInfo: null,
            genomeID: null,
            timestamp: null
        },
        genome: null,
        token: null,

        init: function (options) {
            this._super(options);
            if (!this.options.genomeInfo) {
                this.renderError('Genome information not supplied');
                return;
            }
            this.genome = options.genomeInfo.data;
            this.genomeID = options.genomeID;

            this.render();
            return this;
        },

        renderLineageTable(lineage, taxonRef, scientificName) {
            const taxonURL = `/#review/${taxonRef.ns}/${taxonRef.id}/${taxonRef.ts}`;
            this.$elem.empty().append(
                table(
                    {
                        class: 'table table-bordered'
                    },
                    [
                        tr([
                            th(
                                {
                                    style: {
                                        width: '11em'
                                    }
                                },
                                'Scientific Name'
                            ),
                            td(
                                {
                                    dataField: 'scientific-name',
                                    style: {
                                        fontStyle: 'italic'
                                    }
                                },
                                a(
                                    {
                                        href: taxonURL,
                                        target: '_blank'
                                    },
                                    scientificName
                                )
                            )
                        ]),
                        tr([th('Taxonomic Lineage'), td(this.buildLineage(lineage))])
                    ]
                )
            );
        },

        fetchRELineage: function (genomeRef) {
            const taxonomyAPI = new DynamicServiceClient({
                url: this.runtime.config('services.service_wizard.url'),
                module: 'taxonomy_re_api',
                token: this.runtime.service('session').getAuthToken()
            });
            let timestamp = this.options.timestamp;
            // console.warn('ts?', timestamp, Date.now());
            // TODO: important, remove the following line after the demo! Currently things
            //       break due to the database being incomplete, so there is not complete
            //       coverage over time, and queries which should never fail, do.
            // TODO: the actual timestamp should be ... based on the timestamp associated
            //       with ... the taxon linked to the object?
            //            ... the time the taxon was linked to the object?
            timestamp = Date.now();

            // TODO: resolve the usage of 'ts' in 'get_taxon...'. It should not be necessary
            // since the taxon assignment to an object is not dependent upon some reference time,
            // it is fixed in that respect.
            return taxonomyAPI.callFunc('get_taxon_from_ws_obj', [{
                obj_ref: genomeRef,
                ns: 'ncbi_taxonomy'
            }])
                .then(([result]) => {
                    if (result.results.length === 0) {
                        throw new Error('No taxon found for this object');
                    }
                    const [taxon] = result.results;
                    const taxonRef = {
                        ns: taxon.ns,
                        id: taxon.id,
                        ts: timestamp
                    };
                    return Promise.all([
                        taxonomyAPI.callFunc('get_lineage', [taxonRef]),
                        taxonomyAPI.callFunc('get_taxon', [taxonRef])
                    ])
                        .then(([[{results: lineageResults}], [{results: [taxon]}]]) => {
                            if (!taxon) {
                                throw new Error('Taxon not found');
                            }
                            const {scientific_name: scientificName} = taxon;
                            this.renderLineageTable(lineageResults, taxonRef, scientificName);
                        });
                });

        },

        buildLineage: function (lineage) {
            // Trim off the "root" which is always at the top of the lineage.
            lineage = lineage.slice(1);
            return div(
                {
                    style: {
                        whiteSpace: 'nowrap',
                        overflowX: 'auto'
                    }
                },
                lineage.map((taxon) => {
                    const url = `/#review/${taxon.ns}/${taxon.id}`;
                    return div(
                        a(
                            {
                                href: url,
                                target: '_blank'
                            },
                            taxon.scientific_name
                        )
                    );
                })
            );
        },

        renderLoading: function () {
            this.$elem.empty();
            this.$elem.append(div({
                style: {
                    textAlign: 'left',
                    marginBottom: '10px',
                    color: 'rgba(150, 150, 150, 1)'
                }
            }, [
                span({
                    class: 'fa fa-spinner fa-pulse'
                }),
                span({
                    style: {
                        marginLeft: '4px'
                    }
                }, 'Loading lineage...')
            ]));
        },

        renderError: function (error) {
            var errorMessage;
            if (typeof error === 'string') {
                errorMessage = error;
            } else if (error.error && error.error.message) {
                errorMessage = error.error.message;
            } else {
                errorMessage = 'Sorry, an unknown error occurred';
            }

            var errorAlert = div(
                {
                    class: 'alert alert-danger'
                },
                [
                    span(
                        {
                            textWeight: 'bold'
                        },
                        'Error: '
                    ),
                    span(errorMessage)
                ]
            );
            this.$elem.empty();
            this.$elem.append(errorAlert);
        },

        render: function () {
            const {ws, id, ver} = this.options.genomeRef;
            const genomeRef = [ws, id, ver].join('/');
            this.renderLoading();
            this.fetchRELineage(genomeRef)
                .catch((err) => {
                    console.error('ERROR', err);
                    this.renderError('Error fetching lineage: ' + err.message);
                });
        },

    });
});
<|endoftext|>


<commit_before>const parser = require('./parserObject')
const estemplate = require('./estemplate')

/* Utility Functions */
const {
  mayBe,
  isLanguageConstruct,
  isIOFunc,
  isIOMethod,
  unescape,
  returnRest
} = require('./utilityFunctions')

/*  Predefined regexes */
const spaceRegex = /^([ \t]+)((.|\n)*)$/
const returnRegex = /^(\n)((.|\n)*)$/
const idRegex = /^([_a-zA-Z]+[a-zA-Z0-9_]*)((.|\n)*)$/
const numRegex = /^((?:\d+(?:\.\d*)?|\.\d+)(?:[e][+-]?\d+)?)((.|\n)*)$/
const boolRegex = /^(true|false)((.|\n)*)$/i
const stringRegex = /^('[^\\']*(?:\\.[^\\']*)*')((.|\n)*)$/
const binaryOperatorRegex = /^(\+\+|\+|-|%|\/|\*|<<|<=|<|>y>>|>>|>=|>|&&|&|\|\||\||\^|==|!=)((.|\n)*)$/
const unaryOperatorRegex = /^(:type|-|!)((.|\n)*)$/
const openCurlyRegex = /^({)((.|\n)*)$/
const closeCurlyRegex = /^(})((.|\n)*)$/
const openSquareBracketRegex = /^(\[)((.|\n)*)$/
const closeSquareBracketRegex = /^(])((.|\n)*)$/
const openParensRegex = /^(\()((.|\n)*)$/
const closeParensRegex = /^(\))((.|\n)*)$/
const commaRegex = /^(,)((.|\n)*)$/
const colonRegex = /^(:)((.|\n)*)$/
const singleLineCommentRegex = /^((\/\/)(.*)(\n))((.|\n)*)$/
const multiLineCommentRegex = /^((\/\*)((.|\n)*?)(\*\/))((.|\n)*)$/
const nullRegex = /^(null)((.|\n)*)$/
const assignmentOperatorRegex = /^(\+=|-=|\*=|\/=|\*\*=|>>>=|>>=|<<=|%=|&=|\^=|\|=|=)((.|\n)*)$/
const deleteRegex = /^(delete)((.|\n)*)$/

/*
  All required parsers are created below
*/
const spaceParser = parser.regex(spaceRegex)

const equalSignParser = parser.regex(/^(\s+=\s+)((.|\n)*)$/)

const assignmentOperator = parser.regex(assignmentOperatorRegex)

const thinArrowParser = parser.regex(/^(\s*->\s+)((.|\n)*)$/)

const reverseBindParser = parser.regex(/^(\s*<-\s+)((.|\n)*)$/)

const slashParser = parser.regex(/^(\s*\\)((.|\n)*)$/)

const letParser = parser.regex(/^(\s*let\s+)((.|\n)*)$/)

const inParser = parser.regex(/^(\s*in\s+)((.|\n)*)$/)

const dotParser = parser.regex(/^(\.)((.|\n)*)$/)

const ifParser = parser.regex(/^(if\s+)((.|\n)*)$/)
const thenParser = parser.regex(/^(then\s+)((.|\n)*)$/)
const elseParser = parser.regex(/^(else\s+)((.|\n)*)$/)

const doParser = parser.regex(/^(do)((.|\n)*)$/)

const returnKeywordParser = parser.regex(/^(return)((.|\n)*)$/)

const returnParser = input => mayBe(
  returnRegex.exec(input.str),
  (a, newLine, rest) => returnRest(newLine, input, rest, {'name': 'return', 'value': 1})
)

const numberParser = input => mayBe(
  numRegex.exec(input.str),
  (a, num, rest) => returnRest(estemplate.literal(num, num), input, rest, {'name': 'column', 'value': num.length})
)

const identifierParser = input => mayBe(
  idRegex.exec(input.str),
  (a, name, rest) => (isLanguageConstruct(name) || isIOFunc(name) || isIOMethod(name)) ? null
    : returnRest(estemplate.identifier(name), input, rest, {'name': 'column', 'value': name.length}))

const ioFuncNameParser = input => mayBe(
  idRegex.exec(input.str),
  (a, name, rest) => isIOFunc(name) ? returnRest(estemplate.identifier(name), input, rest, {'name': 'column', 'value': name.length}) : null
)

const ioMethodNameParser = input => mayBe(
  idRegex.exec(input.str),
  (a, name, rest) => isIOMethod(name) ? returnRest(estemplate.identifier(name), input, rest, {'name': 'column', 'value': name.length}) : null
)

const nullParser = input => mayBe(
  nullRegex.exec(input.str),
  (a, val, rest) => returnRest(estemplate.nullLiteral(val), input, rest, {'name': 'column', 'value': 4})
)

const stringParser = input => mayBe(
  stringRegex.exec(input.str),
  (a, string, rest) => returnRest(estemplate.stringLiteral(unescape(string)),
                                    input, rest, {'name': 'column', 'value': string.length})
)

const booleanParser = input => mayBe(
    boolRegex.exec(input.str),
    (a, bool, rest) => returnRest(estemplate.boolLiteral(bool), input, rest, {'name': 'column', 'value': bool.length})
  )

const openParensParser = input => mayBe(
  openParensRegex.exec(input.str),
  (a, openParens, rest) => returnRest(openParens, input, rest, {'name': 'column', 'value': 1})
)

const closeParensParser = input => mayBe(
  closeParensRegex.exec(input.str),
  (a, closeParens, rest) => returnRest(closeParens, input, rest, {'name': 'column', 'value': 1})
)

const openCurlyBraceParser = input => mayBe(
  openCurlyRegex.exec(input.str),
  (a, openCurlyBrace, rest) => returnRest(openCurlyBrace, input, rest, {'name': 'column', 'value': openCurlyBrace.length})
)

const closeCurlyBraceParser = input => mayBe(
  closeCurlyRegex.exec(input.str),
  (a, closeCurlyBrace, rest) => returnRest(closeCurlyBrace, input, rest, {'name': 'column', 'value': closeCurlyBrace.length})
)

const openSquareBracketParser = input => mayBe(
  openSquareBracketRegex.exec(input.str),
  (a, openSquareBracket, rest) => returnRest(openSquareBracket, input, rest, {'name': 'column', 'value': openSquareBracket.length})
)

const closeSquareBracketParser = input => mayBe(
  closeSquareBracketRegex.exec(input.str),
  (a, closeSquareBracket, rest) => returnRest(closeSquareBracket, input, rest, {'name': 'column', 'value': closeSquareBracket.length})
)

const commaParser = input => mayBe(
  commaRegex.exec(input.str),
  (a, comma, rest) => returnRest(comma, input, rest, {'name': 'column', 'value': comma.length})
)

const colonParser = input => mayBe(
  colonRegex.exec(input.str),
  (a, colon, rest) => returnRest(colon, input, rest, {'name': 'column', 'value': colon.length})
)

const singleLineCommentParser = input => mayBe(
  singleLineCommentRegex.exec(input.str),
  (a, comment, b, c, d, rest) => {
    let val = comment.slice(2, comment.length - 1)
    return returnRest(estemplate.comment('Line', val), input, rest, {'name': 'return', 'value': 1})
  }
)

const multiLineCommentParser = input => mayBe(
  multiLineCommentRegex.exec(input.str),
  (a, comment, b, c, d, e, rest) => {
    let lineCount = comment.match(/\n/g) === null ? 0 : comment.match(/\n/g).length
    let val = comment.slice(2, comment.length - 2)
    return returnRest(estemplate.comment('Block', val), input, rest, {'name': 'return', 'value': lineCount})
  }
)

const binaryOperatorParser = parser.regex(binaryOperatorRegex)

const assignmentOperatorParser = input => {
  let result = parser.all(spaceParser, assignmentOperator, spaceParser)(input)
  if (result === null) return null
  let [[sp1, val, sp2], rest] = result
  return returnRest(val, input, rest.str, {'name': 'column', 'value': (sp1 + val + sp2).length})
}

const unaryOperatorParser = input => mayBe(
    unaryOperatorRegex.exec(input.str),
    (m, operator, rest) => returnRest(operator, input, rest, {'name': 'column', 'value': operator.length})
)

const parenCheck = src => mayBe(parser.regex(/^(\))((.|\n)*)$/)(src),
                              (m, val, rest) => returnRest(val, src, src.str))

const mayBeSpace = input => {
  let val = ''
  let space = spaceParser(input)
  let rest = input
  if (space !== null) [val, rest] = space
  return returnRest(val, input, rest.str, {name: 'column', value: val.length})
}

const mayBeNewLine = input => {
  let val = ''
  let result = parser.all(returnParser, spaceParser)(input)
  let rest = input
  if (result !== null) {
    [val, rest] = result
    let [, indent] = val
    return returnRest(indent, input, rest.str, {name: 'indent', value: indent.length})
  }
  return null
}

const mayBeNewLineAndIndent = input => parser.any(mayBeNewLine, mayBeSpace)(input)

const importKeywordParser = input => parser.regex(/^(import)((.|\n)*)$/)(input)

const libNameParser = input => mayBe(
  parser.regex(/^(node-core|browser-core)((.|\n)*)$/)(input),
  (val, rest) => returnRest(val, input, rest.str)
)

const importParser = input => mayBe(
  parser.all(importKeywordParser, spaceParser, libNameParser)(input),
  (val, rest) => returnRest(val[2], input, rest.str)
)

const deleteKeywordParser = input => mayBe(
    deleteRegex.exec(input.str),
    (m, operator, rest) => returnRest(operator, input, rest, {'name': 'column', 'value': operator.length})
)

/* Module exports all basic parsers */
module.exports = {
  returnParser,
  spaceParser,
  mayBeSpace,
  mayBeNewLineAndIndent,
  numberParser,
  identifierParser,
  ioFuncNameParser,
  ioMethodNameParser,
  nullParser,
  stringParser,
  booleanParser,
  openParensParser,
  closeParensParser,
  openCurlyBraceParser,
  closeCurlyBraceParser,
  openSquareBracketParser,
  closeSquareBracketParser,
  commaParser,
  colonParser,
  singleLineCommentParser,
  multiLineCommentParser,
  binaryOperatorParser,
  unaryOperatorParser,
  letParser,
  inParser,
  dotParser,
  thinArrowParser,
  reverseBindParser,
  ifParser,
  thenParser,
  elseParser,
  doParser,
  equalSignParser,
  slashParser,
  parenCheck,
  assignmentOperatorParser,
  returnKeywordParser,
  importParser,
  deleteKeywordParser
}
<commit_msg>Add support for parsing regular expressions - Add `regexRegex` - Add `regexParser` and export `regexParser`<commit_after>const parser = require('./parserObject')
const estemplate = require('./estemplate')

/* Utility Functions */
const {
  mayBe,
  isLanguageConstruct,
  isIOFunc,
  isIOMethod,
  unescape,
  returnRest
} = require('./utilityFunctions')

/*  Predefined regexes */
const spaceRegex = /^([ \t]+)((.|\n)*)$/
const returnRegex = /^(\n)((.|\n)*)$/
const idRegex = /^([_a-zA-Z]+[a-zA-Z0-9_]*)((.|\n)*)$/
const numRegex = /^((?:\d+(?:\.\d*)?|\.\d+)(?:[e][+-]?\d+)?)((.|\n)*)$/
const boolRegex = /^(true|false)((.|\n)*)$/i
const stringRegex = /^('[^\\']*(?:\\.[^\\']*)*')((.|\n)*)$/
const binaryOperatorRegex = /^(\+\+|\+|-|%|\/|\*|<<|<=|<|>y>>|>>|>=|>|&&|&|\|\||\||\^|==|!=)((.|\n)*)$/
const unaryOperatorRegex = /^(:type|-|!)((.|\n)*)$/
const openCurlyRegex = /^({)((.|\n)*)$/
const closeCurlyRegex = /^(})((.|\n)*)$/
const openSquareBracketRegex = /^(\[)((.|\n)*)$/
const closeSquareBracketRegex = /^(])((.|\n)*)$/
const openParensRegex = /^(\()((.|\n)*)$/
const closeParensRegex = /^(\))((.|\n)*)$/
const commaRegex = /^(,)((.|\n)*)$/
const colonRegex = /^(:)((.|\n)*)$/
const singleLineCommentRegex = /^((\/\/)(.*)(\n))((.|\n)*)$/
const multiLineCommentRegex = /^((\/\*)((.|\n)*?)(\*\/))((.|\n)*)$/
const nullRegex = /^(null)((.|\n)*)$/
const assignmentOperatorRegex = /^(\+=|-=|\*=|\/=|\*\*=|>>>=|>>=|<<=|%=|&=|\^=|\|=|=)((.|\n)*)$/
const deleteRegex = /^(delete)((.|\n)*)$/
const regexRegex = /^(\/((.|\n)*)\/(\w*))((.|\n)*)$/

/*
  All required parsers are created below
*/
const spaceParser = parser.regex(spaceRegex)

const equalSignParser = parser.regex(/^(\s+=\s+)((.|\n)*)$/)

const assignmentOperator = parser.regex(assignmentOperatorRegex)

const thinArrowParser = parser.regex(/^(\s*->\s+)((.|\n)*)$/)

const reverseBindParser = parser.regex(/^(\s*<-\s+)((.|\n)*)$/)

const slashParser = parser.regex(/^(\s*\\)((.|\n)*)$/)

const letParser = parser.regex(/^(\s*let\s+)((.|\n)*)$/)

const inParser = parser.regex(/^(\s*in\s+)((.|\n)*)$/)

const dotParser = parser.regex(/^(\.)((.|\n)*)$/)

const ifParser = parser.regex(/^(if\s+)((.|\n)*)$/)
const thenParser = parser.regex(/^(then\s+)((.|\n)*)$/)
const elseParser = parser.regex(/^(else\s+)((.|\n)*)$/)

const doParser = parser.regex(/^(do)((.|\n)*)$/)

const returnKeywordParser = parser.regex(/^(return)((.|\n)*)$/)

const returnParser = input => mayBe(
  returnRegex.exec(input.str),
  (a, newLine, rest) => returnRest(newLine, input, rest, {'name': 'return', 'value': 1})
)

const numberParser = input => mayBe(
  numRegex.exec(input.str),
  (a, num, rest) => returnRest(estemplate.literal(num, num), input, rest, {'name': 'column', 'value': num.length})
)

const identifierParser = input => mayBe(
  idRegex.exec(input.str),
  (a, name, rest) => (isLanguageConstruct(name) || isIOFunc(name) || isIOMethod(name)) ? null
    : returnRest(estemplate.identifier(name), input, rest, {'name': 'column', 'value': name.length}))

const ioFuncNameParser = input => mayBe(
  idRegex.exec(input.str),
  (a, name, rest) => isIOFunc(name) ? returnRest(estemplate.identifier(name), input, rest, {'name': 'column', 'value': name.length}) : null
)

const ioMethodNameParser = input => mayBe(
  idRegex.exec(input.str),
  (a, name, rest) => isIOMethod(name) ? returnRest(estemplate.identifier(name), input, rest, {'name': 'column', 'value': name.length}) : null
)

const nullParser = input => mayBe(
  nullRegex.exec(input.str),
  (a, val, rest) => returnRest(estemplate.nullLiteral(val), input, rest, {'name': 'column', 'value': 4})
)

const stringParser = input => mayBe(
  stringRegex.exec(input.str),
  (a, string, rest) => returnRest(estemplate.stringLiteral(unescape(string)),
                                    input, rest, {'name': 'column', 'value': string.length})
)

const booleanParser = input => mayBe(
    boolRegex.exec(input.str),
    (a, bool, rest) => returnRest(estemplate.boolLiteral(bool), input, rest, {'name': 'column', 'value': bool.length})
  )
const regexParser = input => {
  return mayBe(
  regexRegex.exec(input.str),
  (a, regex, pattern, b, flags, rest) => returnRest(estemplate.regex(regex, pattern, flags), input, rest,
                                                {'name': 'column', 'value': pattern.length}))
}
const openParensParser = input => mayBe(
  openParensRegex.exec(input.str),
  (a, openParens, rest) => returnRest(openParens, input, rest, {'name': 'column', 'value': 1})
)

const closeParensParser = input => mayBe(
  closeParensRegex.exec(input.str),
  (a, closeParens, rest) => returnRest(closeParens, input, rest, {'name': 'column', 'value': 1})
)

const openCurlyBraceParser = input => mayBe(
  openCurlyRegex.exec(input.str),
  (a, openCurlyBrace, rest) => returnRest(openCurlyBrace, input, rest, {'name': 'column', 'value': openCurlyBrace.length})
)

const closeCurlyBraceParser = input => mayBe(
  closeCurlyRegex.exec(input.str),
  (a, closeCurlyBrace, rest) => returnRest(closeCurlyBrace, input, rest, {'name': 'column', 'value': closeCurlyBrace.length})
)

const openSquareBracketParser = input => mayBe(
  openSquareBracketRegex.exec(input.str),
  (a, openSquareBracket, rest) => returnRest(openSquareBracket, input, rest, {'name': 'column', 'value': openSquareBracket.length})
)

const closeSquareBracketParser = input => mayBe(
  closeSquareBracketRegex.exec(input.str),
  (a, closeSquareBracket, rest) => returnRest(closeSquareBracket, input, rest, {'name': 'column', 'value': closeSquareBracket.length})
)

const commaParser = input => mayBe(
  commaRegex.exec(input.str),
  (a, comma, rest) => returnRest(comma, input, rest, {'name': 'column', 'value': comma.length})
)

const colonParser = input => mayBe(
  colonRegex.exec(input.str),
  (a, colon, rest) => returnRest(colon, input, rest, {'name': 'column', 'value': colon.length})
)

const singleLineCommentParser = input => mayBe(
  singleLineCommentRegex.exec(input.str),
  (a, comment, b, c, d, rest) => {
    let val = comment.slice(2, comment.length - 1)
    return returnRest(estemplate.comment('Line', val), input, rest, {'name': 'return', 'value': 1})
  }
)

const multiLineCommentParser = input => mayBe(
  multiLineCommentRegex.exec(input.str),
  (a, comment, b, c, d, e, rest) => {
    let lineCount = comment.match(/\n/g) === null ? 0 : comment.match(/\n/g).length
    let val = comment.slice(2, comment.length - 2)
    return returnRest(estemplate.comment('Block', val), input, rest, {'name': 'return', 'value': lineCount})
  }
)

const binaryOperatorParser = parser.regex(binaryOperatorRegex)

const assignmentOperatorParser = input => {
  let result = parser.all(spaceParser, assignmentOperator, spaceParser)(input)
  if (result === null) return null
  let [[sp1, val, sp2], rest] = result
  return returnRest(val, input, rest.str, {'name': 'column', 'value': (sp1 + val + sp2).length})
}

const unaryOperatorParser = input => mayBe(
    unaryOperatorRegex.exec(input.str),
    (m, operator, rest) => returnRest(operator, input, rest, {'name': 'column', 'value': operator.length})
)

const parenCheck = src => mayBe(parser.regex(/^(\))((.|\n)*)$/)(src),
                              (m, val, rest) => returnRest(val, src, src.str))

const mayBeSpace = input => {
  let val = ''
  let space = spaceParser(input)
  let rest = input
  if (space !== null) [val, rest] = space
  return returnRest(val, input, rest.str, {name: 'column', value: val.length})
}

const mayBeNewLine = input => {
  let val = ''
  let result = parser.all(returnParser, spaceParser)(input)
  let rest = input
  if (result !== null) {
    [val, rest] = result
    let [, indent] = val
    return returnRest(indent, input, rest.str, {name: 'indent', value: indent.length})
  }
  return null
}

const mayBeNewLineAndIndent = input => parser.any(mayBeNewLine, mayBeSpace)(input)

const importKeywordParser = input => parser.regex(/^(import)((.|\n)*)$/)(input)

const libNameParser = input => mayBe(
  parser.regex(/^(node-core|browser-core)((.|\n)*)$/)(input),
  (val, rest) => returnRest(val, input, rest.str)
)

const importParser = input => mayBe(
  parser.all(importKeywordParser, spaceParser, libNameParser)(input),
  (val, rest) => returnRest(val[2], input, rest.str)
)

const deleteKeywordParser = input => mayBe(
    deleteRegex.exec(input.str),
    (m, operator, rest) => returnRest(operator, input, rest, {'name': 'column', 'value': operator.length})
)

/* Module exports all basic parsers */
module.exports = {
  returnParser,
  spaceParser,
  mayBeSpace,
  mayBeNewLineAndIndent,
  numberParser,
  identifierParser,
  ioFuncNameParser,
  ioMethodNameParser,
  nullParser,
  stringParser,
  booleanParser,
  regexParser,
  openParensParser,
  closeParensParser,
  openCurlyBraceParser,
  closeCurlyBraceParser,
  openSquareBracketParser,
  closeSquareBracketParser,
  commaParser,
  colonParser,
  singleLineCommentParser,
  multiLineCommentParser,
  binaryOperatorParser,
  unaryOperatorParser,
  letParser,
  inParser,
  dotParser,
  thinArrowParser,
  reverseBindParser,
  ifParser,
  thenParser,
  elseParser,
  doParser,
  equalSignParser,
  slashParser,
  parenCheck,
  assignmentOperatorParser,
  returnKeywordParser,
  importParser,
  deleteKeywordParser
}
<|endoftext|>


<commit_before>import { click, fillIn, findAll, currentURL, find, visit, settled } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import authPage from 'vault/tests/pages/auth';
import { pollCluster } from 'vault/tests/helpers/poll-cluster';
import withFlash from 'vault/tests/helpers/with-flash';

const disableReplication = async (type, assert) => {
  // disable performance replication
  await visit(`/vault/replication/${type}`);
  if (findAll('[data-test-replication-link="manage"]').length) {
    await click('[data-test-replication-link="manage"]');
    await click('[data-test-disable-replication] button');
    await withFlash(click('[data-test-confirm-button]'), () => {
      if (assert) {
        assert.equal(currentURL(), `/vault/replication/${type}/manage`, 'redirects to the replication page');
        assert.equal(
          // TODO better test selectors for flash messages
          find('[data-test-flash-message-body]').textContent.trim(),
          'This cluster is having replication disabled. Vault will be unavailable for a brief period and will resume service shortly.',
          'renders info flash when disabled'
        );
      }
    });
    await settled();
  }
};

module('Acceptance | Enterprise | replication', function(hooks) {
  setupApplicationTest(hooks);

  hooks.beforeEach(async function() {
    await authPage.login();
    await disableReplication('dr');
    return disableReplication('performance');
  });

  hooks.afterEach(async function() {
    await disableReplication('dr');
    return disableReplication('performance');
  });

  test('replication', async function(assert) {
    const secondaryName = 'firstSecondary';
    const mode = 'blacklist';
    const mountType = 'kv';
    let mountPath;

    await visit('/vault/replication');
    assert.equal(currentURL(), '/vault/replication');

    // enable perf replication
    await click('[data-test-replication-type-select="performance"]');
    await fillIn('[data-test-replication-cluster-mode-select]', 'primary');

    await withFlash(click('[data-test-replication-enable]'));
    await pollCluster(this.owner);

    // add a secondary with a mount filter config
    await click('[data-test-replication-link="secondaries"]');
    await click('[data-test-secondary-add]');
    await fillIn('[data-test-replication-secondary-id]', secondaryName);
    //expand the config
    await click('[data-test-replication-secondary-token-options]');
    await fillIn('[data-test-replication-filter-mount-mode]', mode);
    await click(findAll(`[data-test-mount-filter="${mountType}"]`)[0]);
    mountPath = findAll(`[data-test-mount-filter-path-for-type="${mountType}"]`)[0].textContent.trim();
    await click('[data-test-secondary-add]');

    await pollCluster(this.owner);

    // click into the added secondary's mount filter config
    await click('[data-test-replication-link="secondaries"]');
    await click('[data-test-popup-menu-trigger]');

    await click('[data-test-replication-mount-filter-link]');
    assert.equal(currentURL(), `/vault/replication/performance/secondaries/config/show/${secondaryName}`);
    assert.ok(
      find('[data-test-mount-config-mode]')
        .textContent.trim()
        .toLowerCase()
        .includes(mode),
      'show page renders the correct mode'
    );
    assert
      .dom('[data-test-mount-config-paths]')
      .hasText(mountPath, 'show page renders the correct mount path');
    // click edit

    // delete config
    await click('[data-test-replication-link="edit-mount-config"]');
    await click('[data-test-delete-mount-config] button');
    await withFlash(click('[data-test-confirm-button]'), () => {
      assert.equal(
        findAll('[data-test-flash-message-body]')[0].textContent.trim(),
        `The performance mount filter config for the secondary ${secondaryName} was successfully deleted.`,
        'renders success flash upon deletion'
      );
    });
    assert.equal(
      currentURL(),
      `/vault/replication/performance/secondaries`,
      'redirects to the secondaries page'
    );

    // nav to DR
    await visit('/vault/replication/dr');
    await fillIn('[data-test-replication-cluster-mode-select]', 'secondary');
    assert.ok(
      find('[data-test-replication-enable]:disabled'),
      'dr secondary enable is disabled when other replication modes are on'
    );

    // disable performance replication
    await disableReplication('performance', assert);
    await pollCluster(this.owner);

    // enable dr replication
    await visit('vault/replication/dr');
    await fillIn('[data-test-replication-cluster-mode-select]', 'primary');
    await withFlash(click('button[type="submit"]'));

    await pollCluster(this.owner);
    assert.ok(
      find('[data-test-replication-title]').textContent.includes('Disaster Recovery'),
      'it displays the replication type correctly'
    );
    assert.ok(
      find('[data-test-replication-mode-display]').textContent.includes('primary'),
      'it displays the cluster mode correctly'
    );

    // add dr secondary
    await click('[data-test-replication-link="secondaries"]');
    await click('[data-test-secondary-add]');
    await fillIn('[data-test-replication-secondary-id]', secondaryName);
    await click('[data-test-secondary-add]');
    await pollCluster(this.owner);
    await pollCluster(this.owner);
    await click('[data-test-replication-link="secondaries"]');
    assert
      .dom('[data-test-secondary-name]')
      .hasText(secondaryName, 'it displays the secondary in the list of known secondaries');
  });

  test('disabling dr primary when perf replication is enabled', async function(assert) {
    await visit('vault/replication/performance');
    // enable perf replication
    await fillIn('[data-test-replication-cluster-mode-select]', 'primary');

    await withFlash(click('[data-test-replication-enable]'));
    await pollCluster(this.owner);

    // enable dr replication
    await visit('/vault/replication/dr');
    await fillIn('[data-test-replication-cluster-mode-select]', 'primary');
    await withFlash(click('[data-test-replication-enable]'));
    await pollCluster(this.owner);
    await visit('/vault/replication/dr/manage');
    assert.ok(findAll('[data-test-demote-warning]').length, 'displays the demotion warning');
  });
});
<commit_msg>fix enterprise routing assertion (#6495)<commit_after>import { click, fillIn, findAll, currentURL, find, visit, settled } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import authPage from 'vault/tests/pages/auth';
import { pollCluster } from 'vault/tests/helpers/poll-cluster';
import withFlash from 'vault/tests/helpers/with-flash';

const disableReplication = async (type, assert) => {
  // disable performance replication
  await visit(`/vault/replication/${type}`);
  if (findAll('[data-test-replication-link="manage"]').length) {
    await click('[data-test-replication-link="manage"]');
    await click('[data-test-disable-replication] button');
    await withFlash(click('[data-test-confirm-button]'), () => {
      if (assert) {
        assert.equal(currentURL(), `/vault/replication/${type}`, 'redirects to the replication page');
        assert.equal(
          // TODO better test selectors for flash messages
          find('[data-test-flash-message-body]').textContent.trim(),
          'This cluster is having replication disabled. Vault will be unavailable for a brief period and will resume service shortly.',
          'renders info flash when disabled'
        );
      }
    });
    await settled();
  }
};

module('Acceptance | Enterprise | replication', function(hooks) {
  setupApplicationTest(hooks);

  hooks.beforeEach(async function() {
    await authPage.login();
    await disableReplication('dr');
    return disableReplication('performance');
  });

  hooks.afterEach(async function() {
    await disableReplication('dr');
    return disableReplication('performance');
  });

  test('replication', async function(assert) {
    const secondaryName = 'firstSecondary';
    const mode = 'blacklist';
    const mountType = 'kv';
    let mountPath;

    await visit('/vault/replication');
    assert.equal(currentURL(), '/vault/replication');

    // enable perf replication
    await click('[data-test-replication-type-select="performance"]');
    await fillIn('[data-test-replication-cluster-mode-select]', 'primary');

    await withFlash(click('[data-test-replication-enable]'));
    await pollCluster(this.owner);

    // add a secondary with a mount filter config
    await click('[data-test-replication-link="secondaries"]');
    await click('[data-test-secondary-add]');
    await fillIn('[data-test-replication-secondary-id]', secondaryName);
    //expand the config
    await click('[data-test-replication-secondary-token-options]');
    await fillIn('[data-test-replication-filter-mount-mode]', mode);
    await click(findAll(`[data-test-mount-filter="${mountType}"]`)[0]);
    mountPath = findAll(`[data-test-mount-filter-path-for-type="${mountType}"]`)[0].textContent.trim();
    await click('[data-test-secondary-add]');

    await pollCluster(this.owner);

    // click into the added secondary's mount filter config
    await click('[data-test-replication-link="secondaries"]');
    await click('[data-test-popup-menu-trigger]');

    await click('[data-test-replication-mount-filter-link]');
    assert.equal(currentURL(), `/vault/replication/performance/secondaries/config/show/${secondaryName}`);
    assert.ok(
      find('[data-test-mount-config-mode]')
        .textContent.trim()
        .toLowerCase()
        .includes(mode),
      'show page renders the correct mode'
    );
    assert
      .dom('[data-test-mount-config-paths]')
      .hasText(mountPath, 'show page renders the correct mount path');
    // click edit

    // delete config
    await click('[data-test-replication-link="edit-mount-config"]');
    await click('[data-test-delete-mount-config] button');
    await withFlash(click('[data-test-confirm-button]'), () => {
      assert.equal(
        findAll('[data-test-flash-message-body]')[0].textContent.trim(),
        `The performance mount filter config for the secondary ${secondaryName} was successfully deleted.`,
        'renders success flash upon deletion'
      );
    });
    assert.equal(
      currentURL(),
      `/vault/replication/performance/secondaries`,
      'redirects to the secondaries page'
    );

    // nav to DR
    await visit('/vault/replication/dr');
    await fillIn('[data-test-replication-cluster-mode-select]', 'secondary');
    assert.ok(
      find('[data-test-replication-enable]:disabled'),
      'dr secondary enable is disabled when other replication modes are on'
    );

    // disable performance replication
    await disableReplication('performance', assert);
    await pollCluster(this.owner);

    // enable dr replication
    await visit('vault/replication/dr');
    await fillIn('[data-test-replication-cluster-mode-select]', 'primary');
    await withFlash(click('button[type="submit"]'));

    await pollCluster(this.owner);
    assert.ok(
      find('[data-test-replication-title]').textContent.includes('Disaster Recovery'),
      'it displays the replication type correctly'
    );
    assert.ok(
      find('[data-test-replication-mode-display]').textContent.includes('primary'),
      'it displays the cluster mode correctly'
    );

    // add dr secondary
    await click('[data-test-replication-link="secondaries"]');
    await click('[data-test-secondary-add]');
    await fillIn('[data-test-replication-secondary-id]', secondaryName);
    await click('[data-test-secondary-add]');
    await pollCluster(this.owner);
    await pollCluster(this.owner);
    await click('[data-test-replication-link="secondaries"]');
    assert
      .dom('[data-test-secondary-name]')
      .hasText(secondaryName, 'it displays the secondary in the list of known secondaries');
  });

  test('disabling dr primary when perf replication is enabled', async function(assert) {
    await visit('vault/replication/performance');
    // enable perf replication
    await fillIn('[data-test-replication-cluster-mode-select]', 'primary');

    await withFlash(click('[data-test-replication-enable]'));
    await pollCluster(this.owner);

    // enable dr replication
    await visit('/vault/replication/dr');
    await fillIn('[data-test-replication-cluster-mode-select]', 'primary');
    await withFlash(click('[data-test-replication-enable]'));
    await pollCluster(this.owner);
    await visit('/vault/replication/dr/manage');
    assert.ok(findAll('[data-test-demote-warning]').length, 'displays the demotion warning');
  });
});
<|endoftext|>


<commit_before>import React, { Component } from "react";
import { connect } from "react-redux";

import {
	addComponent,
	removeComponent,
	watchComponent,
	updateQuery,
	setValue
} from "@appbaseio/reactivecore/lib/actions";
import {
	isEqual,
	debounce,
	checkValueChange,
	checkPropChange
} from "@appbaseio/reactivecore/lib/utils/helper";
import types from "@appbaseio/reactivecore/lib/utils/types";

import Input from "../../styles/Input";
import Title from "../../styles/Title";

class TextField extends Component {
	constructor(props) {
		super(props);

		this.type = "match";
		this.state = {
			currentValue: ""
		};
	}

	componentDidMount() {
		this.props.addComponent(this.props.componentId);
		this.setReact(this.props);

		if (this.props.selectedValue) {
			this.setValue(this.props.selectedValue, true);
		} else if (this.props.defaultSelected) {
			this.setValue(this.props.defaultSelected, true);
		}
	}

	componentWillReceiveProps(nextProps) {
		checkPropChange(
			this.props.react,
			nextProps.react,
			() => this.setReact(nextProps)
		);
		if (this.props.defaultSelected !== nextProps.defaultSelected) {
			this.setValue(nextProps.defaultSelected, true, nextProps);
		} else if (this.state.currentValue !== nextProps.selectedValue) {
			this.setValue(nextProps.selectedValue || "", true, nextProps);
		}
	}

	componentWillUnmount() {
		this.props.removeComponent(this.props.componentId);
	}

	setReact(props) {
		if (props.react) {
			props.watchComponent(props.componentId, props.react);
		}
	}

	defaultQuery = (value) => {
		if (value && value.trim() !== "") {
			return {
				[this.type]: {
					[this.props.dataField]: value
				}
			};
		}
		return null;
	}

	handleTextChange = debounce((value) => {
		this.updateQuery(value, this.props);
	}, 300);

	setValue = (value, isDefaultValue = false, props = this.props) => {
		const performUpdate = () => {
			this.setState({
				currentValue: value
			});
			if (isDefaultValue) {
				this.updateQuery(value, props);
			} else {
				// debounce for handling text while typing
				this.handleTextChange(value);
			}
		}
		checkValueChange(
			props.componentId,
			value,
			props.beforeValueChange,
			props.onValueChange,
			performUpdate
		);
	};

	updateQuery = (value, props) => {
		const query = props.customQuery || this.defaultQuery;
		let callback = null;
		if (props.onQueryChange) {
			callback = props.onQueryChange;
		}
		props.updateQuery(props.componentId, query(value, props), value, props.filterLabel, callback);
		// props.setValue(props.componentId, value);
	}

	render() {
		return (

				{
					this.props.title
						? (<Title>{this.props.title}</Title>)
						: null
				}
				<Input
					type="text"
					placeholder={this.props.placeholder}
					onChange={(e) => this.setValue(e.target.value)}
					value={this.state.currentValue}
				/>

		);
	}
}

TextField.propTypes = {
	addComponent: types.addComponent,
	componentId: types.componentId,
	defaultSelected: types.string,
	react: types.react,
	removeComponent: types.removeComponent,
	dataField: types.dataField,
	title: types.title,
	beforeValueChange: types.beforeValueChange,
	onValueChange: types.onValueChange,
	customQuery: types.customQuery,
	onQueryChange: types.onQueryChange,
	updateQuery: types.updateQuery,
	placeholder: types.placeholder,
	selectedValue: types.selectedValue,
	setValue: types.setValue,
	filterLabel: types.string
};

TextField.defaultProps = {
	placeholder: "Search"
}

const mapStateToProps = (state, props) => ({
	selectedValue: state.selectedValues[props.componentId] && state.selectedValues[props.componentId].value || null
});

const mapDispatchtoProps = (dispatch, props) => ({
	addComponent: component => dispatch(addComponent(component)),
	removeComponent: component => dispatch(removeComponent(component)),
	watchComponent: (component, react) => dispatch(watchComponent(component, react)),
	updateQuery: (component, query, value, filterLabel, onQueryChange) => dispatch(
		updateQuery(component, query, value, filterLabel, onQueryChange)
	),
	setValue: (component, value) => dispatch(setValue(component, value, props.filterLabel, true))
});

export default connect(mapStateToProps, mapDispatchtoProps)(TextField);
<commit_msg>Update updateQuery params in TextField - pass object<commit_after>import React, { Component } from "react";
import { connect } from "react-redux";

import {
	addComponent,
	removeComponent,
	watchComponent,
	updateQuery,
	setValue
} from "@appbaseio/reactivecore/lib/actions";
import {
	isEqual,
	debounce,
	checkValueChange,
	checkPropChange
} from "@appbaseio/reactivecore/lib/utils/helper";
import types from "@appbaseio/reactivecore/lib/utils/types";

import Input from "../../styles/Input";
import Title from "../../styles/Title";

class TextField extends Component {
	constructor(props) {
		super(props);

		this.type = "match";
		this.state = {
			currentValue: ""
		};
	}

	componentDidMount() {
		this.props.addComponent(this.props.componentId);
		this.setReact(this.props);

		if (this.props.selectedValue) {
			this.setValue(this.props.selectedValue, true);
		} else if (this.props.defaultSelected) {
			this.setValue(this.props.defaultSelected, true);
		}
	}

	componentWillReceiveProps(nextProps) {
		checkPropChange(
			this.props.react,
			nextProps.react,
			() => this.setReact(nextProps)
		);
		if (this.props.defaultSelected !== nextProps.defaultSelected) {
			this.setValue(nextProps.defaultSelected, true, nextProps);
		} else if (this.state.currentValue !== nextProps.selectedValue) {
			this.setValue(nextProps.selectedValue || "", true, nextProps);
		}
	}

	componentWillUnmount() {
		this.props.removeComponent(this.props.componentId);
	}

	setReact(props) {
		if (props.react) {
			props.watchComponent(props.componentId, props.react);
		}
	}

	defaultQuery = (value) => {
		if (value && value.trim() !== "") {
			return {
				[this.type]: {
					[this.props.dataField]: value
				}
			};
		}
		return null;
	}

	handleTextChange = debounce((value) => {
		this.updateQuery(value, this.props);
	}, 300);

	setValue = (value, isDefaultValue = false, props = this.props) => {
		const performUpdate = () => {
			this.setState({
				currentValue: value
			});
			if (isDefaultValue) {
				this.updateQuery(value, props);
			} else {
				// debounce for handling text while typing
				this.handleTextChange(value);
			}
		}
		checkValueChange(
			props.componentId,
			value,
			props.beforeValueChange,
			props.onValueChange,
			performUpdate
		);
	};

	updateQuery = (value, props) => {
		const query = props.customQuery || this.defaultQuery;
		let onQueryChange = null;
		if (props.onQueryChange) {
			onQueryChange = props.onQueryChange;
		}
		props.updateQuery({
			componentId: props.componentId,
			query: query(value, props),
			value,
			label: props.filterLabel,
			showFilter: props.showFilter,
			onQueryChange
		});
		// props.setValue(props.componentId, value);
	}

	render() {
		return (

				{
					this.props.title
						? (<Title>{this.props.title}</Title>)
						: null
				}
				<Input
					type="text"
					placeholder={this.props.placeholder}
					onChange={(e) => this.setValue(e.target.value)}
					value={this.state.currentValue}
				/>

		);
	}
}

TextField.propTypes = {
	addComponent: types.addComponent,
	componentId: types.componentId,
	defaultSelected: types.string,
	react: types.react,
	removeComponent: types.removeComponent,
	dataField: types.dataField,
	title: types.title,
	beforeValueChange: types.beforeValueChange,
	onValueChange: types.onValueChange,
	customQuery: types.customQuery,
	onQueryChange: types.onQueryChange,
	updateQuery: types.updateQuery,
	placeholder: types.placeholder,
	selectedValue: types.selectedValue,
	setValue: types.setValue,
	filterLabel: types.string
};

TextField.defaultProps = {
	placeholder: "Search"
}

const mapStateToProps = (state, props) => ({
	selectedValue: state.selectedValues[props.componentId] && state.selectedValues[props.componentId].value || null
});

const mapDispatchtoProps = (dispatch, props) => ({
	addComponent: component => dispatch(addComponent(component)),
	removeComponent: component => dispatch(removeComponent(component)),
	watchComponent: (component, react) => dispatch(watchComponent(component, react)),
	updateQuery: (updateQueryObject) => dispatch(
		updateQuery(updateQueryObject)
	),
	setValue: (component, value) => dispatch(setValue(component, value, props.filterLabel, true))
});

export default connect(mapStateToProps, mapDispatchtoProps)(TextField);
<|endoftext|>


<commit_before>module.exports = function blocklike(func){
  return function(){
    var args = Array.prototype.slice.apply(arguments);
    var callback = args[args.length - 1];
    if (typeof callback === 'function') {
      while (args.length < func.length) {
        args.splice(args.length - 1, 0, undefined);
      }
    }
    return func.apply(this, args);
  };
};
<commit_msg>Fix a invalid variable name<commit_after>module.exports = function callbackEnd(func){
  return function(){
    var args = Array.prototype.slice.apply(arguments);
    var callback = args[args.length - 1];
    if (typeof callback === 'function') {
      while (args.length < func.length) {
        args.splice(args.length - 1, 0, undefined);
      }
    }
    return func.apply(this, args);
  };
};
<|endoftext|>


<commit_before>// Description: This model is responsible determining page numbers to display for both reflowable and fixed layout pubs.
// Rationale: This model exists to abstract and encapsulate the logic for determining which pages numbers should be
//   dispalyed in the viewer. The logic for this is reasonably complex, as there a number of different factors that must be
//   taken into account in various cases. These include: The type of the pub (reflowable or fixed layout), the page progression direction,
//   the reading order of pages, the number of pages displayed on the screen and author preferences
//   for the location of pages (left/right/centre).

Readium.Models.PageNumberDisplayLogic = Backbone.Model.extend({

	// ------------------------------------------------------------------------------------ //
	//  "PUBLIC" METHODS (THE API)                                                          //
	// ------------------------------------------------------------------------------------ //

	initialize: function () {},

    // Description: This method determines the page numbers to display, given a single page number to "go to"
    // Arguments (
    //   gotoPageNumber (integer): The page number to "go to"
    //   twoUp (boolean): Are two pages currently displayed in the reader?
    //   isFixedLayout (boolean): Are the current set of pages fixed layout pages?
    //   pageProgDirection ("rtl" or "ltr): The page progression direction
    //	)
	// REFACTORING CANDIDATE: This might be better named as getPageNumsToDisplay; the "goto" is confusing; also some
	//   deep nesting here that could be refactored for clarity.
	getGotoPageNumsToDisplay: function(gotoPageNumber, twoUp, isFixedLayout, pageProgDirection, firstPageOffset) {

		if (twoUp) {

			// Fixed layout page
			if (isFixedLayout) {

				if (pageProgDirection === "rtl") {

					if (this.displayedPageIsLeft(gotoPageNumber)) {
						return [gotoPageNumber - 1, gotoPageNumber];
					}
					else if (this.displayedPageIsRight(gotoPageNumber)) {
						return [gotoPageNumber, gotoPageNumber + 1];
					}
					else {
						return [gotoPageNumber];
					}
				}
				// Left-to-right page progression
				else {

					if (this.displayedPageIsLeft(gotoPageNumber)) {
						return [gotoPageNumber, gotoPageNumber + 1];
					}
					else if (this.displayedPageIsRight(gotoPageNumber)) {
						return [gotoPageNumber - 1, gotoPageNumber];
					}
					else {
						return [gotoPageNumber];
					}
				}
			}
			// This is a reflowable page
			else {

				if (firstPageOffset) {

					if (gotoPageNumber % 2 === 1) {
						return [gotoPageNumber - 1, gotoPageNumber];
					}
					else {
						return [gotoPageNumber, gotoPageNumber + 1];
					}
				}
				else {
					// in reflowable format, we want this config always:
					// ODD_PAGE |spine| EVEN_PAGE
					if (gotoPageNumber % 2 === 1) {
						return [gotoPageNumber, gotoPageNumber + 1];
					}
					else {
						return [gotoPageNumber - 1, gotoPageNumber];
					}
				}
			}
		}
		else {
			return [gotoPageNumber];
		}
	},

    // Description: Get the pages numbers to display when moving in reverse reading order
    // Arguments (
    //   prevPageNumberToDisplay (integer): The page to move to; this page must be one of the displayed pages
    //   isFixedLayout (boolean): Are the current set of pages fixed layout pages?
    //   pageProgDirection ("rtl" or "ltr): The page progression direction
    //	)
	getPrevPageNumsToDisplay: function (prevPageNumberToDisplay, isFixedLayout, pageProgDirection) {

		// If fixed layout
		if (isFixedLayout) {

			if (pageProgDirection === "rtl") {

				// If the first page is a left page in rtl progression, only one page
				// can be displayed, even in two-up mode
				if (this.displayedPageIsLeft(prevPageNumberToDisplay) &&
					this.displayedPageIsRight(prevPageNumberToDisplay - 1)) {

					return [prevPageNumberToDisplay - 1, prevPageNumberToDisplay];
				}
				else {

					return [prevPageNumberToDisplay];
				}
			}
			// Left-to-right progresion
			else {

				if (this.displayedPageIsRight(prevPageNumberToDisplay) &&
					this.displayedPageIsLeft(prevPageNumberToDisplay - 1)) {

					return [prevPageNumberToDisplay - 1, prevPageNumberToDisplay];
				}
				else {

					return [prevPageNumberToDisplay];
				}
			}
		}
		// A reflowable text
		else {

			return [prevPageNumberToDisplay - 1, prevPageNumberToDisplay];
		}
	},

	// Description: Get the pages to display when moving in reading order
    // Arguments (
    //   nextPageNumberToDisplay (integer): The page to move to; this page must be one of the displayed pages
    //   isFixedLayout (boolean): Are the current set of pages fixed layout pages?
    //   pageProgDirection ("rtl" or "ltr): The page progression direction
    //	)
	getNextPageNumsToDisplay: function (nextPageNumberToDisplay, isFixedLayout, pageProgDirection) {

		// If fixed layout
		if (isFixedLayout) {

			if (pageProgDirection === "rtl") {

				// If the first page is a left page in rtl progression, only one page
				// can be displayed, even in two-up mode
				if (this.displayedPageIsRight(nextPageNumberToDisplay) &&
					this.displayedPageIsLeft(nextPageNumberToDisplay + 1)) {

					return [nextPageNumberToDisplay, nextPageNumberToDisplay + 1];
				}
				else {

					return [nextPageNumberToDisplay];
				}
			}
			else {

				if (this.displayedPageIsLeft(nextPageNumberToDisplay) &&
					this.displayedPageIsRight(nextPageNumberToDisplay + 1)) {

					return [nextPageNumberToDisplay, nextPageNumberToDisplay + 1];
				}
				else {

					return [nextPageNumberToDisplay];
				}
			}
		}
		// Reflowable section
		else {

			return [nextPageNumberToDisplay, nextPageNumberToDisplay + 1];
		}
	},

	// Description: This method determines which page numbers to display when switching
	//   between a single page and side-by-side page views and vice versa.
	// Arguments (
	//   twoUp (boolean): Are two pages currently displayed in the reader?
	//   displayedPageNumbers (array of integers): An array of page numbers that are currently displayed
	//   isFixedLayout (boolean): Are the current set of pages fixed layout pages?
	//   pageProgDirection ("rtl" or "ltr): The page progression direction
	//	)
	// Notes: Authors can specify a fixed layout page as a "center" page, which prevents more than one page
	//   being displayed. This case is not handled yet.
	getPageNumbersForTwoUp: function(twoUp, displayedPageNumbers, pageProgDirection, isFixedLayout, firstPageOffset) {

		var displayed = displayedPageNumbers;
		var twoPagesDisplayed = displayed.length === 2 ? true : false;
		var newPages = [];

		// Two pages are currently displayed; find the single page number to display
		if (twoPagesDisplayed) {

			// Rationale: I think this check is a bit of a hack, for the case in which a set of pages is [0, 1]. Pages are
			//   1-indexed, so the "0" in the 0 index position of the array is not valid.
			if (displayed[0] === 0) {

				newPages[0] = 1;
			}
			else {

				newPages[0] = displayed[0];
			}
		}
		// A single reflowable page is currently displayed; find two pages to display
		else if (!isFixedLayout) {

			if (firstPageOffset) {

				if (displayed[0] % 2 === 1) {

					newPages[0] = displayed[0] - 1;
					newPages[1] = displayed[0];
				}
				else {

					newPages[0] = displayed[0];
					newPages[1] = displayed[0] + 1;
				}
			}
			else {

				if (displayed[0] % 2 === 1) {

					newPages[0] = displayed[0];
					newPages[1] = displayed[0] + 1;
				}
				else {

					newPages[0] = displayed[0] - 1;
					newPages[1] = displayed[0];
				}
			}
		}
		// A single fixed layout page is displayed
		else {

			// page progression is right-to-left
			if (pageProgDirection === "rtl") {

				// and the previous one is right, then display both, otherwise, just display one
				if (this.displayedPageIsLeft(displayed[0])) {

					if (this.displayedPageIsRight(displayed[0] - 1)) {

						newPages[0] = displayed[0] - 1;
						newPages[1] = displayed[0];
					}
					else {

						newPages[0] = displayed[0];
					}
				}
				// if the next page is left, display both, otherwise, just display one
				else if (this.displayedPageIsRight(displayed[0])) {

					if (this.displayedPageIsLeft(displayed[0] + 1)) {

						newPages[0] = displayed[0];
						newPages[1] = displayed[0] + 1;
					}
					else {

						newPages[0] = displayed[0];
					}
				}
				// It is a center page
				else {

					newPages[0] = displayed[0];
				}
			}
			// page progression is left-to-right
			else {

				// If next page is a right page, display both, otherwise just display this one
				if (this.displayedPageIsLeft(displayed[0])) {

					if (this.displayedPageIsRight(displayed[0] + 1)) {

						newPages[0] = displayed[0];
						newPages[1] = displayed[0] + 1;
					}
					else {

						newPages[0] = displayed[0];
					}
				}
				else if (this.displayedPageIsRight(displayed[0])) {

					if (this.displayedPageIsLeft(displayed[0] - 1)) {

						newPages[0] = displayed[0] - 1;
						newPages[1] = displayed[0];
					}
					else {

						newPages[0] = displayed[0];
					}
				}
				// It is a center page
				else {

					newPages[0] = displayed[0];
				}
			}
		}

		return newPages;
	},

	// ------------------------------------------------------------------------------------ //
	//  "PRIVATE" HELPERS                                                                   //
	// ------------------------------------------------------------------------------------ //

	// Description: The `displayedPageIs...` methods determine if a fixed layout page is right, left or center.
	//
	// Rationale: This is not an ideal approach, as we're pulling properties directly out of the dom, rather than
	//   out of our models. The rationale is that as of Readium 0.4.1, the page-spread-* value
	//   is not maintained in the model hierarchy accessible from an ebook object. An alternative
	//   would be to infer the left/right/center value from model attributes on ebook, or other objects in
	//   ebook's object hierarchy. However, this would duplicate the logic that exists elsewhere for determining right/left/center
	//   for a page, which is probably worse than pulling out of the dom. This approach also avoids having to convert
	//   from the page number (based on what is rendered on the screen) to spine index.
	displayedPageIsRight: function (displayedPageNum) {

		return $("#page-" + displayedPageNum).hasClass("right_page") ? true : false;
	},

	displayedPageIsLeft: function (displayedPageNum) {

		return $("#page-" + displayedPageNum).hasClass("left_page") ? true : false;
	},

	displayedPageIsCenter: function (displayedPageNum) {

		return $("#page-" + displayedPageNum).hasClass("center_page") ? true : false;
	}
});<commit_msg>go to page number logic now accounts for all page-spread-* property values<commit_after>// Description: This model is responsible determining page numbers to display for both reflowable and fixed layout pubs.
// Rationale: This model exists to abstract and encapsulate the logic for determining which pages numbers should be
//   dispalyed in the viewer. The logic for this is reasonably complex, as there a number of different factors that must be
//   taken into account in various cases. These include: The type of the pub (reflowable or fixed layout), the page progression direction,
//   the reading order of pages, the number of pages displayed on the screen and author preferences
//   for the location of pages (left/right/centre).

Readium.Models.PageNumberDisplayLogic = Backbone.Model.extend({

	// ------------------------------------------------------------------------------------ //
	//  "PUBLIC" METHODS (THE API)                                                          //
	// ------------------------------------------------------------------------------------ //

	initialize: function () {},

    // Description: This method determines the page numbers to display, given a single page number to "go to"
    // Arguments (
    //   gotoPageNumber (integer): The page number to "go to"
    //   twoUp (boolean): Are two pages currently displayed in the reader?
    //   isFixedLayout (boolean): Are the current set of pages fixed layout pages?
    //   pageProgDirection ("rtl" or "ltr): The page progression direction
    //	)
	// REFACTORING CANDIDATE: This might be better named as getPageNumsToDisplay; the "goto" is confusing; also some
	//   deep nesting here that could be refactored for clarity.
	getGotoPageNumsToDisplay: function(gotoPageNumber, twoUp, isFixedLayout, pageProgDirection, firstPageOffset) {

		if (twoUp) {

			// Fixed layout page
			if (isFixedLayout) {

				if (pageProgDirection === "rtl") {

					if (this.displayedPageIsLeft(gotoPageNumber)) {

						if (this.displayedPageIsRight(gotoPageNumber - 1)) {
							return [gotoPageNumber - 1, gotoPageNumber];
						}
						else {
							return [gotoPageNumber];
						}
					}
					else if (this.displayedPageIsRight(gotoPageNumber)) {

						if (this.displayedPageIsLeft(gotoPageNumber + 1)) {
							return [gotoPageNumber, gotoPageNumber + 1];
						}
						else {
							return [gotoPageNumber];
						}
					}
					// A center page
					else {
						return [gotoPageNumber];
					}
				}
				// Left-to-right page progression
				else {

					if (this.displayedPageIsLeft(gotoPageNumber)) {

						if (this.displayedPageIsRight(gotoPageNumber + 1)) {
							return [gotoPageNumber, gotoPageNumber + 1];
						}
						else {
							return [gotoPageNumber];
						}
					}
					else if (this.displayedPageIsRight(gotoPageNumber)) {

						if (this.displayedPageIsLeft(gotoPageNumber - 1)) {
							return [gotoPageNumber - 1, gotoPageNumber];
						}
						else {
							return [gotoPageNumber];
						}
					}
					// A center page
					else {
						return [gotoPageNumber];
					}
				}
			}
			// This is a reflowable page
			else {

				if (firstPageOffset) {

					if (gotoPageNumber % 2 === 1) {
						return [gotoPageNumber - 1, gotoPageNumber];
					}
					else {
						return [gotoPageNumber, gotoPageNumber + 1];
					}
				}
				else {
					// in reflowable format, we want this config always:
					// ODD_PAGE |spine| EVEN_PAGE
					if (gotoPageNumber % 2 === 1) {
						return [gotoPageNumber, gotoPageNumber + 1];
					}
					else {
						return [gotoPageNumber - 1, gotoPageNumber];
					}
				}
			}
		}
		else {
			return [gotoPageNumber];
		}
	},

    // Description: Get the pages numbers to display when moving in reverse reading order
    // Arguments (
    //   prevPageNumberToDisplay (integer): The page to move to; this page must be one of the displayed pages
    //   isFixedLayout (boolean): Are the current set of pages fixed layout pages?
    //   pageProgDirection ("rtl" or "ltr): The page progression direction
    //	)
	getPrevPageNumsToDisplay: function (prevPageNumberToDisplay, isFixedLayout, pageProgDirection) {

		// If fixed layout
		if (isFixedLayout) {

			if (pageProgDirection === "rtl") {

				// If the first page is a left page in rtl progression, only one page
				// can be displayed, even in two-up mode
				if (this.displayedPageIsLeft(prevPageNumberToDisplay) &&
					this.displayedPageIsRight(prevPageNumberToDisplay - 1)) {

					return [prevPageNumberToDisplay - 1, prevPageNumberToDisplay];
				}
				else {

					return [prevPageNumberToDisplay];
				}
			}
			// Left-to-right progresion
			else {

				if (this.displayedPageIsRight(prevPageNumberToDisplay) &&
					this.displayedPageIsLeft(prevPageNumberToDisplay - 1)) {

					return [prevPageNumberToDisplay - 1, prevPageNumberToDisplay];
				}
				else {

					return [prevPageNumberToDisplay];
				}
			}
		}
		// A reflowable text
		else {

			return [prevPageNumberToDisplay - 1, prevPageNumberToDisplay];
		}
	},

	// Description: Get the pages to display when moving in reading order
    // Arguments (
    //   nextPageNumberToDisplay (integer): The page to move to; this page must be one of the displayed pages
    //   isFixedLayout (boolean): Are the current set of pages fixed layout pages?
    //   pageProgDirection ("rtl" or "ltr): The page progression direction
    //	)
	getNextPageNumsToDisplay: function (nextPageNumberToDisplay, isFixedLayout, pageProgDirection) {

		// If fixed layout
		if (isFixedLayout) {

			if (pageProgDirection === "rtl") {

				// If the first page is a left page in rtl progression, only one page
				// can be displayed, even in two-up mode
				if (this.displayedPageIsRight(nextPageNumberToDisplay) &&
					this.displayedPageIsLeft(nextPageNumberToDisplay + 1)) {

					return [nextPageNumberToDisplay, nextPageNumberToDisplay + 1];
				}
				else {

					return [nextPageNumberToDisplay];
				}
			}
			else {

				if (this.displayedPageIsLeft(nextPageNumberToDisplay) &&
					this.displayedPageIsRight(nextPageNumberToDisplay + 1)) {

					return [nextPageNumberToDisplay, nextPageNumberToDisplay + 1];
				}
				else {

					return [nextPageNumberToDisplay];
				}
			}
		}
		// Reflowable section
		else {

			return [nextPageNumberToDisplay, nextPageNumberToDisplay + 1];
		}
	},

	// Description: This method determines which page numbers to display when switching
	//   between a single page and side-by-side page views and vice versa.
	// Arguments (
	//   twoUp (boolean): Are two pages currently displayed in the reader?
	//   displayedPageNumbers (array of integers): An array of page numbers that are currently displayed
	//   isFixedLayout (boolean): Are the current set of pages fixed layout pages?
	//   pageProgDirection ("rtl" or "ltr): The page progression direction
	//	)
	// Notes: Authors can specify a fixed layout page as a "center" page, which prevents more than one page
	//   being displayed. This case is not handled yet.
	getPageNumbersForTwoUp: function(twoUp, displayedPageNumbers, pageProgDirection, isFixedLayout, firstPageOffset) {

		var displayed = displayedPageNumbers;
		var twoPagesDisplayed = displayed.length === 2 ? true : false;
		var newPages = [];

		// Two pages are currently displayed; find the single page number to display
		if (twoPagesDisplayed) {

			// Rationale: I think this check is a bit of a hack, for the case in which a set of pages is [0, 1]. Pages are
			//   1-indexed, so the "0" in the 0 index position of the array is not valid.
			if (displayed[0] === 0) {

				newPages[0] = 1;
			}
			else {

				newPages[0] = displayed[0];
			}
		}
		// A single reflowable page is currently displayed; find two pages to display
		else if (!isFixedLayout) {

			if (firstPageOffset) {

				if (displayed[0] % 2 === 1) {

					newPages[0] = displayed[0] - 1;
					newPages[1] = displayed[0];
				}
				else {

					newPages[0] = displayed[0];
					newPages[1] = displayed[0] + 1;
				}
			}
			else {

				if (displayed[0] % 2 === 1) {

					newPages[0] = displayed[0];
					newPages[1] = displayed[0] + 1;
				}
				else {

					newPages[0] = displayed[0] - 1;
					newPages[1] = displayed[0];
				}
			}
		}
		// A single fixed layout page is displayed
		else {

			// page progression is right-to-left
			if (pageProgDirection === "rtl") {

				// and the previous one is right, then display both, otherwise, just display one
				if (this.displayedPageIsLeft(displayed[0])) {

					if (this.displayedPageIsRight(displayed[0] - 1)) {

						newPages[0] = displayed[0] - 1;
						newPages[1] = displayed[0];
					}
					else {

						newPages[0] = displayed[0];
					}
				}
				// if the next page is left, display both, otherwise, just display one
				else if (this.displayedPageIsRight(displayed[0])) {

					if (this.displayedPageIsLeft(displayed[0] + 1)) {

						newPages[0] = displayed[0];
						newPages[1] = displayed[0] + 1;
					}
					else {

						newPages[0] = displayed[0];
					}
				}
				// It is a center page
				else {

					newPages[0] = displayed[0];
				}
			}
			// page progression is left-to-right
			else {

				// If next page is a right page, display both, otherwise just display this one
				if (this.displayedPageIsLeft(displayed[0])) {

					if (this.displayedPageIsRight(displayed[0] + 1)) {

						newPages[0] = displayed[0];
						newPages[1] = displayed[0] + 1;
					}
					else {

						newPages[0] = displayed[0];
					}
				}
				else if (this.displayedPageIsRight(displayed[0])) {

					if (this.displayedPageIsLeft(displayed[0] - 1)) {

						newPages[0] = displayed[0] - 1;
						newPages[1] = displayed[0];
					}
					else {

						newPages[0] = displayed[0];
					}
				}
				// It is a center page
				else {

					newPages[0] = displayed[0];
				}
			}
		}

		return newPages;
	},

	// ------------------------------------------------------------------------------------ //
	//  "PRIVATE" HELPERS                                                                   //
	// ------------------------------------------------------------------------------------ //

	// Description: The `displayedPageIs...` methods determine if a fixed layout page is right, left or center.
	//
	// Rationale: This is not an ideal approach, as we're pulling properties directly out of the dom, rather than
	//   out of our models. The rationale is that as of Readium 0.4.1, the page-spread-* value
	//   is not maintained in the model hierarchy accessible from an ebook object. An alternative
	//   would be to infer the left/right/center value from model attributes on ebook, or other objects in
	//   ebook's object hierarchy. However, this would duplicate the logic that exists elsewhere for determining right/left/center
	//   for a page, which is probably worse than pulling out of the dom. This approach also avoids having to convert
	//   from the page number (based on what is rendered on the screen) to spine index.
	displayedPageIsRight: function (displayedPageNum) {

		return $("#page-" + displayedPageNum).hasClass("right_page") ? true : false;
	},

	displayedPageIsLeft: function (displayedPageNum) {

		return $("#page-" + displayedPageNum).hasClass("left_page") ? true : false;
	},

	displayedPageIsCenter: function (displayedPageNum) {

		return $("#page-" + displayedPageNum).hasClass("center_page") ? true : false;
	}
});<|endoftext|>


<commit_before>'use strict';

var Surface = require('./Surface');
var TextProperty = require('./TextPropertyComponent');

/**
  Editor for a text property (annotated string). Needs to be
  instantiated inside a {@link ui/Controller} context.

  @class
  @component
  @extends ui/Surface

  @prop {String} name unique editor name
  @prop {String[]} path path to a text property
  @prop {ui/SurfaceCommand[]} commands array of command classes to be available

  @example

  Create a `TextPropertyEditor` for the `name` property of an author object. Allow emphasis annotations.

  ```js
  $$(TextPropertyEditor, {
    name: 'authorNameEditor',
    path: ['author_1', 'name'],
    commands: [EmphasisCommand]
  })
  ```
*/

function TextPropertyEditor() {
  Surface.apply(this, arguments);
}

TextPropertyEditor.Prototype = function() {

  this.render = function($$) {
    var el = Surface.prototype.render.call(this);
    el.addClass("sc-text-property-editor");
    el.append(
      $$(TextProperty, {
        tagName: "div",
        path: this.props.path
      })
    );
    if (this.isEditable()) {
      el.attr('contenteditable', true);
    }
    return el;
  };

  /**
    Selects all text
  */
  this.selectAll = function() {
    var doc = this.getDocument();
    var path = this.props.path;
    var text = doc.get(path);
    var sel = doc.createSelection({
      type: 'property',
      path: path,
      startOffset: 0,
      endOffset: text.length
    });
    this.setSelection(sel);
  };

};

Surface.extend(TextPropertyEditor);

module.exports = TextPropertyEditor;
<commit_msg>Fix in TextPropertyEditor.<commit_after>'use strict';

var Surface = require('./Surface');
var TextProperty = require('./TextPropertyComponent');

/**
  Editor for a text property (annotated string). Needs to be
  instantiated inside a {@link ui/Controller} context.

  @class
  @component
  @extends ui/Surface

  @prop {String} name unique editor name
  @prop {String[]} path path to a text property
  @prop {ui/SurfaceCommand[]} commands array of command classes to be available

  @example

  Create a `TextPropertyEditor` for the `name` property of an author object. Allow emphasis annotations.

  ```js
  $$(TextPropertyEditor, {
    name: 'authorNameEditor',
    path: ['author_1', 'name'],
    commands: [EmphasisCommand]
  })
  ```
*/

function TextPropertyEditor() {
  Surface.apply(this, arguments);
}

TextPropertyEditor.Prototype = function() {

  this.render = function($$) {
    var el = Surface.prototype.render.apply(this, arguments);
    el.addClass("sc-text-property-editor");
    el.append(
      $$(TextProperty, {
        tagName: "div",
        path: this.props.path
      })
    );
    if (this.isEditable()) {
      el.attr('contenteditable', true);
    }
    return el;
  };

  /**
    Selects all text
  */
  this.selectAll = function() {
    var doc = this.getDocument();
    var path = this.props.path;
    var text = doc.get(path);
    var sel = doc.createSelection({
      type: 'property',
      path: path,
      startOffset: 0,
      endOffset: text.length
    });
    this.setSelection(sel);
  };

};

Surface.extend(TextPropertyEditor);

module.exports = TextPropertyEditor;
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { connect } from 'react-redux';

class Temperature extends Component {
  constructor(props){
    super(props);
    this.state = {
      temperature: 15
    }
  }
    render() {
    const { storeData } = this.context;
    return (

        <lable>Temperature: {this.props.todos.temperature}</lable>

        <input
          type="range" min="10" max="35" step="1"
          onChange={(e=>{this.props.onInputChange(e)}).bind(this)}/>

    )
  }
}

const mapStateToProps = (state) => {
  return {
    todos: state
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    onInputChange: (e) => {
      dispatch({type: 'TEMP_CHANGE', temperature: e.target.value})
    }
  }
}

const TemperatureC = connect(mapStateToProps, mapDispatchToProps)(Temperature)

export default TemperatureC;<commit_msg>temp edit<commit_after>import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { connect } from 'react-redux';

class Temperature extends Component {
  constructor(props){
    super(props);
    this.state = {
      temperature: 15
    }
  }
    render() {
    const { storeData } = this.context;
    return (

        <lable>Temperature: {this.props.todos.temperature}</lable>

        <input
          type="range" min="10" max="35" step="1"
          onChange={(e=>{this.props.onInputChange(e)}).bind(this)}/>

    )
  }
}

const mapStateToProps = (state) => {
  return {
    todos: state
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    onInputChange: (e) => {
      dispatch({type: 'TEMP_CHANGE', temperature: e.target.value})
    }
  }
}

const TemperatureC = connect(mapStateToProps, mapDispatchToProps)(Temperature)

export default TemperatureC;
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import Trait from './Trait';

const maxDots = 10;
const rankDots = [7, 5, 3];

class Attributes extends Component {
  static propTypes = {
    attributes: PropTypes.object.isRequired,
    setRank: PropTypes.func.isRequired
  };

  handleRankChange = (trait, dotsFromRank) => {
    this.props.setRank('attributes', trait, dotsFromRank);
  };

  render() {
    const attributes = this.props.attributes;

    return (

Attributes

        <Trait
          name="physical"
          maxDots={maxDots}
          rankDots={rankDots}
          traitState={attributes.physical}
          onRankChange={this.handleRankChange}
        />
        <Trait
          name="social"
          maxDots={maxDots}
          rankDots={rankDots}
          traitState={attributes.social}
          onRankChange={this.handleRankChange}
        />
        <Trait
          name="mental"
          maxDots={maxDots}
          rankDots={rankDots}
          traitState={attributes.mental}
          onRankChange={this.handleRankChange}
        />
        <Link to="/skills">Skills</Link>

    );
  }
}

export default Attributes;
<commit_msg>Refactor Attributes to render array of trait names<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import Trait from './Trait';

const maxDots = 10;
const rankDots = [7, 5, 3];
const traitNames = ['physical', 'social', 'mental'];

class Attributes extends Component {
  static propTypes = {
    attributes: PropTypes.object.isRequired,
    setRank: PropTypes.func.isRequired
  };

  handleRankChange = (trait, dotsFromRank) => {
    this.props.setRank('attributes', trait, dotsFromRank);
  };

  render() {
    const { attributes } = this.props;

    const traits = traitNames.map(name => (
      <Trait
        key={name}
        name={name}
        maxDots={maxDots}
        rankDots={rankDots}
        traitState={attributes[name]}
        onRankChange={this.handleRankChange}
      />
    ));

    return (

Attributes

        {traits}
        <Link to="/skills">Skills</Link>

    );
  }
}

export default Attributes;
<|endoftext|>


<commit_before>var webpack = require('webpack');
var path = require('path');
module.exports = {
  entry: [
    'webpack-dev-server/client?http://localhost:3000',
    'webpack/hot/only-dev-server',
    './index.jsx'
  ],
  output: {
    path: path.join(__dirname, 'public/ui'),
    filename: "index.js"
  },
  module: {
    loaders: [
      {
        test: /\.(jsx|es6)$/,
        loaders: [
          'react-hot',
          'babel-loader?babelrc=false,presets[]=react,presets[]=es2015,cacheDirectory',
          'eslint-loader'
        ],
        exclude: /node_modules/
      },
      { test: /\.json$/, loader: 'json' },
      { test: /\.css$/, exclude: /\.useable\.css$/, loader: "style!css" },
      { test: /\.less$/, loader: "style!css!less" }
    ]
  },
  resolve: {
    extensions: ['', '.js', '.es6', '.jsx']
  },
  devtool: 'source-map',
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ],
  eslint:{
    configFile: "./.eslintrc"
  }
};
<commit_msg>Removed eslint-loader<commit_after>var webpack = require('webpack');
var path = require('path');
module.exports = {
  entry: [
    'webpack-dev-server/client?http://localhost:3000',
    'webpack/hot/only-dev-server',
    './index.jsx'
  ],
  output: {
    path: path.join(__dirname, 'public/ui'),
    filename: "index.js"
  },
  module: {
    loaders: [
      {
        test: /\.(jsx|es6)$/,
        loaders: [
          'react-hot',
          'babel-loader?babelrc=false,presets[]=react,presets[]=es2015,cacheDirectory'
        ],
        exclude: /node_modules/
      },
      { test: /\.json$/, loader: 'json' },
      { test: /\.css$/, exclude: /\.useable\.css$/, loader: "style!css" },
      { test: /\.less$/, loader: "style!css!less" }
    ]
  },
  resolve: {
    extensions: ['', '.js', '.es6', '.jsx']
  },
  devtool: 'source-map',
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ],
  eslint:{
    configFile: "./.eslintrc"
  }
};
<|endoftext|>