<commit_before>'use strict';

const Dock = require('../../lib/bases/Dock');
const Sparkles = require('sparkles');
const test = require('tape-plus');
const group = require('tape-plus').group;

const config = {
    port: 8080,
    parser: {
        subtagSeparator: '|',
        dataSeparator: ','
    },
    encoder: {
        subtagSeparator: '|',
        dataSeparator: ','
    },
    maxMessageLength: 100,
    events: true
};
const dispatcher = {
    tags: {
        'tag1': {}
    },
    dispatch: (data, callback) => {}
};

group('dock.id', (test) => {
    const dock = new Dock('test', 'test');

    test('sets dock Id', (t) => {
        dock.id = 'test';
        t.equal(dock.id, 'test');
    });

    test('gets dock Id', (t) => {
        dock.id = 'example';
        t.equal(dock.id, 'example');
    });
});

group('dock.name', (test) => {
    const dock = new Dock('test', 'test');

    test('gets dock name', (t) => {
        t.equal(dock.name, 'test');
    });
});

group('dock.type', (test) => {
    const dock = new Dock('test', 'test');

    test('gets dock type', (t) => {
        t.equal(dock.type, 'dock');
    });
});

group('dock.protocol', (test) => {
    const dock = new Dock('test', 'test');

    test('gets dock protocol', (t) => {
        t.equal(dock.protocol, 'test');
    });
});

group('dock.port', (test) => {
    const dock = new Dock('test', 'test');

    test('gets dock port', (t) => {
        dock.config = config;
        t.equal(dock.port, 8080);
    });
});

group('dock.config', (test) => {
    const dock = new Dock('test', 'test');

    test('sets dock config', (t) => {
        dock.config = config;
        t.deepEqual(dock._config, config);
    });

    test('gets dock config', (t) => {
        t.deepEqual(dock.config, config);
    });
});

group('dock.dispatcher', (test) => {
    const dock = new Dock('test', 'test');

    test('sets dispatcher instance', (t) => {
        dock.dispatcher = dispatcher;
        t.deepEqual(dock._dispatcher, dispatcher);
    });
});

group('dock.validate()', (test) => {
    const dock = new Dock('test', 'test');

    dock.dispatcher = dispatcher;
    dock.config = config;

    test('validates messages', (t) => {
        const result = dock.validate('tag1|subtag1|02,56,58,8|subtag2|sds,sd,wtr,ghd');
        const expectedResult = {
            tag: 'tag1',
            message: ['subtag1', '02,56,58,8', 'subtag2', 'sds,sd,wtr,ghd']
        };

        t.deepEqual(result, expectedResult);
    });

    test('checks message length', (t) => {
        const result = dock.validate(
            'tag1|subtag1|02,56,58,8,69,45,78,65,125,69,898,98|subtag2|sds,sd,wtr,ghd,sd,rt,frt,uty,adf,wfg,dgs,sd'
        );

        t.equal(result, false);
    });

    test('checks message tag', (t) => {
        const result = dock.validate('tag2|subtag1|02,56,58,8|subtag2|sds,sd,wtr,ghd');

        t.equal(result, false);
    });

    test('checks message format', (t) => {
        const result = dock.validate('tag1|subtag1|02;56;58;8|subtag2|sds;sd;wtr;ghd');

        t.equal(result, false);
    });
});

group('dock.parse()', (test) => {
    const dock = new Dock('test', 'test');

    dock.dispatcher = dispatcher;
    dock.config = config;

    test('parses messages', (t) => {
        const data = {
            tag: 'tag1',
            message: ['subtag1', '02,56,58,8', 'subtag2', 'sds,sd,wtr,ghd']
        };
        const meta = {
            test: 'test'
        };
        const result = dock.parse(data, meta);
        const expectedResult = {
            tag: 'tag1',
            meta: meta,
            data: {
                'subtag1': [
                    '02', '56', '58', '8'
                ],
                'subtag2': ['sds', 'sd', 'wtr', 'ghd']
            }
        };

        t.deepEqual(result, expectedResult);
    });

    test('checks message body', (t) => {
        const data = {
            tag: 'tag1',
            message: '|subtag1|02,56,58,8|subtag2|sds,sd,wtr,ghd'
        };
        const meta = {};
        const result = dock.parse(data, meta);

        t.equal(result, false);
    });
});

group('dock.process()', (test) => {
    const dock = new Dock('test', 'test');
    const events = Sparkles('test');

    const message = 'tag1|subtag1|02,56,58,8|subtag2|sds,sd,wtr,ghd';
    const meta = {};
    const callback = () => {};

    dock.id = 'test';
    dock.config = config;

    test('sends messages to dispatcher', (t) => {
        let failed = true;
        const eventCallback = (data) => {
            failed = false;

            t.pass('Ok');
        };

        events.on('dispatcherExecuted', eventCallback.bind(this));
        dock.dispatcher = dispatcher;
        dock._dispatcher.dispatch = (data, callback) => {
            events.emit('dispatcherExecuted', {});
        };
        dock.process(message, meta, callback);

        setTimeout(() => {
            if (failed) {
                t.fail('dispatcher.dispatch() was never called');
            }
        }, 5);
    });

    test('sets dock Id', (t) => {
        const eventCallback = (data) => {
            failed = false;

            t.pass('Ok');
        };
        let failed = true;

        events.on('setDockId', eventCallback.bind(this));
        dock.dispatcher = dispatcher;
        dock._dispatcher.dispatch = (data, callback) => {
            if (data.meta.dock) events.emit('setDockId', {});
        };
        dock.process(message, meta, callback);

        setTimeout(() => {
            if (failed) {
                t.fail('Dock id was never set');
            }
        }, 5);
    });

    test('sets message timestamp', (t) => {
        const eventCallback = (data) => {
            failed = false;

            t.pass('Ok');
        };
        let failed = true;

        events.on('setTimestamp', eventCallback.bind(this));
        dock.dispatcher = dispatcher;
        dock._dispatcher.dispatch = (data, callback) => {
            if (data.meta.timestamp) events.emit('setTimestamp', {});
        };
        dock.process(message, meta, callback);

        setTimeout(() => {
            if (failed) {
                t.fail('Timestamp was never set');
            }
        }, 5);
    });

    test('uses message.toString()', (t) => {
        const customMessage = {
            toString: () => 'tag1|subtag1|02,56,58,8|subtag2|sds,sd,wtr,ghd'
        };
        const eventCallback = (data) => {
            failed = false;

            t.pass('Ok');
        };
        let failed = true;

        events.on('dispatcherExecuted', eventCallback.bind(this));
        dock.dispatcher = dispatcher;
        dock._dispatcher.dispatch = (data, callback) => {
            events.emit('dispatcherExecuted', {});
        };
        dock.process(customMessage, meta, callback);

        setTimeout(() => {
            if (failed) {
                t.fail('dispatcher.dispatch() was never called');
            }
        }, 5);
    });

    test('fails with unrecognized message types', (t) => {
        const customMessage = {
            message: {}
        };
        const returnValue = dock.process(customMessage, meta, callback);

        t.equal(returnValue, false);
    });

    test('fails when there is no dispatcher reference', (t) => {
        let valid = false;

        dock._dispatcher = undefined;
        dock.logger.error = () => {
            valid = true;
        };

        dock.process(message, meta, callback);
        t.equal(valid, true);
    });

    test('fails when the parser returns no data', (t) => {
        const eventCallback = (data) => {
            passed = false;

            t.fail('dispatcher.dispatch() should not have been called');
        };
        let passed = true;

        dock.parse = () => {};

        events.on('dispatcherExecuted', eventCallback.bind(this));
        dock.dispatcher = dispatcher;
        dock._dispatcher.dispatch = (data, callback) => {
            events.emit('dispatcherExecuted', {});
        };
        dock.process(message, meta, callback);

        setTimeout(() => {
            if (passed) {
                t.pass('Ok');
            }
        }, 5);
    });
});

group('dock.encode()', (test) => {
    const dock = new Dock('test', 'test');

    dock.id = 'test';
    dock.config = config;
    dock.dispatcher = dispatcher;

    test('encodes array messages', (t) => {
        const result = dock.encode({
            message: ['abc', 'def', 'ghi']
        });

        t.equal(result, 'abc,def,ghi');
    });

    test('encodes object messages', (t) => {
        const result = dock.encode({
            message: {
                subtag1: [
                    'abc', 'def', 'ghi'
                ],
                subtag2: ['jkl', 'mno', 'pqr'],
                subtag3: {
                    toString: () => {
                        return 'stu,vwx';
                    }
                }
            }
        });

        t.equal(result, '|subtag1|abc,def,ghi|subtag2|jkl,mno,pqr|subtag3|stu,vwx');
    });

    test('encodes object messages with string values', (t) => {
        const result = dock.encode({
            message: {
                subtag1: 'abc',
                subtag2: 'jkl'
            }
        });

        t.equal(result, '|subtag1|abc|subtag2|jkl');
    });

    test('encodes messages with toString() method', (t) => {
        const message = {
            toString: () => 'Test'
        };

        const result = dock.encode({message: message});

        t.equal(result, 'Test');
    });

    test('returns string messages', (t) => {
        const result = dock.encode({message: 'Test'});

        t.equal(result, 'Test');
    });

    test('handles unknown message types', (t) => {
        const result = dock.encode({
            message: () => 'Test'
        });

        t.equal(result, false);
    });
});

group('dock.reply()', (test) => {
    test('sends a reply', (t, next) => {
        const dock = new Dock('test', 'test');
        let valid = false;

        dock.config = config;
        dock.send = () => {
            valid = true;
        };

        dock.reply({
            meta: {
                dock: dock._id
            },
            message: 'test'
        });

        setTimeout(() => {
            t.equal(valid, true);

            next();
        }, 5);
    });

    test('fails because there is no message to send', (t, next) => {
        const dock = new Dock('test', 'test');
        let valid = false;

        dock.config = config;
        dock.send = () => {};
        dock.logger.error = () => {
            valid = true;
        };

        dock.reply({
            meta: {
                dock: dock._id
            },
            message: {}
        });

        setTimeout(() => {
            t.equal(valid, true);

            next();
        }, 5);
    });

    test('fails with invalid dock reference', (t, next) => {
        const dock = new Dock('test', 'test');
        let valid = false;

        dock.config = config;
        dock.logger.error = () => {
            valid = true;
        };

        dock.reply({
            meta: {
                dock: 'test'
            },
            message: {}
        });

        setTimeout(() => {
            t.equal(valid, true);

            next();
        }, 5);
    });
});

group('dock.on()', (test) => {
    test('registers an event handler', (t, next) => {
        const dock = new Dock('test', 'test');
        let failed = true;

        dock.config = config;

        dock.on('test', () => {
            failed = false;
        });
        dock._emitEvent('test', {});

        setTimeout(() => {
            if (failed) t.fail('Event was not handled');
            else t.pass('Ok');

            next();
        }, 5);
    });
});

group('dock._checkConfig()', (test) => {
    const dock = new Dock('test', 'test');

    dock.id = 'test';
    dock.dispatcher = dispatcher;

    test('checks config', (t, next) => {
        let fails = false;

        dock.config = config;
        dock.logger.error = () => {
            fails = true;
        };

        dock._checkConfig(config);

        setTimeout(() => {
            if (fails) t.fail('Config threw validation errors');
            else t.pass('Ok');

            next();
        }, 5);
    });

    test('catches validation errors', (t, next) => {
        const invalidConfig = {
            parser: {
                subtagSeparator: '|',
                dataSeparator: ','
            },
            encoder: {
                subtagSeparator: '|',
                dataSeparator: ','
            },
            maxMessageLength: 100,
            events: true
        };
        let valid = false;

        dock.logger.error = () => {
            valid = true;
        };

        dock._checkConfig(invalidConfig);

        setTimeout(() => {
            t.equal(valid, true);

            next();
        }, 5);
    });
});

group('dock._emitEvent', (test) => {
    const dock = new Dock('test', 'test');
    let failed = true;

    test('emits events', (t, next) => {
        dock.config = config;

        dock.on('test', () => {
            failed = false;
        });
        dock._emitEvent('test', {});

        setTimeout(() => {
            if (failed) t.fail('Event was not emitted');
            else t.pass('Ok');

            next();
        }, 5);
    });
});<commit_msg>Cleanup<commit_after>'use strict';

const Dock = require('../../lib/bases/Dock');
const test = require('tape-plus');
const group = require('tape-plus').group;

const config = {
    port: 8080,
    parser: {
        subtagSeparator: '|',
        dataSeparator: ','
    },
    encoder: {
        subtagSeparator: '|',
        dataSeparator: ','
    },
    maxMessageLength: 100,
    events: true
};
const dispatcher = {
    tags: {
        'tag1': {}
    },
    dispatch: (data, callback) => {}
};

group('dock.id', (test) => {
    const dock = new Dock('test', 'test');

    test('sets dock Id', (t) => {
        dock.id = 'test';
        t.equal(dock.id, 'test');
    });

    test('gets dock Id', (t) => {
        dock.id = 'example';
        t.equal(dock.id, 'example');
    });
});

group('dock.name', (test) => {
    const dock = new Dock('test', 'test');

    test('gets dock name', (t) => {
        t.equal(dock.name, 'test');
    });
});

group('dock.type', (test) => {
    const dock = new Dock('test', 'test');

    test('gets dock type', (t) => {
        t.equal(dock.type, 'dock');
    });
});

group('dock.protocol', (test) => {
    const dock = new Dock('test', 'test');

    test('gets dock protocol', (t) => {
        t.equal(dock.protocol, 'test');
    });
});

group('dock.port', (test) => {
    const dock = new Dock('test', 'test');

    test('gets dock port', (t) => {
        dock.config = config;
        t.equal(dock.port, 8080);
    });
});

group('dock.config', (test) => {
    const dock = new Dock('test', 'test');

    test('sets dock config', (t) => {
        dock.config = config;
        t.deepEqual(dock._config, config);
    });

    test('gets dock config', (t) => {
        t.deepEqual(dock.config, config);
    });
});

group('dock.dispatcher', (test) => {
    const dock = new Dock('test', 'test');

    test('sets dispatcher instance', (t) => {
        dock.dispatcher = dispatcher;
        t.deepEqual(dock._dispatcher, dispatcher);
    });
});

group('dock.validate()', (test) => {
    const dock = new Dock('test', 'test');

    dock.dispatcher = dispatcher;
    dock.config = config;

    test('validates messages', (t) => {
        const result = dock.validate('tag1|subtag1|02,56,58,8|subtag2|sds,sd,wtr,ghd');
        const expectedResult = {
            tag: 'tag1',
            message: ['subtag1', '02,56,58,8', 'subtag2', 'sds,sd,wtr,ghd']
        };

        t.deepEqual(result, expectedResult);
    });

    test('checks message length', (t) => {
        const result = dock.validate(
            'tag1|subtag1|02,56,58,8,69,45,78,65,125,69,898,98|subtag2|sds,sd,wtr,ghd,sd,rt,frt,uty,adf,wfg,dgs,sd'
        );

        t.equal(result, false);
    });

    test('checks message tag', (t) => {
        const result = dock.validate('tag2|subtag1|02,56,58,8|subtag2|sds,sd,wtr,ghd');

        t.equal(result, false);
    });

    test('checks message format', (t) => {
        const result = dock.validate('tag1|subtag1|02;56;58;8|subtag2|sds;sd;wtr;ghd');

        t.equal(result, false);
    });
});

group('dock.parse()', (test) => {
    const dock = new Dock('test', 'test');

    dock.dispatcher = dispatcher;
    dock.config = config;

    test('parses messages', (t) => {
        const data = {
            tag: 'tag1',
            message: ['subtag1', '02,56,58,8', 'subtag2', 'sds,sd,wtr,ghd']
        };
        const meta = {
            test: 'test'
        };
        const result = dock.parse(data, meta);
        const expectedResult = {
            tag: 'tag1',
            meta: meta,
            data: {
                'subtag1': [
                    '02', '56', '58', '8'
                ],
                'subtag2': ['sds', 'sd', 'wtr', 'ghd']
            }
        };

        t.deepEqual(result, expectedResult);
    });

    test('checks message body', (t) => {
        const data = {
            tag: 'tag1',
            message: '|subtag1|02,56,58,8|subtag2|sds,sd,wtr,ghd'
        };
        const meta = {};
        const result = dock.parse(data, meta);

        t.equal(result, false);
    });
});

group('dock.process()', (test) => {
    const dock = new Dock('test', 'test');
    const message = 'tag1|subtag1|02,56,58,8|subtag2|sds,sd,wtr,ghd';
    const meta = {};
    const callback = () => {};

    dock.id = 'test';
    dock.config = config;

    test('sends messages to dispatcher', (t) => {
        let failed = true;
        const eventCallback = (data) => {
            failed = false;

            t.pass('Ok');
        };

        dock.on('dispatcherExecuted', eventCallback.bind(this));
        dock.dispatcher = dispatcher;
        dock._dispatcher.dispatch = (data, callback) => {
            dock._emitEvent('dispatcherExecuted', {});
        };
        dock.process(message, meta, callback);

        setTimeout(() => {
            if (failed) {
                t.fail('dispatcher.dispatch() was never called');
            }
        }, 5);
    });

    test('sets dock Id', (t) => {
        const eventCallback = (data) => {
            failed = false;

            t.pass('Ok');
        };
        let failed = true;

        dock.on('setDockId', eventCallback.bind(this));
        dock.dispatcher = dispatcher;
        dock._dispatcher.dispatch = (data, callback) => {
            if (data.meta.dock) dock._emitEvent('setDockId', {});
        };
        dock.process(message, meta, callback);

        setTimeout(() => {
            if (failed) {
                t.fail('Dock id was never set');
            }
        }, 5);
    });

    test('sets message timestamp', (t) => {
        const eventCallback = (data) => {
            failed = false;

            t.pass('Ok');
        };
        let failed = true;

        dock.on('setTimestamp', eventCallback.bind(this));
        dock.dispatcher = dispatcher;
        dock._dispatcher.dispatch = (data, callback) => {
            if (data.meta.timestamp) dock._emitEvent('setTimestamp', {});
        };
        dock.process(message, meta, callback);

        setTimeout(() => {
            if (failed) {
                t.fail('Timestamp was never set');
            }
        }, 5);
    });

    test('uses message.toString()', (t) => {
        const customMessage = {
            toString: () => 'tag1|subtag1|02,56,58,8|subtag2|sds,sd,wtr,ghd'
        };
        const eventCallback = (data) => {
            failed = false;

            t.pass('Ok');
        };
        let failed = true;

        dock.on('dispatcherExecuted', eventCallback.bind(this));
        dock.dispatcher = dispatcher;
        dock._dispatcher.dispatch = (data, callback) => {
            dock._emitEvent('dispatcherExecuted', {});
        };
        dock.process(customMessage, meta, callback);

        setTimeout(() => {
            if (failed) {
                t.fail('dispatcher.dispatch() was never called');
            }
        }, 5);
    });

    test('fails with unrecognized message types', (t) => {
        const customMessage = {
            message: {}
        };
        const returnValue = dock.process(customMessage, meta, callback);

        t.equal(returnValue, false);
    });

    test('fails when there is no dispatcher reference', (t) => {
        let valid = false;

        dock._dispatcher = undefined;
        dock.logger.error = () => {
            valid = true;
        };

        dock.process(message, meta, callback);
        t.equal(valid, true);
    });

    test('fails when the parser returns no data', (t) => {
        const eventCallback = (data) => {
            passed = false;

            t.fail('dispatcher.dispatch() should not have been called');
        };
        let passed = true;

        dock.parse = () => {};

        dock.on('dispatcherExecuted', eventCallback.bind(this));
        dock.dispatcher = dispatcher;
        dock._dispatcher.dispatch = (data, callback) => {
            dock._emitEvent('dispatcherExecuted', {});
        };
        dock.process(message, meta, callback);

        setTimeout(() => {
            t.equal(passed, true);
        }, 5);
    });
});

group('dock.encode()', (test) => {
    const dock = new Dock('test', 'test');

    dock.id = 'test';
    dock.config = config;
    dock.dispatcher = dispatcher;

    test('encodes array messages', (t) => {
        const result = dock.encode({
            message: ['abc', 'def', 'ghi']
        });

        t.equal(result, 'abc,def,ghi');
    });

    test('encodes object messages', (t) => {
        const result = dock.encode({
            message: {
                subtag1: [
                    'abc', 'def', 'ghi'
                ],
                subtag2: ['jkl', 'mno', 'pqr'],
                subtag3: {
                    toString: () => {
                        return 'stu,vwx';
                    }
                }
            }
        });

        t.equal(result, '|subtag1|abc,def,ghi|subtag2|jkl,mno,pqr|subtag3|stu,vwx');
    });

    test('encodes object messages with string values', (t) => {
        const result = dock.encode({
            message: {
                subtag1: 'abc',
                subtag2: 'jkl'
            }
        });

        t.equal(result, '|subtag1|abc|subtag2|jkl');
    });

    test('encodes messages with toString() method', (t) => {
        const message = {
            toString: () => 'Test'
        };

        const result = dock.encode({message: message});

        t.equal(result, 'Test');
    });

    test('returns string messages', (t) => {
        const result = dock.encode({message: 'Test'});

        t.equal(result, 'Test');
    });

    test('handles unknown message types', (t) => {
        const result = dock.encode({
            message: () => 'Test'
        });

        t.equal(result, false);
    });
});

group('dock.reply()', (test) => {
    test('sends a reply', (t, next) => {
        const dock = new Dock('test', 'test');
        let valid = false;

        dock.config = config;
        dock.send = () => {
            valid = true;
        };

        dock.reply({
            meta: {
                dock: dock._id
            },
            message: 'test'
        });

        setTimeout(() => {
            t.equal(valid, true);

            next();
        }, 5);
    });

    test('fails because there is no message to send', (t, next) => {
        const dock = new Dock('test', 'test');
        let valid = false;

        dock.config = config;
        dock.send = () => {};
        dock.logger.error = () => {
            valid = true;
        };

        dock.reply({
            meta: {
                dock: dock._id
            },
            message: {}
        });

        setTimeout(() => {
            t.equal(valid, true);

            next();
        }, 5);
    });

    test('fails with invalid dock reference', (t, next) => {
        const dock = new Dock('test', 'test');
        let valid = false;

        dock.config = config;
        dock.logger.error = () => {
            valid = true;
        };

        dock.reply({
            meta: {
                dock: 'test'
            },
            message: {}
        });

        setTimeout(() => {
            t.equal(valid, true);

            next();
        }, 5);
    });
});

group('dock.on()', (test) => {
    test('registers an event handler', (t, next) => {
        const dock = new Dock('test', 'test');
        let failed = true;

        dock.config = config;

        dock.on('test', () => {
            failed = false;
        });
        dock._emitEvent('test', {});

        setTimeout(() => {
            if (failed) t.fail('Event was not handled');
            else t.pass('Ok');

            next();
        }, 5);
    });
});

group('dock._checkConfig()', (test) => {
    const dock = new Dock('test', 'test');

    dock.id = 'test';
    dock.dispatcher = dispatcher;

    test('checks config', (t, next) => {
        let fails = false;

        dock.config = config;
        dock.logger.error = () => {
            fails = true;
        };

        dock._checkConfig(config);

        setTimeout(() => {
            if (fails) t.fail('Config threw validation errors');
            else t.pass('Ok');

            next();
        }, 5);
    });

    test('catches validation errors', (t, next) => {
        const invalidConfig = {
            parser: {
                subtagSeparator: '|',
                dataSeparator: ','
            },
            encoder: {
                subtagSeparator: '|',
                dataSeparator: ','
            },
            maxMessageLength: 100,
            events: true
        };
        let valid = false;

        dock.logger.error = () => {
            valid = true;
        };

        dock._checkConfig(invalidConfig);

        setTimeout(() => {
            t.equal(valid, true);

            next();
        }, 5);
    });
});

group('dock._emitEvent', (test) => {
    const dock = new Dock('test', 'test');
    let failed = true;

    test('emits events', (t, next) => {
        dock.config = config;

        dock.on('test', () => {
            failed = false;
        });
        dock._emitEvent('test', {});

        setTimeout(() => {
            if (failed) t.fail('Event was not emitted');
            else t.pass('Ok');

            next();
        }, 5);
    });
});<|endoftext|>


<commit_before>import React, { PureComponent as Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import axios from 'axios';
import { Table, Button, Modal, message, Tooltip, Select, Icon } from 'antd';
import AddInterfaceForm from './AddInterfaceForm';
import {
  fetchInterfaceListMenu,
  fetchInterfaceList,
  fetchInterfaceCatList
} from '../../../../reducer/modules/interface.js';
import { getProject } from '../../../../reducer/modules/project.js';
import { Link } from 'react-router-dom';
import variable from '../../../../constants/variable';
import './Edit.scss';
import Label from '../../../../components/Label/Label.js';

const Option = Select.Option;
const limit = 20;

@connect(
  state => {
    return {
      curData: state.inter.curdata,
      curProject: state.project.currProject,
      catList: state.inter.list,
      totalTableList: state.inter.totalTableList,
      catTableList: state.inter.catTableList,
      totalCount: state.inter.totalCount,
      count: state.inter.count
    };
  },
  {
    fetchInterfaceListMenu,
    fetchInterfaceList,
    fetchInterfaceCatList,
    getProject
  }
)
class InterfaceList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      visible: false,
      data: [],
      catid: null,
      total: null,
      current: 1
    };
  }

  static propTypes = {
    curData: PropTypes.object,
    catList: PropTypes.array,
    match: PropTypes.object,
    curProject: PropTypes.object,
    history: PropTypes.object,
    fetchInterfaceListMenu: PropTypes.func,
    fetchInterfaceList: PropTypes.func,
    fetchInterfaceCatList: PropTypes.func,
    totalTableList: PropTypes.array,
    catTableList: PropTypes.array,
    totalCount: PropTypes.number,
    count: PropTypes.number,
    getProject: PropTypes.func
  };

  handleRequest = async props => {
    const { params } = props.match;
    if (!params.actionId) {
      let projectId = params.id;
      this.setState({
        catid: null
      });
      let option = {
        page: this.state.current,
        limit,
        project_id: projectId
      };
      await this.props.fetchInterfaceList(option);
    } else if (isNaN(params.actionId)) {
      let catid = params.actionId.substr(4);
      this.setState({ catid: +catid });
      let option = {
        page: this.state.current,
        limit,
        catid
      };

      await this.props.fetchInterfaceCatList(option);
    }
  };

  // 更新分类简介
  handleChangeInterfaceCat = (desc, name) => {
    let params = {
      catid: this.state.catid,
      name: name,
      desc: desc
    };

    axios.post('/api/interface/up_cat', params).then(async res => {
      if (res.data.errcode !== 0) {
        return message.error(res.data.errmsg);
      }
      let project_id = this.props.match.params.id;
      await this.props.getProject(project_id);
      await this.props.fetchInterfaceListMenu(project_id);
      message.success('接口集合简介更新成功');
    });
  };
  handleChange = (pagination, filters, sorter) => {
    this.setState({
      sortedInfo: sorter
    });
  };

  componentWillMount() {
    this.actionId = this.props.match.params.actionId;
    this.handleRequest(this.props);
  }

  componentWillReceiveProps(nextProps) {
    let _actionId = nextProps.match.params.actionId;

    if (this.actionId !== _actionId) {
      this.actionId = _actionId;
      this.setState(
        {
          current: 1
        },
        () => this.handleRequest(nextProps)
      );
    }
  }

  handleAddInterface = data => {
    data.project_id = this.props.curProject._id;
    axios.post('/api/interface/add', data).then(res => {
      if (res.data.errcode !== 0) {
        return message.error(`${res.data.errmsg}, 你可以在左侧的接口列表中对接口进行删改`);
      }
      message.success('接口添加成功');
      let interfaceId = res.data.data._id;
      this.props.history.push('/project/' + data.project_id + '/interface/api/' + interfaceId);
      this.props.fetchInterfaceListMenu(data.project_id);
    });
  };

  changeInterfaceCat = async (id, catid) => {
    const params = {
      id: id,
      catid
    };
    let result = await axios.post('/api/interface/up', params);
    if (result.data.errcode === 0) {
      message.success('修改成功');
      this.handleRequest(this.props);
      this.props.fetchInterfaceListMenu(this.props.curProject._id);
    } else {
      message.error(result.data.errmsg);
    }
  };

  changeInterfaceStatus = async value => {
    const params = {
      id: value.split('-')[0],
      status: value.split('-')[1]
    };
    let result = await axios.post('/api/interface/up', params);
    if (result.data.errcode === 0) {
      message.success('修改成功');
      this.handleRequest(this.props);
    } else {
      message.error(result.data.errmsg);
    }
  };

  changePage = current => {
    this.setState(
      {
        current: current
      },
      () => this.handleRequest(this.props)
    );
  };

  render() {
    let tag = this.props.curProject.tag;
    let filter = tag.map(item => {
      return { text: item.name, value: item.name };
    });

    const columns = [
      {
        title: '接口名称',
        dataIndex: 'title',
        key: 'title',
        width: 30,
        render: (text, item) => {
          return (
            <Link to={'/project/' + item.project_id + '/interface/api/' + item._id}>
              {text}
            </Link>
          );
        }
      },
      {
        title: '接口路径',
        dataIndex: 'path',
        key: 'path',
        width: 50,
        render: (item, record) => {
          const path = this.props.curProject.basepath + item;
          let methodColor =
            variable.METHOD_COLOR[record.method ? record.method.toLowerCase() : 'get'] ||
            variable.METHOD_COLOR['get'];
          return (

                {record.method}

              <Tooltip title="开放接口" placement="topLeft">
                {record.api_opened && <Icon className="opened" type="eye-o" />}
              </Tooltip>
              <Tooltip title={path} placement="topLeft" overlayClassName="toolTip">
                {path}
              </Tooltip>

          );
        }
      },
      {
        title: '接口分类',
        dataIndex: 'catid',
        key: 'catid',
        width: 28,
        render: (item, record) => {
          return (
            <Select
              value={item + ''}
              className="select path"
              onChange={catid => this.changeInterfaceCat(record._id, catid)}
            >
              {this.props.catList.map(cat => {
                return (
                  <Option key={cat.id + ''} value={cat._id + ''}>
                    {cat.name}
                  </Option>
                );
              })}
            </Select>
          );
        }
      },
      {
        title: '状态',
        dataIndex: 'status',
        key: 'status',
        width: 24,
        render: (text, record) => {
          const key = record.key;
          return (
            <Select
              value={key + '-' + text}
              className="select"
              onChange={this.changeInterfaceStatus}
            >
              <Option value={key + '-done'}>
                已完成
              </Option>
              <Option value={key + '-undone'}>
                未完成
              </Option>
            </Select>
          );
        },
        filters: [
          {
            text: '已完成',
            value: 'done'
          },
          {
            text: '未完成',
            value: 'undone'
          }
        ],
        onFilter: (value, record) => record.status.indexOf(value) === 0
      },
      {
        title: 'tag',
        dataIndex: 'tag',
        key: 'tag',
        width: 14,
        render: text => {
          let textMsg = text.length > 0 ? text.join('\n') : '未设置';
          return
{textMsg}
;
        },
        filters: filter,
        onFilter: (value, record) => {
          return record.tag.indexOf(value) >= 0;
        }
      }
    ];
    let intername = '',
      desc = '';
    let cat = this.props.curProject ? this.props.curProject.cat : [];

    if (cat) {
      for (let i = 0; i < cat.length; i++) {
        if (cat[i]._id === this.state.catid) {
          intername = cat[i].name;
          desc = cat[i].desc;
          break;
        }
      }
    }
    // const data = this.state.data ? this.state.data.map(item => {
    //   item.key = item._id;
    //   return item;
    // }) : [];
    let data = [];
    let total = 0;
    const { params } = this.props.match;
    if (!params.actionId) {
      data = this.props.totalTableList;
      total = this.props.totalCount;
    } else if (isNaN(params.actionId)) {
      data = this.props.catTableList;
      total = this.props.count;
    }

    data = data.map(item => {
      item.key = item._id;
      return item;
    });

    const pageConfig = {
      total: total,
      pageSize: limit,
      current: this.state.current,
      onChange: this.changePage
    };

    const isDisabled = this.props.catList.length === 0;

    // console.log(this.props.curProject.tag)

    return (

          {intername ? intername : '全部接口'}共 ({total}) 个

        <Button
          style={{ float: 'right' }}
          disabled={isDisabled}
          type="primary"
          onClick={() => this.setState({ visible: true })}
        >
          添加接口
        </Button>

           this.handleChangeInterfaceCat(value, intername)} desc={desc} />

        {this.state.visible && (
          <Modal
            title="添加接口"
            visible={this.state.visible}
            onCancel={() => this.setState({ visible: false })}
            footer={null}
            className="addcatmodal"
          >
            <AddInterfaceForm
              catid={this.state.catid}
              catdata={cat}
              onCancel={() => this.setState({ visible: false })}
              onSubmit={this.handleAddInterface}
            />
          </Modal>
        )}

    );
  }
}

export default InterfaceList;
<commit_msg>fix: ldap<commit_after>import React, { PureComponent as Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import axios from 'axios';
import { Table, Button, Modal, message, Tooltip, Select, Icon } from 'antd';
import AddInterfaceForm from './AddInterfaceForm';
import {
  fetchInterfaceListMenu,
  fetchInterfaceList,
  fetchInterfaceCatList
} from '../../../../reducer/modules/interface.js';
import { getProject } from '../../../../reducer/modules/project.js';
import { Link } from 'react-router-dom';
import variable from '../../../../constants/variable';
import './Edit.scss';
import Label from '../../../../components/Label/Label.js';

const Option = Select.Option;
const limit = 20;

@connect(
  state => {
    return {
      curData: state.inter.curdata,
      curProject: state.project.currProject,
      catList: state.inter.list,
      totalTableList: state.inter.totalTableList,
      catTableList: state.inter.catTableList,
      totalCount: state.inter.totalCount,
      count: state.inter.count
    };
  },
  {
    fetchInterfaceListMenu,
    fetchInterfaceList,
    fetchInterfaceCatList,
    getProject
  }
)
class InterfaceList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      visible: false,
      data: [],
      catid: null,
      total: null,
      current: 1
    };
  }

  static propTypes = {
    curData: PropTypes.object,
    catList: PropTypes.array,
    match: PropTypes.object,
    curProject: PropTypes.object,
    history: PropTypes.object,
    fetchInterfaceListMenu: PropTypes.func,
    fetchInterfaceList: PropTypes.func,
    fetchInterfaceCatList: PropTypes.func,
    totalTableList: PropTypes.array,
    catTableList: PropTypes.array,
    totalCount: PropTypes.number,
    count: PropTypes.number,
    getProject: PropTypes.func
  };

  handleRequest = async props => {
    const { params } = props.match;
    if (!params.actionId) {
      let projectId = params.id;
      this.setState({
        catid: null
      });
      let option = {
        page: this.state.current,
        limit,
        project_id: projectId
      };
      await this.props.fetchInterfaceList(option);
    } else if (isNaN(params.actionId)) {
      let catid = params.actionId.substr(4);
      this.setState({ catid: +catid });
      let option = {
        page: this.state.current,
        limit,
        catid
      };

      await this.props.fetchInterfaceCatList(option);
    }
  };

  // 更新分类简介
  handleChangeInterfaceCat = (desc, name) => {
    let params = {
      catid: this.state.catid,
      name: name,
      desc: desc
    };

    axios.post('/api/interface/up_cat', params).then(async res => {
      if (res.data.errcode !== 0) {
        return message.error(res.data.errmsg);
      }
      let project_id = this.props.match.params.id;
      await this.props.getProject(project_id);
      await this.props.fetchInterfaceListMenu(project_id);
      message.success('接口集合简介更新成功');
    });
  };
  handleChange = (pagination, filters, sorter) => {
    this.setState({
      sortedInfo: sorter
    });
  };

  componentWillMount() {
    this.actionId = this.props.match.params.actionId;
    this.handleRequest(this.props);
  }

  componentWillReceiveProps(nextProps) {
    let _actionId = nextProps.match.params.actionId;

    if (this.actionId !== _actionId) {
      this.actionId = _actionId;
      this.setState(
        {
          current: 1
        },
        () => this.handleRequest(nextProps)
      );
    }
  }

  handleAddInterface = data => {
    data.project_id = this.props.curProject._id;
    axios.post('/api/interface/add', data).then(res => {
      if (res.data.errcode !== 0) {
        return message.error(`${res.data.errmsg}, 你可以在左侧的接口列表中对接口进行删改`);
      }
      message.success('接口添加成功');
      let interfaceId = res.data.data._id;
      this.props.history.push('/project/' + data.project_id + '/interface/api/' + interfaceId);
      this.props.fetchInterfaceListMenu(data.project_id);
    });
  };

  changeInterfaceCat = async (id, catid) => {
    const params = {
      id: id,
      catid
    };
    let result = await axios.post('/api/interface/up', params);
    if (result.data.errcode === 0) {
      message.success('修改成功');
      this.handleRequest(this.props);
      this.props.fetchInterfaceListMenu(this.props.curProject._id);
    } else {
      message.error(result.data.errmsg);
    }
  };

  changeInterfaceStatus = async value => {
    const params = {
      id: value.split('-')[0],
      status: value.split('-')[1]
    };
    let result = await axios.post('/api/interface/up', params);
    if (result.data.errcode === 0) {
      message.success('修改成功');
      this.handleRequest(this.props);
    } else {
      message.error(result.data.errmsg);
    }
  };

  changePage = current => {
    this.setState(
      {
        current: current
      },
      () => this.handleRequest(this.props)
    );
  };

  render() {
    let tag = this.props.curProject.tag;
    let filter = tag.map(item => {
      return { text: item.name, value: item.name };
    });

    const columns = [
      {
        title: '接口名称',
        dataIndex: 'title',
        key: 'title',
        width: 30,
        render: (text, item) => {
          return (
            <Link to={'/project/' + item.project_id + '/interface/api/' + item._id}>
              {text}
            </Link>
          );
        }
      },
      {
        title: '接口路径',
        dataIndex: 'path',
        key: 'path',
        width: 50,
        render: (item, record) => {
          const path = this.props.curProject.basepath + item;
          let methodColor =
            variable.METHOD_COLOR[record.method ? record.method.toLowerCase() : 'get'] ||
            variable.METHOD_COLOR['get'];
          return (

                {record.method}

              <Tooltip title="开放接口" placement="topLeft">
                {record.api_opened && <Icon className="opened" type="eye-o" />}
              </Tooltip>
              <Tooltip title={path} placement="topLeft" overlayClassName="toolTip">
                {path}
              </Tooltip>

          );
        }
      },
      {
        title: '接口分类',
        dataIndex: 'catid',
        key: 'catid',
        width: 28,
        render: (item, record) => {
          return (
            <Select
              value={item + ''}
              className="select path"
              onChange={catid => this.changeInterfaceCat(record._id, catid)}
            >
              {this.props.catList.map(cat => {
                return (
                  <Option key={cat.id + ''} value={cat._id + ''}>
                    {cat.name}
                  </Option>
                );
              })}
            </Select>
          );
        }
      },
      {
        title: '状态',
        dataIndex: 'status',
        key: 'status',
        width: 24,
        render: (text, record) => {
          const key = record.key;
          return (
            <Select
              value={key + '-' + text}
              className="select"
              onChange={this.changeInterfaceStatus}
            >
              <Option value={key + '-done'}>
                已完成
              </Option>
              <Option value={key + '-undone'}>
                未完成
              </Option>
            </Select>
          );
        },
        filters: [
          {
            text: '已完成',
            value: 'done'
          },
          {
            text: '未完成',
            value: 'undone'
          }
        ],
        onFilter: (value, record) => record.status.indexOf(value) === 0
      },
      {
        title: 'tag',
        dataIndex: 'tag',
        key: 'tag',
        width: 14,
        render: text => {
          let textMsg = text.length > 0 ? text.join('\n') : '未设置';
          return
{textMsg}
;
        },
        filters: filter,
        onFilter: (value, record) => {
          return record.tag.indexOf(value) >= 0;
        }
      }
    ];
    let intername = '',
      desc = '';
    let cat = this.props.curProject ? this.props.curProject.cat : [];

    if (cat) {
      for (let i = 0; i < cat.length; i++) {
        if (cat[i]._id === this.state.catid) {
          intername = cat[i].name;
          desc = cat[i].desc;
          break;
        }
      }
    }
    // const data = this.state.data ? this.state.data.map(item => {
    //   item.key = item._id;
    //   return item;
    // }) : [];
    let data = [];
    let total = 0;
    const { params } = this.props.match;
    if (!params.actionId) {
      data = this.props.totalTableList;
      total = this.props.totalCount;
    } else if (isNaN(params.actionId)) {
      data = this.props.catTableList;
      total = this.props.count;
    }

    data = data.map(item => {
      item.key = item._id;
      return item;
    }) : null;

    const pageConfig = {
      total: total,
      pageSize: limit,
      current: this.state.current,
      onChange: this.changePage
    };

    const isDisabled = this.props.catList.length === 0;

    // console.log(this.props.curProject.tag)

    return (

          {intername ? intername : '全部接口'}共 ({total}) 个

        <Button
          style={{ float: 'right' }}
          disabled={isDisabled}
          type="primary"
          onClick={() => this.setState({ visible: true })}
        >
          添加接口
        </Button>

           this.handleChangeInterfaceCat(value, intername)} desc={desc} />

        {this.state.visible && (
          <Modal
            title="添加接口"
            visible={this.state.visible}
            onCancel={() => this.setState({ visible: false })}
            footer={null}
            className="addcatmodal"
          >
            <AddInterfaceForm
              catid={this.state.catid}
              catdata={cat}
              onCancel={() => this.setState({ visible: false })}
              onSubmit={this.handleAddInterface}
            />
          </Modal>
        )}

    );
  }
}

export default InterfaceList;
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

angular.module('dgc.search').controller('SearchController', ['$scope', '$location', '$http', '$state', '$stateParams', 'SearchResource', 'NotificationService',
    function($scope, $location, $http, $state, $stateParams, SearchResource, NotificationService) {

        $scope.types = ['table','column','db','view','loadprocess','storagedesc'];
        $scope.results = [];
        $scope.resultCount=0;
        $scope.isCollapsed = true;
        $scope.currentPage = 1;
        $scope.itemsPerPage = 10
        $scope.totalItems = 40;
        $scope.filteredResults = [];
        $scope.resultRows = [];

        $scope.setPage = function (pageNo) {
            $scope.currentPage = pageNo;
        };
        $scope.search = function(query) {
            $scope.results = [];
            NotificationService.reset();
            $scope.limit = 4;
            SearchResource.search({query:query}, function searchSuccess(response) {

                $scope.resultCount=response.count;
                $scope.results = response.results;
                $scope.resultRows = $scope.results.rows;
                $scope.totalItems = $scope.resultCount;
                $scope.$watch('currentPage + itemsPerPage', function() {
                    var begin = (($scope.currentPage - 1) * $scope.itemsPerPage),
                        end = begin + $scope.itemsPerPage;
                    $scope.searchTypesAvailable = $scope.typeAvailable();
                    console.log($scope.searchTypesAvailable);
                    if ($scope.searchTypesAvailable) {
                        console.log($scope.searchTypesAvailable);
                        $scope.searchMessage = 'loading results...';
                        $scope.filteredResults = $scope.resultRows.slice(begin, end);
                        $scope.pageCount = function () {
                            return Math.ceil($scope.resultCount / $scope.itemsPerPage);
                        };
                        if ($scope.results.rows)
                            $scope.searchMessage = $scope.results.rows.length +' results matching your search query '+ $scope.query +' were found';
                        else
                            $scope.searchMessage = '0 results matching your search query '+ $scope.query +' were found';
                        if ($scope.results.length < 1) {
                            NotificationService.error('No Result found', false);
                        }
                    } else {
                        $scope.searchMessage = '0 results matching your search query '+ $scope.query +' were found';
                    }
                });
                $state.go('search.results', {query:query}, {
                    location: 'replace'
                });

            }, function searchError(err) {
                NotificationService.error('Error occurred during executing search query, error status code = ' + err.status + ', status text = ' + err.statusText, false);
            });
        };

        $scope.typeAvailable = function() {

           if($scope.results.dataType) {
               return $scope.types.indexOf($scope.results.dataType.typeName && $scope.results.dataType.typeName.toLowerCase()) > -1;
           }
        };

        $scope.onKeyPress = function ($event,query) {
            console.log($event);
        };

        $scope.doToggle = function($event,el) {
            this.isCollapsed = !el;
        };
        $scope.filterSearchResults = function(items) {
            var res = {};
            var count = 0;
            angular.forEach(items, function(value, key) {
                if(typeof value !== 'object') {
                    res[key] = value;
                    count++;
                }
            });

            $scope.keyLength = count;
            return res;
        };
        $scope.searchQuery = $location.search();
        $scope.query=($location.search()).query;
        if ($scope.query) {
            $scope.searchMessage = 'searching...';
            $scope.search($scope.query);
        }
    }
]);
<commit_msg>fixed couple of syntax errors and removes all debug info<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

angular.module('dgc.search').controller('SearchController', ['$scope', '$location', '$http', '$state', '$stateParams', 'SearchResource', 'NotificationService',
    function($scope, $location, $http, $state, $stateParams, SearchResource, NotificationService) {

        $scope.types = ['table','column','db','view','loadprocess','storagedesc'];
        $scope.results = [];
        $scope.resultCount=0;
        $scope.isCollapsed = true;
        $scope.currentPage = 1;
        $scope.itemsPerPage = 10;
        $scope.totalItems = 40;
        $scope.filteredResults = [];
        $scope.resultRows = [];

        $scope.setPage = function (pageNo) {
            $scope.currentPage = pageNo;
        };
        $scope.search = function(query) {
            $scope.results = [];
            NotificationService.reset();
            $scope.limit = 4;
            SearchResource.search({query:query}, function searchSuccess(response) {

                $scope.resultCount=response.count;
                $scope.results = response.results;
                $scope.resultRows = $scope.results.rows;
                $scope.totalItems = $scope.resultCount;
                $scope.$watch('currentPage + itemsPerPage', function() {
                    var begin = (($scope.currentPage - 1) * $scope.itemsPerPage),
                        end = begin + $scope.itemsPerPage;
                    $scope.searchTypesAvailable = $scope.typeAvailable();
                    if ($scope.searchTypesAvailable) {
                        $scope.searchMessage = 'loading results...';
                        $scope.filteredResults = $scope.resultRows.slice(begin, end);
                        $scope.pageCount = function () {
                            return Math.ceil($scope.resultCount / $scope.itemsPerPage);
                        };
                        if ($scope.results.rows)
                            $scope.searchMessage = $scope.results.rows.length +' results matching your search query '+ $scope.query +' were found';
                        else
                            $scope.searchMessage = '0 results matching your search query '+ $scope.query +' were found';
                        if ($scope.results.length < 1) {
                            NotificationService.error('No Result found', false);
                        }
                    } else {
                        $scope.searchMessage = '0 results matching your search query '+ $scope.query +' were found';
                    }
                });
                $state.go('search.results', {query:query}, {
                    location: 'replace'
                });

            }, function searchError(err) {
                NotificationService.error('Error occurred during executing search query, error status code = ' + err.status + ', status text = ' + err.statusText, false);
            });
        };

        $scope.typeAvailable = function() {

           if($scope.results.dataType) {
               return $scope.types.indexOf($scope.results.dataType.typeName && $scope.results.dataType.typeName.toLowerCase()) > -1;
           }
        };
        $scope.doToggle = function($event,el) {
            this.isCollapsed = !el;
        };
        $scope.filterSearchResults = function(items) {
            var res = {};
            var count = 0;
            angular.forEach(items, function(value, key) {
                if(typeof value !== 'object') {
                    res[key] = value;
                    count++;
                }
            });

            $scope.keyLength = count;
            return res;
        };
        $scope.searchQuery = $location.search();
        $scope.query=($location.search()).query;
        if ($scope.query) {
            $scope.searchMessage = 'searching...';
            $scope.search($scope.query);
        }
    }
]);
<|endoftext|>


<commit_before>import FilterControls from './FilterControls';
import FilterContainer from './FilterContainer';
import Positions from './Positions';
import {
  concat,
  debounce,
  intersection,
  includes,
  isEqual,
  merge,
  reverse,
  shuffle,
  sortBy,
} from './vendor/lodash.custom';

class Filterizr {
  constructor(selector = ".filtr-container", options) {
    // make the options a property of the Filterizr instance
    // so that we can later easily modify them
    this.options = options;

    // setup FilterControls and FilterContainer
    const filterControls  = new FilterControls(this);
    const filterContainer = new FilterContainer(selector, options);
    // define props
    this.props = {
      searchTerm: '',
      sort: 'index',
      sortOrder: 'asc',
      FilterContainer: filterContainer,
      FilterItems: filterContainer.props.FilterItems,
      FilteredItems: [],
    }

    // set up events needed by Filterizr
    this.setupEvents();
    // Init Filterizr
    this.filter(this.options.filter);
  }

  // Public API of Filterizr
  filter(category) {
    const {
      searchTerm,
      FilterContainer,
      FilterItems,
    } = this.props;

    // trigger filtering start event
    FilterContainer.trigger('filteringStart');

    // filter items and optionally apply search if a search term exists
    const FilteredItems = this.searchFilterItems(this.filterFilterItems(FilterItems, category), searchTerm);
    this.props.FilteredItems = FilteredItems;

    // set up events needed by Filterizr
    // render the items
    this.render(FilteredItems);
  }

  sort(sortAttr = 'index', sortOrder = 'asc') {
    const {
      FilterItems,
    } = this.props;

    // sort main array
    this.props.FilterItems = this.sortFilterItems(FilterItems, sortAttr, sortOrder);
    // apply filters
    const FilteredItems = this.filterFilterItems(this.props.FilterItems, this.options.filter);
    this.props.FilteredItems = FilteredItems;

    // Update and render the sorted items
    this.render(FilteredItems);
  }

  search(searchTerm = this.props.searchTerm) {
    const {
      FilterItems
    } = this.props;

    // filter items and optionally apply search if a search term exists
    const FilteredItems = this.searchFilterItems(this.filterFilterItems(FilterItems, this.options.filter), searchTerm);
    this.props.FilteredItems = FilteredItems;

    // render the items
    this.render(FilteredItems);
  }

  shuffle() {
    const {
      FilteredItems
    } = this.props;

    const ShuffledItems = this.shuffleFilterItems(FilteredItems);
    this.props.FilteredItems = ShuffledItems;

    this.render(ShuffledItems);
  }

  setOptions(newOptions) {
    this.options = merge(this.options, newOptions);
  }

  toggleFilter(toggledFilter) {
    // NOTE: fix bug in how filters are toggled
    let activeFilters = this.options.filter;

    // if the active filters are already an array
    if (Array.isArray(activeFilters)) {
      // check if toggledFilter is there
      if (~activeFilters.indexOf(toggledFilter)) {
        // remove filter
        activeFilters = activeFilters.filter(f => f !== toggledFilter);
        // if there is now only 1 item in the array flatten it
        if (activeFilters.length === 1)
          activeFilters = activeFilters[0];
      }
      // otherwise just push it
      else
        activeFilters.push(toggledFilter);
    }
    // in case there is only one active filter, then form an array
    else  {
      // if the current filter is set to "all"
      activeFilters === "all" ?
        // then just set the filter to the int of the target filter
        activeFilters = toggledFilter :
        // if the active filter is already set to a category
        // and the user clicks another category filter, check
        // that they are not the same and
        (activeFilters !== toggledFilter) ?
        // form an array with both of them
        activeFilters = concat(activeFilters, toggledFilter) :
        // if the same category is clicked then revert filter to "all"
        activeFilters = "all";
    }

    // update active filter in Filterizr's options
    this.setOptions({
      filter: activeFilters,
    });

    console.log(activeFilters)
    this.filter(this.options.filter);
  }

  // Helper methods
  filterFilterItems(FilterItems, filters) {
    // Get filtered items
    const FilteredItems = (filters === "all") ?
      // in this case return all items
      FilterItems :
      // otherwise return filtered array
      FilterItems.filter(FilterItem => {
        const categories = FilterItem.getCategories();
        return Array.isArray(filters) ?
          intersection(categories, filters).length :
          includes(categories, filters)
      });

    return FilteredItems;
  }

  sortFilterItems(FilterItems ,sortAttr = 'index', sortOrder = 'asc') {
    // Sort the FilterItems and reverse the array if order is descending
    let SortedItems = sortBy(FilterItems, (FilterItem) => {
      return (sortAttr !== 'index' && sortAttr !== 'sortData') ?
        // if the user has not used one of the two default sort attributes
        // then search for custom data attributes on the filter items to sort
        FilterItem.props.data[sortAttr] :
        // otherwise use the defaults
        FilterItem.props[sortAttr];
    });
    SortedItems = sortOrder === 'asc' ? SortedItems : reverse(SortedItems);

    return SortedItems;
  }

  searchFilterItems(FilterItems, searchTerm = this.props.searchTerm) {
    if (!searchTerm) return FilterItems; // exit case when no search is applied

    const SoughtItems =  FilterItems.filter(FilterItem => {
      const contents = FilterItem.getContentsLowercase();
      return includes(contents, searchTerm);
    });

    return SoughtItems;
  }

  shuffleFilterItems(FilterItems) {
    let ShuffledItems = shuffle(FilterItems)
    // shuffle items until they are different from the initial FilteredItems
    while (FilterItems.length > 1 && isEqual(FilterItems, ShuffledItems)) {
      ShuffledItems = shuffle(FilterItems)
    }

    return ShuffledItems;
  }

  render(FilterItems) {
    // get items to be filtered out
    const FilteredOutItems = this.props.FilterItems.filter(FilterItem => {
      const categories = FilterItem.getCategories();
      const filters = this.options.filter;
      return Array.isArray(filters) ?
        !intersection(categories, filters).length :
        !includes(categories, filters)
    })
    // filter out old items
    FilteredOutItems.forEach(FilterItem => {
      FilterItem.filterOut(this.options.filterOutCss);
    });

    // Determine target positions for items to be filtered in
    const PositionsArray = Positions(this.options.layout, this);

    // filter in new items
    FilterItems.forEach((FilterItem, index) => {
      FilterItem.filterIn(PositionsArray[index], this.options.filterInCss);
    });
  }

  setupEvents() {
    // set up a window resize event to fire refiltering
    $(window).on('resize', debounce((evt) => {
      // update dimensions of items based on new window size
      this.props.FilterContainer.updateWidth();
      this.props.FilterContainer.updateFilterItemsDimensions();
      // refilter the grid to assume new positions
      this.filter(this.options.filter);
    }, 250));
  }
}

export default Filterizr;
<commit_msg>cast category to string before filtering<commit_after>import FilterControls from './FilterControls';
import FilterContainer from './FilterContainer';
import Positions from './Positions';
import {
  concat,
  debounce,
  intersection,
  includes,
  isEqual,
  merge,
  reverse,
  shuffle,
  sortBy,
} from './vendor/lodash.custom';

class Filterizr {
  constructor(selector = ".filtr-container", options) {
    // make the options a property of the Filterizr instance
    // so that we can later easily modify them
    this.options = options;

    // setup FilterControls and FilterContainer
    const filterControls  = new FilterControls(this);
    const filterContainer = new FilterContainer(selector, options);
    // define props
    this.props = {
      searchTerm: '',
      sort: 'index',
      sortOrder: 'asc',
      FilterContainer: filterContainer,
      FilterItems: filterContainer.props.FilterItems,
      FilteredItems: [],
    }

    // set up events needed by Filterizr
    this.setupEvents();
    // Init Filterizr
    this.filter(this.options.filter);
  }

  // Public API of Filterizr
  filter(category) {
    const {
      searchTerm,
      FilterContainer,
      FilterItems,
    } = this.props;

    // trigger filtering start event
    FilterContainer.trigger('filteringStart');

    // cast category to string or array of strings
    category = Array.isArray(category) ?
      category.map(c => c.toString()) :
      category.toString();

    // filter items and optionally apply search if a search term exists
    const FilteredItems = this.searchFilterItems(this.filterFilterItems(FilterItems, category), searchTerm);
    this.props.FilteredItems = FilteredItems;

    // set up events needed by Filterizr
    // render the items
    this.render(FilteredItems);
  }

  sort(sortAttr = 'index', sortOrder = 'asc') {
    const {
      FilterItems,
    } = this.props;

    // sort main array
    this.props.FilterItems = this.sortFilterItems(FilterItems, sortAttr, sortOrder);
    // apply filters
    const FilteredItems = this.filterFilterItems(this.props.FilterItems, this.options.filter);
    this.props.FilteredItems = FilteredItems;

    // Update and render the sorted items
    this.render(FilteredItems);
  }

  search(searchTerm = this.props.searchTerm) {
    const {
      FilterItems
    } = this.props;

    // filter items and optionally apply search if a search term exists
    const FilteredItems = this.searchFilterItems(this.filterFilterItems(FilterItems, this.options.filter), searchTerm);
    this.props.FilteredItems = FilteredItems;

    // render the items
    this.render(FilteredItems);
  }

  shuffle() {
    const {
      FilteredItems
    } = this.props;

    const ShuffledItems = this.shuffleFilterItems(FilteredItems);
    this.props.FilteredItems = ShuffledItems;

    this.render(ShuffledItems);
  }

  setOptions(newOptions) {
    this.options = merge(this.options, newOptions);
  }

  toggleFilter(toggledFilter) {
    // NOTE: fix bug in how filters are toggled
    let activeFilters = this.options.filter;

    // if the active filters are already an array
    if (Array.isArray(activeFilters)) {
      // check if toggledFilter is there
      if (~activeFilters.indexOf(toggledFilter)) {
        // remove filter
        activeFilters = activeFilters.filter(f => f !== toggledFilter);
        // if there is now only 1 item in the array flatten it
        if (activeFilters.length === 1)
          activeFilters = activeFilters[0];
      }
      // otherwise just push it
      else
        activeFilters.push(toggledFilter);
    }
    // in case there is only one active filter, then form an array
    else  {
      // if the current filter is set to "all"
      activeFilters === "all" ?
        // then just set the filter to the int of the target filter
        activeFilters = toggledFilter :
        // if the active filter is already set to a category
        // and the user clicks another category filter, check
        // that they are not the same and
        (activeFilters !== toggledFilter) ?
        // form an array with both of them
        activeFilters = concat(activeFilters, toggledFilter) :
        // if the same category is clicked then revert filter to "all"
        activeFilters = "all";
    }

    // update active filter in Filterizr's options
    this.setOptions({
      filter: activeFilters,
    });

    console.log(activeFilters)
    this.filter(this.options.filter);
  }

  // Helper methods
  filterFilterItems(FilterItems, filters) {
    // Get filtered items
    const FilteredItems = (filters === "all") ?
      // in this case return all items
      FilterItems :
      // otherwise return filtered array
      FilterItems.filter(FilterItem => {
        const categories = FilterItem.getCategories();
        return Array.isArray(filters) ?
          intersection(categories, filters).length :
          includes(categories, filters)
      });

    return FilteredItems;
  }

  sortFilterItems(FilterItems ,sortAttr = 'index', sortOrder = 'asc') {
    // Sort the FilterItems and reverse the array if order is descending
    let SortedItems = sortBy(FilterItems, (FilterItem) => {
      return (sortAttr !== 'index' && sortAttr !== 'sortData') ?
        // if the user has not used one of the two default sort attributes
        // then search for custom data attributes on the filter items to sort
        FilterItem.props.data[sortAttr] :
        // otherwise use the defaults
        FilterItem.props[sortAttr];
    });
    SortedItems = sortOrder === 'asc' ? SortedItems : reverse(SortedItems);

    return SortedItems;
  }

  searchFilterItems(FilterItems, searchTerm = this.props.searchTerm) {
    if (!searchTerm) return FilterItems; // exit case when no search is applied

    const SoughtItems =  FilterItems.filter(FilterItem => {
      const contents = FilterItem.getContentsLowercase();
      return includes(contents, searchTerm);
    });

    return SoughtItems;
  }

  shuffleFilterItems(FilterItems) {
    let ShuffledItems = shuffle(FilterItems)
    // shuffle items until they are different from the initial FilteredItems
    while (FilterItems.length > 1 && isEqual(FilterItems, ShuffledItems)) {
      ShuffledItems = shuffle(FilterItems)
    }

    return ShuffledItems;
  }

  render(FilterItems) {
    // get items to be filtered out
    const FilteredOutItems = this.props.FilterItems.filter(FilterItem => {
      const categories = FilterItem.getCategories();
      const filters = this.options.filter;
      return Array.isArray(filters) ?
        !intersection(categories, filters).length :
        !includes(categories, filters)
    })
    // filter out old items
    FilteredOutItems.forEach(FilterItem => {
      FilterItem.filterOut(this.options.filterOutCss);
    });

    // Determine target positions for items to be filtered in
    const PositionsArray = Positions(this.options.layout, this);

    // filter in new items
    FilterItems.forEach((FilterItem, index) => {
      FilterItem.filterIn(PositionsArray[index], this.options.filterInCss);
    });
  }

  setupEvents() {
    // set up a window resize event to fire refiltering
    $(window).on('resize', debounce((evt) => {
      // update dimensions of items based on new window size
      this.props.FilterContainer.updateWidth();
      this.props.FilterContainer.updateFilterItemsDimensions();
      // refilter the grid to assume new positions
      this.filter(this.options.filter);
    }, 250));
  }
}

export default Filterizr;
<|endoftext|>


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

let userAuth = false;
let userName = '';
let counter = 1;
/**
 * Authenticate user
 */
async function authenticate() {
  try {
    logInOut = document.getElementById('logInOut');
    const response = await fetch('/auth');
    const userDetails = await response.json();

    if (userDetails.email) {
      userAuth = true;
      logInOut.innerHTML = `Logout`;
      setPreference();
    } else {
      if (userDetails.invalidLogin) {
        logInOut.innerHTML = `Logout`;
        alert(`We can only allow @google.com users currently. Please logout
        and make sure you are logged in with your @google.com account before
        trying again.`);
      } else {
        userAuth = false;
        logInOut.innerHTML = `<a href="${userDetails.loginUrl}">Login</a>`;
      }
    }
  } catch (e) {
    console.log('Error: ', e.message);
  }
};

/**
 * Set user UI preferneces
 */
async function setPreference() {
  try {
    const response = await fetch('/auth');
    const userDetails = await response.json();
    const userFont = userDetails.font;
    const userFontSize = userDetails.font_size;
    const userFontColor = userDetails.text_color;
    const userBackgroundColor = userDetails.bg_color;
    userName = userDetails.name;

    document.body.style.fontFamily = userFont;
    document.body.style.fontSize = userFontSize + 'px';
    document.body.style.color = userFontColor;
    document.body.style.backgroundColor = userBackgroundColor;
  } catch (e) {
    console.log('Error: ', e.message);
  }
}

// On load
window.onload = function() {
  authenticate();
};

/* eslint-disable no-unused-vars */
/**
 * Check if user has access to page
 */
function pageAccess() {
  if (userAuth) {
    const page = newUser(userName);
    window.location.href = page;
  } else {
    document.getElementById(
        'accessDenied',
    ).innerHTML = `<p> Cannot access until you login</p>`;
  }
};

/**
 * Check if user is new
 * @param {string} name name of the user
 * @return {string} return href depending on user status
 */
function newUser(name) {
  if (name === null) {
    return 'userSetUp.html';
  } else if (name === undefined) {
    return 'userSetUp.html';
  } else {
    return '/dashboardServlet';
  }
};

/**
 * Gets the list of checkbox items
 */
function getCheckBox() {
  const checkBoxList = document.querySelectorAll('#checkbox');
  const submitButton = document.getElementById('checkBoxSubmit');
  isChecked(checkBoxList, submitButton);
};

/**
 * Checks if any items in the list are checked
 * @param {NodeListOf<Element>} checkBoxList List of checkbox items
 * @param {HTMLElement} submitButton Html for submit button
 * @return {Boolean} returns if any boxes are checked
 */
function isChecked(checkBoxList, submitButton) {
  const checkBoxArray = [...checkBoxList];
  const areTheyChecked = checkBoxArray.some((box) => box.checked);
  if (areTheyChecked) {
    submitButton.style.display = 'block';
  } else {
    submitButton.style.display = 'none';
  }
  return areTheyChecked;
};
/** Checks if the MCQ checkbox is checked */
function getMcqChecked() {
  const mcqCheck = document.getElementById('mcqCheckBox');
  const addFieldsButton = document.getElementById('addFields');
  const removeFieldsButton= document.getElementById('removeFields');
  const fieldsList = document.getElementById('fieldsList');
  const mcqAnswer = document.getElementById('mcqAnswer');
  const mcqLine = document.getElementById('mcq');
  if (mcqCheck.checked) {
    addFieldsButton.style.display = 'inline-block';
    removeFieldsButton.style.display = 'inline-block';
    fieldsList.style.display = 'block';
    mcqLine.style.display = 'block';
    mcqAnswer.style.display = 'block';
  } else {
    addFieldsButton.style.display = 'none';
    removeFieldsButton.style.display = 'none';
    mcqAnswer.style.display = 'none';
    mcqLine.style.display = 'none';
    fieldsList.style.display = 'none';
  }
};
/** Add more input fields for the MCQ answers */
function moreFields() {
  if (counter >= 5) {
    document.getElementById('popup').style.display = 'block';
  } else {
    const dropdown = document.createElement('OPTION');
    dropdown.innerHTML ='<option>' + counter + '</option';
    document.getElementById('mcqAnswer').append(dropdown);
    document.getElementById('mcqAnswer').style.display = 'block';
    document.getElementById('mcq').style.display = 'block';
    const number = document.createElement('SPAN');
    number.innerHTML = counter + '. ';
    const field = document.createElement('input');
    field.type ='text';
    field.name = 'mcqField';
    field.id = 'mcqField'+counter;
    field.onClick = startDictation(field.id);
    field.cols = '50';
    field.rows = '3';
    field.style.display = 'block';
    field.required = true;
    number.append(field);
    document.getElementById('fieldsList').append(number);
    document.getElementById('removeFields').style.display = 'inline-block';
    counter++;
  }
};
/** Remove the last field from the MCQ answers */
function lessFields() {
  if (counter > 1) {
    const listOfFields = document.getElementById('fieldsList').lastChild;
    listOfFields.parentNode.removeChild(listOfFields);
    document.getElementById('popup').style.display = 'none';
    counter--;
  }
};
/**
*  Starts the speech to text ability
*  @param {string} Id id of the element that called startDictation
*
 */
function startDictation(Id) {
  if (window.hasOwnProperty('webkitSpeechRecognition')) {
    const WebkitSpeechRecognition = webkitSpeechRecognition;
    const recognition = new WebkitSpeechRecognition();
    recognition.continuous = false;
    recognition.interimResults = false;
    recognition.lang = 'en-GB';
    recognition.start();
    recognition.onresult = function(e) {
      if (document.getElementById(Id).value == null) {
        document.getElementById(Id).value = e.results[0][0].transcript;
      } else {
        document.getElementById(Id).value +=' ' + e.results[0][0].transcript;
      }
      recognition.stop();
    };
    recognition.onerror = function(e) {
      recognition.stop();
    };
  }
};
/* eslint-enable no-unused-vars */

// Export modules for testing
if (typeof exports !== 'undefined') {
  module.exports = {
    authenticate,
    setPreference,
    pageAccess,
    userAuth,
    userName,
    newUser,
    isChecked,
  };
};
/* eslint-disable no-unused-vars */

/* eslint-disable no-unused-vars */
<commit_msg>Remove blank lines<commit_after>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

let userAuth = false;
let userName = '';
let counter = 1;
/**
 * Authenticate user
 */
async function authenticate() {
  try {
    logInOut = document.getElementById('logInOut');
    const response = await fetch('/auth');
    const userDetails = await response.json();

    if (userDetails.email) {
      userAuth = true;
      logInOut.innerHTML = `Logout`;
      setPreference();
    } else {
      if (userDetails.invalidLogin) {
        logInOut.innerHTML = `Logout`;
        alert(`We can only allow @google.com users currently. Please logout
        and make sure you are logged in with your @google.com account before
        trying again.`);
      } else {
        userAuth = false;
        logInOut.innerHTML = `<a href="${userDetails.loginUrl}">Login</a>`;
      }
    }
  } catch (e) {
    console.log('Error: ', e.message);
  }
};

/**
 * Set user UI preferneces
 */
async function setPreference() {
  try {
    const response = await fetch('/auth');
    const userDetails = await response.json();
    const userFont = userDetails.font;
    const userFontSize = userDetails.font_size;
    const userFontColor = userDetails.text_color;
    const userBackgroundColor = userDetails.bg_color;
    userName = userDetails.name;

    document.body.style.fontFamily = userFont;
    document.body.style.fontSize = userFontSize + 'px';
    document.body.style.color = userFontColor;
    document.body.style.backgroundColor = userBackgroundColor;
  } catch (e) {
    console.log('Error: ', e.message);
  }
}

// On load
window.onload = function() {
  authenticate();
};

/* eslint-disable no-unused-vars */
/**
 * Check if user has access to page
 */
function pageAccess() {
  if (userAuth) {
    const page = newUser(userName);
    window.location.href = page;
  } else {
    document.getElementById(
        'accessDenied',
    ).innerHTML = `<p> Cannot access until you login</p>`;
  }
};

/**
 * Check if user is new
 * @param {string} name name of the user
 * @return {string} return href depending on user status
 */
function newUser(name) {
  if (name === null) {
    return 'userSetUp.html';
  } else if (name === undefined) {
    return 'userSetUp.html';
  } else {
    return '/dashboardServlet';
  }
};

/**
 * Gets the list of checkbox items
 */
function getCheckBox() {
  const checkBoxList = document.querySelectorAll('#checkbox');
  const submitButton = document.getElementById('checkBoxSubmit');
  isChecked(checkBoxList, submitButton);
};

/**
 * Checks if any items in the list are checked
 * @param {NodeListOf<Element>} checkBoxList List of checkbox items
 * @param {HTMLElement} submitButton Html for submit button
 * @return {Boolean} returns if any boxes are checked
 */
function isChecked(checkBoxList, submitButton) {
  const checkBoxArray = [...checkBoxList];
  const areTheyChecked = checkBoxArray.some((box) => box.checked);
  if (areTheyChecked) {
    submitButton.style.display = 'block';
  } else {
    submitButton.style.display = 'none';
  }
  return areTheyChecked;
};
/** Checks if the MCQ checkbox is checked */
function getMcqChecked() {
  const mcqCheck = document.getElementById('mcqCheckBox');
  const addFieldsButton = document.getElementById('addFields');
  const removeFieldsButton= document.getElementById('removeFields');
  const fieldsList = document.getElementById('fieldsList');
  const mcqAnswer = document.getElementById('mcqAnswer');
  const mcqLine = document.getElementById('mcq');
  if (mcqCheck.checked) {
    addFieldsButton.style.display = 'inline-block';
    removeFieldsButton.style.display = 'inline-block';
    fieldsList.style.display = 'block';
    mcqLine.style.display = 'block';
    mcqAnswer.style.display = 'block';
  } else {
    addFieldsButton.style.display = 'none';
    removeFieldsButton.style.display = 'none';
    mcqAnswer.style.display = 'none';
    mcqLine.style.display = 'none';
    fieldsList.style.display = 'none';
  }
};
/** Add more input fields for the MCQ answers */
function moreFields() {
  if (counter >= 5) {
    document.getElementById('popup').style.display = 'block';
  } else {
    const dropdown = document.createElement('OPTION');
    dropdown.innerHTML ='<option>' + counter + '</option';
    document.getElementById('mcqAnswer').append(dropdown);
    document.getElementById('mcqAnswer').style.display = 'block';
    document.getElementById('mcq').style.display = 'block';
    const number = document.createElement('SPAN');
    number.innerHTML = counter + '. ';
    const field = document.createElement('input');
    field.type ='text';
    field.name = 'mcqField';
    field.id = 'mcqField'+counter;
    field.onClick = startDictation(field.id);
    field.cols = '50';
    field.rows = '3';
    field.style.display = 'block';
    field.required = true;
    number.append(field);
    document.getElementById('fieldsList').append(number);
    document.getElementById('removeFields').style.display = 'inline-block';
    counter++;
  }
};
/** Remove the last field from the MCQ answers */
function lessFields() {
  if (counter > 1) {
    const listOfFields = document.getElementById('fieldsList').lastChild;
    listOfFields.parentNode.removeChild(listOfFields);
    document.getElementById('popup').style.display = 'none';
    counter--;
  }
};
/**
*  Starts the speech to text ability
*  @param {string} Id id of the element that called startDictation
*
 */
function startDictation(Id) {
  if (window.hasOwnProperty('webkitSpeechRecognition')) {
    const WebkitSpeechRecognition = webkitSpeechRecognition;
    const recognition = new WebkitSpeechRecognition();
    recognition.continuous = false;
    recognition.interimResults = false;
    recognition.lang = 'en-GB';
    recognition.start();
    recognition.onresult = function(e) {
      if (document.getElementById(Id).value == null) {
        document.getElementById(Id).value = e.results[0][0].transcript;
      } else {
        document.getElementById(Id).value +=' ' + e.results[0][0].transcript;
      }
      recognition.stop();
    };
    recognition.onerror = function(e) {
      recognition.stop();
    };
  }
};
/* eslint-enable no-unused-vars */

// Export modules for testing
if (typeof exports !== 'undefined') {
  module.exports = {
    authenticate,
    setPreference,
    pageAccess,
    userAuth,
    userName,
    newUser,
    isChecked,
  };
};
/* eslint-disable no-unused-vars */

/* eslint-disable no-unused-vars */
<|endoftext|>