<commit_before>var getContext = function(display, infos) {

    var language_strings = {
        en: {
            categories: {
                database: 'Database'
            },
            label: {
                loadTable: 'loadTable(%1)',
                loadTableFromCsv: 'loadTableFromCsv(%1, %2)',
                getRecords: 'getRecords(%1)',
                selectByColumn: 'selectByColumn(%1, %2, %3)',
                selectByFunction: 'selectByFunction(%1, %2)',
                selectTopRows: 'selectTopRows(%1, %2)',
                getColumn: 'getColumn(%1, %2)',
                sortByColumn: 'sortByColumn(%1, %2, %3)',
                sortByFunction: 'sortByFunction(%1, %2)',
                selectColumns: 'selectColumns(%1, %2)',
                joinTables: 'joinTables(%1, %2, %3, %4, %5)',
                displayTable: 'displayTable(%1, %2)',
                updateWhere: 'updateWhere(%1, %2, %3)',
                insertRecord: 'insertRecord(%1, %2)',
                unionTables: 'unionTables(%1, %2)',
                displayRecord: 'displayRecord(%1)',
                displayTableOnMap: 'displayTableOnMap(%1, %2, %3, %4)'
            },
            code: {
                loadTable: 'loadTable',
                loadTableFromCsv: 'loadTableFromCsv',
                getRecords: 'getRecords',
                selectByColumn: 'selectByColumn',
                selectByFunction: 'selectByFunction',
                selectTopRows: 'selectTopRows',
                getColumnL: 'getColumn',
                sortByColumn: 'sortByColumn',
                sortByFunction: 'sortByFunction',
                selectColumns: 'selectColumns',
                joinTables: 'joinTables',
                displayTable: 'displayTable',
                updateWhere: 'updateWhere',
                insertRecord: 'insertRecord',
                unionTables: 'unionTables',
                displayRecord: 'displayRecord',
                displayTableOnMap: 'displayTableOnMap'
            },
            description: {
/*                loadTable: 'loadTable',
                loadTableFromCsv: 'loadTableFromCsv',
                getRecords: 'getRecords',
                selectByColumn: 'selectByColumn',
                selectByFunction: 'selectByFunction',
                selectTopRows: 'selectTopRows',
                getColumnL: 'getColumn',
                sortByColumn: 'sortByColumn',
                sortByFunction: 'sortByFunction',
                selectColumns: 'selectColumns',
                joinTables: 'joinTables',
                displayTable: 'displayTable',
                updateWhere: 'updateWhere',
                insertRecord: 'insertRecord',
                unionTables: 'unionTables',
                displayRecord: 'displayRecord',
                displayTableOnMap: 'displayTableOnMap'*/
            },
            startingBlockName: "Programme",
            constantLabel: {
                asc: 'asc',
                desc: 'desc',
                inner: 'inner',
                outer: 'outer',
                left: 'left',
                right: 'right'
            },
            messages: {
                table_not_found: 'Table not found: ',
                incorrect_results: 'Incorrect results',
                some_results_missing: 'Some results are missing'
            },
            ui: {
                'btn_files_repository': 'Add CSV files...',
                'files_repository': {
                    'caption': 'CSV files list',
                    'hint': 'Use file number as param for loadTableFromCsv function. Allowed CSV files with ; delimiter only.',
                    'add': 'Add',
                    'incompatible_browser': 'Incompatible browser'
                }
            }
        },
        fr: {
            categories: {
                database: 'Base de données'
            },
            label: {
                loadTable: 'loadTable(%1)',
                loadTableFromCsv: 'loadTableFromCsv(%1, %2)',
                getRecords: 'getRecords(%1)',
                selectByColumn: 'selectByColumn(%1, %2, %3)',
                selectByFunction: 'selectByFunction(%1, %2)',
                selectTopRows: 'selectTopRows(%1, %2)',
                getColumn: 'getColumn(%1, %2)',
                sortByColumn: 'sortByColumn(%1, %2, %3)',
                sortByFunction: 'sortByFunction(%1, %2)',
                selectColumns: 'selectColumns(%1, %2)',
                joinTables: 'joinTables(%1, %2, %3, %4, %5)',
                displayTable: 'displayTable(%1, %2)',
                updateWhere: 'updateWhere(%1, %2, %3)',
                insertRecord: 'insertRecord(%1, %2)',
                unionTables: 'unionTables(%1, %2)',
                displayRecord: 'displayRecord(%1)',
                displayTableOnMap: 'displayTableOnMap(%1, %2, %3, %4)'
            },
            code: {
                loadTable: 'loadTable',
                loadTableFromCsv: 'loadTableFromCsv',
                getRecords: 'getRecords',
                selectByColumn: 'selectByColumn',
                selectByFunction: 'selectByFunction',
                selectTopRows: 'selectTopRows',
                getColumnL: 'getColumn',
                sortByColumn: 'sortByColumn',
                sortByFunction: 'sortByFunction',
                selectColumns: 'selectColumns',
                joinTables: 'joinTables',
                displayTable: 'displayTable',
                updateWhere: 'updateWhere',
                insertRecord: 'insertRecord',
                unionTables: 'unionTables',
                displayRecord: 'displayRecord',
                displayTableOnMap: 'displayTableOnMap'
            },
            description: {
                loadTable: 'loadTable',
                loadTableFromCsv: 'loadTableFromCsv',
                getRecords: 'getRecords',
                selectByColumn: 'selectByColumn',
                selectByFunction: 'selectByFunction',
                selectTopRows: 'selectTopRows',
                getColumnL: 'getColumn',
                sortByColumn: 'sortByColumn',
                sortByFunction: 'sortByFunction',
                selectColumns: 'selectColumns',
                joinTables: 'joinTables',
                displayTable: 'displayTable',
                updateWhere: 'updateWhere',
                insertRecord: 'insertRecord',
                unionTables: 'unionTables',
                displayRecord: 'displayRecord',
                displayTableOnMap: 'displayTableOnMap'
            },
            startingBlockName: "Programme",
            constantLabel: {
                asc: 'asc',
                desc: 'desc',
                inner: 'inner',
                outer: 'outer',
                left: 'left',
                right: 'right'
            },
            messages: {
                table_not_found: 'Table non trouvée: ',
                incorrect_results: 'Résultats incorrects',
                some_results_missing: 'Il manque une partie des résultats'
            },
            ui: {
                'btn_files_repository': 'Ajouter des CSV...',
                'files_repository': {
                    'caption': 'Liste des fichiers CSV',
                    'hint': 'Utilisez le numéro de fichier comme paramètre de la fonction loadTableFromCsv. Seuls les fichiers CSV utilisant ; comme délimiteur sont acceptés.',
                    'add': 'Ajouter',
                    'incompatible_browser': 'Navigateur incompatible'
                }
            }
        }
    }

    var context = quickAlgoContext(display, infos)
    var strings = context.setLocalLanguageStrings(language_strings)
    var task_tables = {};
    var files, db_helper;
    var ready = false;

    context.reset = function(taskInfos) {
        if(!context.display || ready) return;
        ready = true;

        if(taskInfos) {
            task_tables = taskInfos.tables || {};
        }

        files = new FilesRepository({
            extensions: '.csv',
            parent: $('#taskContent'),
            strings: strings.ui.files_repository
        });

        db_helper = new DatabaseHelper(
            Object.assign({
                parent: $('#grid')
            }, infos.databaseConfig)
        );

        var html =
            '
' +
                '<button class="btn btn-xs" style="float: right" id="btn_files">' + strings.ui.btn_files_repository + '</button>' +
            '
';
        $('#testSelector').prepend($(html))
        $('#btn_files').click(function() {
            files.show();
        })

/*
        //test html render
        setTimeout(function() {
            context.database.loadTable('test_table', function(table, callback) {
                context.database.displayTable(table, null, function() {
                    context.expectTable('valid_table')
                });
            })
        }, 1500);
*/
/*
        //test map render
        setTimeout(function() {
            context.database.loadTable('test_table2', function(table, callback) {
                context.database.displayTableOnMap(table, 'city', 'lng', 'lat', function() {
                    context.expectTable('valid_table2');
                });

            })
        }, 500)
*/

    }

    context.setScale = function(scale) {}
    context.updateScale = function() {}
    context.resetDisplay = function() {}
    context.unload = function() {}

    context.expectTable = function(name) {
        if(name in task_tables) {
            var table = Table(task_tables[name]);
            var status = db_helper.validateResult(table);
            if(status === true) {
                context.success = true;
                return;
            }
            context.success = false;
            throw new Error(strings.messages[status]);
        } else {
            context.success = false;
            console.error('Table not found: ' + name)
        }
    }

    context.database = {

        loadTable: function(name, callback) {
            if(!task_tables[name]) throw new Error(strings.messages.table_not_found + name);
            context.waitDelay(callback, Table(task_tables[name]));
        },

        loadTableFromCsv: function(fileNumber, types, callback) {
            var file = files.getFile(fileNumber - 1);
            var types_arr = Array.from(types);
            db_helper.loadCsv(file, types_arr, function(table) {
                context.waitDelay(callback, table);
            });
        },

        getRecords: function(table, callback) {
            context.waitDelay(callback, table.getRecords());
        },

        selectByColumn: function(table, columnName, value, callback) {
            context.waitDelay(callback, table.selectByColumn(columnName, value));
        },

        selectByFunction: function(table, filterFunction, callback) {
            context.waitDelay(callback, table.selectByFunction(filterFunction));
        },

        selectTopRows: function(table, amount, callback) {
            context.waitDelay(callback, table.selectTopRows(amount));
        },

        getColumn: function(record, columnName, callback) {
            if(columnName in record) {
                context.waitDelay(callback, record[columnName]);
            } else {
                throw new Error('Column ' + columnName + ' not found');
            }
        },

        sortByColumn: function(table, columnName, direction, callback) {
            context.waitDelay(callback, table.sortByColumn(columnName, direction));
        },

        sortByFunction: function(table, compareFunction, callback) {
            context.waitDelay(callback, table.sortByFunction(compareFunction));
        },

        selectColumns: function(table, columns, callback) {
            context.waitDelay(callback, table.selectColumns(columns));
        },

        joinTables: function(table1, column1, table2, column2, type, callback) {
            context.waitDelay(callback, table1.join(column1, table2, column2, type));
        },

        displayTable: function(table, columns, callback) {
            if(columns) {
                db_helper.displayTable(
                    table.selectColumns(Array.from(columns))
                )
            } else {
                db_helper.displayTable(table);
            }
            context.waitDelay(callback);
        },

        updateWhere: function(table, filterFunction, updateFunction, callback) {
            context.waitDelay(callback, table.updateWhere(filterFunction, updateFunction));
        },

        insertRecord: function(table, record, callback) {
            context.waitDelay(callback, table.insertRecord(record));
        },

        unionTables: function(table1, table2, callback) {
            context.waitDelay(callback, table1.union(table2));
        },

        displayRecord: function(record, callback) {
            var res = {
                columnNames: Object.keys(record),
                records: [
                    Object.values(record),
                ]
            }
            res.columnTypes = Array.apply(null, Array(res.records[0].length)).map(function() {
                return 'string';
            })
            var table = Table(res)
            db_helper.displayTable(table);
            context.waitDelay(callback);
        },

        displayTableOnMap: function(table, nameColumn, longitudeColumn, latitudeColumn, callback) {
            db_helper.displayTableOnMap(
                table.selectColumns([nameColumn, longitudeColumn, latitudeColumn]),
            );
            context.waitDelay(callback);
        }
    }

    context.customBlocks = {
        database: {
            database: [
                { name: 'loadTable',
                    params: ['String'],
                    params_names: ['table_name'],
                    yieldsValue: true
                },
                { name: 'loadTableFromCsv',
                    params: ['String', 'Block'],
                    params_names: ['file', 'columnTypes'],
                    yieldsValue: true
                },
                { name: 'getRecords',
                    params: ['Block'],
                    params_names: ['table'],
                    yieldsValue: true
                },
                { name: 'selectByColumn',
                    params: ['Block', 'String', 'String'],
                    params_names: ['table', 'columnName', 'value'],
                    yieldsValue: true
                },
                { name: 'selectByFunction',
                    params: ['Block', 'String'],
                    params_names: ['table', 'filterFunction'],
                    yieldsValue: true
                },
                { name: 'selectTopRows',
                    params: ['Block', 'Number'],
                    params_names: ['table', 'amount'],
                    yieldsValue: true
                },
                { name: 'getColumn',
                    params: ['String', 'String'],
                    params_names: ['record', 'columnName'],
                    yieldsValue: true
                },
                { name: 'sortByColumn',
                    params: ['Block', 'String', 'SortOrder'],
                    params_names: ['table', 'columnName', 'direction'],
                    yieldsValue: true
                },
                { name: 'sortByFunction',
                    params: ['Block', 'String'],
                    params_names: ['table', 'compareFunction'],
                    yieldsValue: true
                },
                { name: 'selectColumns',
                    params: ['Block', 'String'],
                    params_names: ['table', 'columns'],
                    yieldsValue: true
                },
                { name: 'joinTables',
                    params: ['Block', 'String', 'Block', 'String', 'JoinType'],
                    params_names: ['table', 'columnName', 'table', 'columnName', 'type'],
                    yieldsValue: true
                },
                { name: 'updateWhere',
                    params: ['Block', 'String', 'String'],
                    params_names: ['table', 'filterFunction', 'updateFunction'],
                    yieldsValue: true
                },
                { name: 'insertRecord',
                    params: ['Block', 'String'],
                    params_names: ['table', 'record'],
                    yieldsValue: true
                },
                { name: 'unionTables',
                    params: ['Block', 'Block'],
                    params_names: ['table', 'table'],
                    yieldsValue: true
                },
                { name: 'displayTable',
                    params: ['Block', 'Block'],
                    params_names: ['table', 'columns'],
                },
                { name: 'displayRecord',
                    params: ['Block'],
                    params_names: ['record']
                },
                { name: 'displayTableOnMap',
                    params: ['Block', 'String','String', 'String'],
                    params_names: ['table', 'nameColumn', 'longitudeColumn', 'latitudeColumn'],
                }
            ]
        }
    }

    var typeData = {
        'Number': { bType: 'input_value', vType: 'math_number', fName: 'NUM', defVal: 0 },
        'String': { bType: 'input_value', vType: 'text', fName: 'TEXT', defVal: '' },
        'Block': { bType: 'input_value', fName: 'BLOCK', defVal: '' },
        'SortOrder': { bType: 'field_dropdown', defVal: 'asc', options: [
            [strings.constantLabel.asc, 'asc'],
            [strings.constantLabel.desc, 'desc']
        ]},
        'JoinType': { bType: 'field_dropdown', defVal: 'inner', options: [
            [strings.constantLabel.inner, 'inner'],
            [strings.constantLabel.outer, 'outer'],
            [strings.constantLabel.left, 'left'],
            [strings.constantLabel.right, 'right']
        ]}
    }

    BlocksHelper.convertBlocks(context, 'database', typeData);

    return context;
}

if(window.quickAlgoLibraries) {
    quickAlgoLibraries.register('database', getContext);
} else {
    if(!window.quickAlgoLibrariesList) { window.quickAlgoLibrariesList = []; }
    window.quickAlgoLibrariesList.push(['database', getContext]);
}
<commit_msg>database: Fix descriptions<commit_after>var getContext = function(display, infos) {

    var language_strings = {
        en: {
            categories: {
                database: 'Database'
            },
            label: {
                loadTable: 'loadTable(%1)',
                loadTableFromCsv: 'loadTableFromCsv(%1, %2)',
                getRecords: 'getRecords(%1)',
                selectByColumn: 'selectByColumn(%1, %2, %3)',
                selectByFunction: 'selectByFunction(%1, %2)',
                selectTopRows: 'selectTopRows(%1, %2)',
                getColumn: 'getColumn(%1, %2)',
                sortByColumn: 'sortByColumn(%1, %2, %3)',
                sortByFunction: 'sortByFunction(%1, %2)',
                selectColumns: 'selectColumns(%1, %2)',
                joinTables: 'joinTables(%1, %2, %3, %4, %5)',
                displayTable: 'displayTable(%1, %2)',
                updateWhere: 'updateWhere(%1, %2, %3)',
                insertRecord: 'insertRecord(%1, %2)',
                unionTables: 'unionTables(%1, %2)',
                displayRecord: 'displayRecord(%1)',
                displayTableOnMap: 'displayTableOnMap(%1, %2, %3, %4)'
            },
            code: {
                loadTable: 'loadTable',
                loadTableFromCsv: 'loadTableFromCsv',
                getRecords: 'getRecords',
                selectByColumn: 'selectByColumn',
                selectByFunction: 'selectByFunction',
                selectTopRows: 'selectTopRows',
                getColumnL: 'getColumn',
                sortByColumn: 'sortByColumn',
                sortByFunction: 'sortByFunction',
                selectColumns: 'selectColumns',
                joinTables: 'joinTables',
                displayTable: 'displayTable',
                updateWhere: 'updateWhere',
                insertRecord: 'insertRecord',
                unionTables: 'unionTables',
                displayRecord: 'displayRecord',
                displayTableOnMap: 'displayTableOnMap'
            },
            description: {
/*                loadTable: 'loadTable()',
                loadTableFromCsv: 'loadTableFromCsv()',
                getRecords: 'getRecords()',
                selectByColumn: 'selectByColumn()',
                selectByFunction: 'selectByFunction()',
                selectTopRows: 'selectTopRows()',
                getColumnL: 'getColumn()',
                sortByColumn: 'sortByColumn()',
                sortByFunction: 'sortByFunction()',
                selectColumns: 'selectColumns()',
                joinTables: 'joinTables()',
                displayTable: 'displayTable()',
                updateWhere: 'updateWhere()',
                insertRecord: 'insertRecord()',
                unionTables: 'unionTables()',
                displayRecord: 'displayRecord()',
                displayTableOnMap: 'displayTableOnMap()'
*/
            },
            startingBlockName: "Programme",
            constantLabel: {
                asc: 'asc',
                desc: 'desc',
                inner: 'inner',
                outer: 'outer',
                left: 'left',
                right: 'right'
            },
            messages: {
                table_not_found: 'Table not found: ',
                incorrect_results: 'Incorrect results',
                some_results_missing: 'Some results are missing'
            },
            ui: {
                'btn_files_repository': 'Add CSV files...',
                'files_repository': {
                    'caption': 'CSV files list',
                    'hint': 'Use file number as param for loadTableFromCsv function. Allowed CSV files with ; delimiter only.',
                    'add': 'Add',
                    'incompatible_browser': 'Incompatible browser'
                }
            }
        },
        fr: {
            categories: {
                database: 'Base de données'
            },
            label: {
                loadTable: 'loadTable(%1)',
                loadTableFromCsv: 'loadTableFromCsv(%1, %2)',
                getRecords: 'getRecords(%1)',
                selectByColumn: 'selectByColumn(%1, %2, %3)',
                selectByFunction: 'selectByFunction(%1, %2)',
                selectTopRows: 'selectTopRows(%1, %2)',
                getColumn: 'getColumn(%1, %2)',
                sortByColumn: 'sortByColumn(%1, %2, %3)',
                sortByFunction: 'sortByFunction(%1, %2)',
                selectColumns: 'selectColumns(%1, %2)',
                joinTables: 'joinTables(%1, %2, %3, %4, %5)',
                displayTable: 'displayTable(%1, %2)',
                updateWhere: 'updateWhere(%1, %2, %3)',
                insertRecord: 'insertRecord(%1, %2)',
                unionTables: 'unionTables(%1, %2)',
                displayRecord: 'displayRecord(%1)',
                displayTableOnMap: 'displayTableOnMap(%1, %2, %3, %4)'
            },
            code: {
                loadTable: 'loadTable',
                loadTableFromCsv: 'loadTableFromCsv',
                getRecords: 'getRecords',
                selectByColumn: 'selectByColumn',
                selectByFunction: 'selectByFunction',
                selectTopRows: 'selectTopRows',
                getColumnL: 'getColumn',
                sortByColumn: 'sortByColumn',
                sortByFunction: 'sortByFunction',
                selectColumns: 'selectColumns',
                joinTables: 'joinTables',
                displayTable: 'displayTable',
                updateWhere: 'updateWhere',
                insertRecord: 'insertRecord',
                unionTables: 'unionTables',
                displayRecord: 'displayRecord',
                displayTableOnMap: 'displayTableOnMap'
            },
            description: {
/*                loadTable: 'loadTable()',
                loadTableFromCsv: 'loadTableFromCsv()',
                getRecords: 'getRecords()',
                selectByColumn: 'selectByColumn()',
                selectByFunction: 'selectByFunction()',
                selectTopRows: 'selectTopRows()',
                getColumnL: 'getColumn()',
                sortByColumn: 'sortByColumn()',
                sortByFunction: 'sortByFunction()',
                selectColumns: 'selectColumns()',
                joinTables: 'joinTables()',
                displayTable: 'displayTable()',
                updateWhere: 'updateWhere()',
                insertRecord: 'insertRecord()',
                unionTables: 'unionTables()',
                displayRecord: 'displayRecord()',
                displayTableOnMap: 'displayTableOnMap()'
*/
            },
            startingBlockName: "Programme",
            constantLabel: {
                asc: 'asc',
                desc: 'desc',
                inner: 'inner',
                outer: 'outer',
                left: 'left',
                right: 'right'
            },
            messages: {
                table_not_found: 'Table non trouvée: ',
                incorrect_results: 'Résultats incorrects',
                some_results_missing: 'Il manque une partie des résultats'
            },
            ui: {
                'btn_files_repository': 'Ajouter des CSV...',
                'files_repository': {
                    'caption': 'Liste des fichiers CSV',
                    'hint': 'Utilisez le numéro de fichier comme paramètre de la fonction loadTableFromCsv. Seuls les fichiers CSV utilisant ; comme délimiteur sont acceptés.',
                    'add': 'Ajouter',
                    'incompatible_browser': 'Navigateur incompatible'
                }
            }
        }
    }

    var context = quickAlgoContext(display, infos)
    var strings = context.setLocalLanguageStrings(language_strings)
    var task_tables = {};
    var files, db_helper;
    var ready = false;

    context.reset = function(taskInfos) {
        if(!context.display || ready) return;
        ready = true;

        if(taskInfos) {
            task_tables = taskInfos.tables || {};
        }

        files = new FilesRepository({
            extensions: '.csv',
            parent: $('#taskContent'),
            strings: strings.ui.files_repository
        });

        db_helper = new DatabaseHelper(
            Object.assign({
                parent: $('#grid')
            }, infos.databaseConfig)
        );

        var html =
            '
' +
                '<button class="btn btn-xs" style="float: right" id="btn_files">' + strings.ui.btn_files_repository + '</button>' +
            '
';
        $('#testSelector').prepend($(html))
        $('#btn_files').click(function() {
            files.show();
        })

/*
        //test html render
        setTimeout(function() {
            context.database.loadTable('test_table', function(table, callback) {
                context.database.displayTable(table, null, function() {
                    context.expectTable('valid_table')
                });
            })
        }, 1500);
*/
/*
        //test map render
        setTimeout(function() {
            context.database.loadTable('test_table2', function(table, callback) {
                context.database.displayTableOnMap(table, 'city', 'lng', 'lat', function() {
                    context.expectTable('valid_table2');
                });

            })
        }, 500)
*/

    }

    context.setScale = function(scale) {}
    context.updateScale = function() {}
    context.resetDisplay = function() {}
    context.unload = function() {}

    context.expectTable = function(name) {
        if(name in task_tables) {
            var table = Table(task_tables[name]);
            var status = db_helper.validateResult(table);
            if(status === true) {
                context.success = true;
                return;
            }
            context.success = false;
            throw new Error(strings.messages[status]);
        } else {
            context.success = false;
            console.error('Table not found: ' + name)
        }
    }

    context.database = {

        loadTable: function(name, callback) {
            if(!task_tables[name]) throw new Error(strings.messages.table_not_found + name);
            context.waitDelay(callback, Table(task_tables[name]));
        },

        loadTableFromCsv: function(fileNumber, types, callback) {
            var file = files.getFile(fileNumber - 1);
            var types_arr = Array.from(types);
            db_helper.loadCsv(file, types_arr, function(table) {
                context.waitDelay(callback, table);
            });
        },

        getRecords: function(table, callback) {
            context.waitDelay(callback, table.getRecords());
        },

        selectByColumn: function(table, columnName, value, callback) {
            context.waitDelay(callback, table.selectByColumn(columnName, value));
        },

        selectByFunction: function(table, filterFunction, callback) {
            context.waitDelay(callback, table.selectByFunction(filterFunction));
        },

        selectTopRows: function(table, amount, callback) {
            context.waitDelay(callback, table.selectTopRows(amount));
        },

        getColumn: function(record, columnName, callback) {
            if(columnName in record) {
                context.waitDelay(callback, record[columnName]);
            } else {
                throw new Error('Column ' + columnName + ' not found');
            }
        },

        sortByColumn: function(table, columnName, direction, callback) {
            context.waitDelay(callback, table.sortByColumn(columnName, direction));
        },

        sortByFunction: function(table, compareFunction, callback) {
            context.waitDelay(callback, table.sortByFunction(compareFunction));
        },

        selectColumns: function(table, columns, callback) {
            context.waitDelay(callback, table.selectColumns(columns));
        },

        joinTables: function(table1, column1, table2, column2, type, callback) {
            context.waitDelay(callback, table1.join(column1, table2, column2, type));
        },

        displayTable: function(table, columns, callback) {
            if(columns) {
                db_helper.displayTable(
                    table.selectColumns(Array.from(columns))
                )
            } else {
                db_helper.displayTable(table);
            }
            context.waitDelay(callback);
        },

        updateWhere: function(table, filterFunction, updateFunction, callback) {
            context.waitDelay(callback, table.updateWhere(filterFunction, updateFunction));
        },

        insertRecord: function(table, record, callback) {
            context.waitDelay(callback, table.insertRecord(record));
        },

        unionTables: function(table1, table2, callback) {
            context.waitDelay(callback, table1.union(table2));
        },

        displayRecord: function(record, callback) {
            var res = {
                columnNames: Object.keys(record),
                records: [
                    Object.values(record),
                ]
            }
            res.columnTypes = Array.apply(null, Array(res.records[0].length)).map(function() {
                return 'string';
            })
            var table = Table(res)
            db_helper.displayTable(table);
            context.waitDelay(callback);
        },

        displayTableOnMap: function(table, nameColumn, longitudeColumn, latitudeColumn, callback) {
            db_helper.displayTableOnMap(
                table.selectColumns([nameColumn, longitudeColumn, latitudeColumn]),
            );
            context.waitDelay(callback);
        }
    }

    context.customBlocks = {
        database: {
            database: [
                { name: 'loadTable',
                    params: ['String'],
                    params_names: ['table_name'],
                    yieldsValue: true
                },
                { name: 'loadTableFromCsv',
                    params: ['String', 'Block'],
                    params_names: ['file', 'columnTypes'],
                    yieldsValue: true
                },
                { name: 'getRecords',
                    params: ['Block'],
                    params_names: ['table'],
                    yieldsValue: true
                },
                { name: 'selectByColumn',
                    params: ['Block', 'String', 'String'],
                    params_names: ['table', 'columnName', 'value'],
                    yieldsValue: true
                },
                { name: 'selectByFunction',
                    params: ['Block', 'String'],
                    params_names: ['table', 'filterFunction'],
                    yieldsValue: true
                },
                { name: 'selectTopRows',
                    params: ['Block', 'Number'],
                    params_names: ['table', 'amount'],
                    yieldsValue: true
                },
                { name: 'getColumn',
                    params: ['String', 'String'],
                    params_names: ['record', 'columnName'],
                    yieldsValue: true
                },
                { name: 'sortByColumn',
                    params: ['Block', 'String', 'SortOrder'],
                    params_names: ['table', 'columnName', 'direction'],
                    yieldsValue: true
                },
                { name: 'sortByFunction',
                    params: ['Block', 'String'],
                    params_names: ['table', 'compareFunction'],
                    yieldsValue: true
                },
                { name: 'selectColumns',
                    params: ['Block', 'String'],
                    params_names: ['table', 'columns'],
                    yieldsValue: true
                },
                { name: 'joinTables',
                    params: ['Block', 'String', 'Block', 'String', 'JoinType'],
                    params_names: ['table', 'columnName', 'table', 'columnName', 'type'],
                    yieldsValue: true
                },
                { name: 'updateWhere',
                    params: ['Block', 'String', 'String'],
                    params_names: ['table', 'filterFunction', 'updateFunction'],
                    yieldsValue: true
                },
                { name: 'insertRecord',
                    params: ['Block', 'String'],
                    params_names: ['table', 'record'],
                    yieldsValue: true
                },
                { name: 'unionTables',
                    params: ['Block', 'Block'],
                    params_names: ['table', 'table'],
                    yieldsValue: true
                },
                { name: 'displayTable',
                    params: ['Block', 'Block'],
                    params_names: ['table', 'columns'],
                },
                { name: 'displayRecord',
                    params: ['Block'],
                    params_names: ['record']
                },
                { name: 'displayTableOnMap',
                    params: ['Block', 'String','String', 'String'],
                    params_names: ['table', 'nameColumn', 'longitudeColumn', 'latitudeColumn'],
                }
            ]
        }
    }

    var typeData = {
        'Number': { bType: 'input_value', vType: 'math_number', fName: 'NUM', defVal: 0 },
        'String': { bType: 'input_value', vType: 'text', fName: 'TEXT', defVal: '' },
        'Block': { bType: 'input_value', fName: 'BLOCK', defVal: '' },
        'SortOrder': { bType: 'field_dropdown', defVal: 'asc', options: [
            [strings.constantLabel.asc, 'asc'],
            [strings.constantLabel.desc, 'desc']
        ]},
        'JoinType': { bType: 'field_dropdown', defVal: 'inner', options: [
            [strings.constantLabel.inner, 'inner'],
            [strings.constantLabel.outer, 'outer'],
            [strings.constantLabel.left, 'left'],
            [strings.constantLabel.right, 'right']
        ]}
    }

    BlocksHelper.convertBlocks(context, 'database', typeData);

    return context;
}

if(window.quickAlgoLibraries) {
    quickAlgoLibraries.register('database', getContext);
} else {
    if(!window.quickAlgoLibrariesList) { window.quickAlgoLibrariesList = []; }
    window.quickAlgoLibrariesList.push(['database', getContext]);
}
<|endoftext|>


<commit_before>'use strict';
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2015-2016 ArangoDB GmbH, Cologne, Germany
///
/// 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
///
///     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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Alan Plum
////////////////////////////////////////////////////////////////////////////////

const _ = require('lodash');
const joi = require('joi');
const assert = require('assert');
const mimeTypes = require('mime-types');
const mediaTyper = require('media-typer');
const joiToJsonSchema = require('joi-to-json-schema');
const tokenize = require('@arangodb/foxx/router/tokenize');

const MIME_JSON = 'application/json; charset=utf-8';
const MIME_BINARY = 'application/octet-stream';
const DEFAULT_BODY_SCHEMA = joi.object().optional().meta({allowInvalid: true});
const DEFAULT_ERROR_SCHEMA = joi.object().keys({
  error: joi.allow(true).required(),
  errorNum: joi.number().integer().optional(),
  errorMessage: joi.string().optional(),
  code: joi.number().integer().optional()
});

module.exports = exports = class SwaggerContext {
  constructor(path) {
    if (!path) {
      path = '';
    }
    {
      const n = path.length - 1;
      if (path.charAt(n) === '/') {
        path = path.slice(0, n);
      }
      if (path.charAt(0) !== '/') {
        path = `/${path}`;
      }
    }
    this._headers = new Map();
    this._queryParams = new Map();
    this._bodyParam = null;
    this._responses = new Map();
    this._summary = null;
    this._description = null;
    this._deprecated = false;
    this.path = path;
    this._pathParams = new Map();
    this._pathParamNames = [];
    this._pathTokens = tokenize(path, this);
  }

  header(name, schema, description) {
    this._headers.set(name, {schema: schema, description: description});
    return this;
  }

  pathParam(name, schema, description) {
    this._pathParams.set(name, {schema: schema, description: description});
    return this;
  }

  queryParam(name, schema, description) {
    this._queryParams.set(name, {schema: schema, description: description});
    return this;
  }

  body(model, mimes, description) {
    if (
      typeof model === 'string'
      || (Array.isArray(model) && typeof model[0] === 'string')
    ) {
      description = mimes;
      mimes = model;
      model = undefined;
    }

    if (typeof mimes === 'string') {
      description = mimes;
      mimes = undefined;
    }

    let multiple = false;
    if (Array.isArray(model)) {
      if (model.length !== 1) {
        throw new Error(
          'Model must be a model or schema'
          + ' or an array containing exactly one model or schema.'
          + ' If you are trying to use multiple schemas'
          + ' try using joi.alternatives.'
        );
      }
      model = model[0];
      multiple = true;
    }

    if (!mimes) {
      mimes = [];
    }

    if (!mimes.length && model) {
      mimes.push(MIME_JSON);
    }

    const contentTypes = mimes.map(function (mime) {
      if (mime === 'binary') {
        mime = MIME_BINARY;
      }
      const contentType = mimeTypes.contentType(mime) || mime;
      const parsed = mediaTyper.parse(contentType);
      return mediaTyper.format(_.pick(parsed, [
        'type',
        'subtype',
        'suffix'
      ]));
    });

    if (model) {
      if (model.isJoi) {
        model = {schema: model};
      } else {
        model = _.clone(model);
      }
      if (model.schema && !model.schema.isJoi) {
        model.schema = joi.object(model.schema).required();
      }
      assert(
        !model.forClient || typeof model.forClient === 'function',
        `Request body model forClient handler must be a function, not ${typeof model.forClient}`
      );
      assert(
        !model.fromClient || typeof model.fromClient === 'function',
        `Request body model fromClient handler must be a function, not ${typeof model.fromClient}`
      );
      if (!model.forClient && typeof model.toClient === 'function') {
        console.log(
          `Found unexpected "toClient" method on request body model.`
          + ' Did you mean "forClient"?'
        );
      }
    }

    this._bodyParam = {
      model: model,
      multiple: multiple,
      contentTypes: contentTypes,
      description: description
    };
    return this;
  }

  response(status, model, mimes, description) {
    let statusCode = Number(status);
    if (!status || Number.isNaN(statusCode)) {
      description = mimes;
      mimes = model;
      model = status;
      statusCode = 200;
    }

    if (model === null) {
      if (statusCode === 200) {
        this._responses.delete(200);
        statusCode = 204;
      }
    }

    if (
      typeof model === 'string'
      || (Array.isArray(model) && typeof model[0] === 'string')
    ) {
      description = mimes;
      mimes = model;
      model = undefined;
    }

    if (typeof mimes === 'string') {
      description = mimes;
      mimes = undefined;
    }

    let multiple = false;
    if (Array.isArray(model)) {
      if (model.length !== 1) {
        throw new Error(
          'Model must be a model or schema'
          + ' or an array containing exactly one model or schema.'
          + ' If you are trying to use multiple schemas'
          + ' try using joi.alternatives.'
        );
      }
      model = model[0];
      multiple = true;
    }

    if (!mimes) {
      mimes = [];
    }

    if (!mimes.length && model) {
      mimes.push(MIME_JSON);
    }

    const contentTypes = mimes.map(function (mime) {
      if (mime === 'binary') {
        mime = MIME_BINARY;
      }
      const contentType = mimeTypes.contentType(mime) || mime;
      const parsed = mediaTyper.parse(contentType);
      return mediaTyper.format(_.pick(parsed, [
        'type',
        'subtype',
        'suffix'
      ]));
    });

    if (model) {
      if (model.isJoi) {
        model = {schema: model};
      } else {
        model = _.clone(model);
      }
      if (model.schema && !model.schema.isJoi) {
        model.schema = joi.object(model.schema).required();
      }
      assert(
        !model.forClient || typeof model.forClient === 'function',
        `Response body model forClient handler at ${statusCode} must be a function, not ${typeof model.forClient}`
      );
      assert(
        !model.fromClient || typeof model.fromClient === 'function',
        `Response body model fromClient handler at ${statusCode} must be a function, not ${typeof model.fromClient}`
      );
      if (!model.forClient && typeof model.toClient === 'function') {
        console.log(
          `Found unexpected "toClient" method on response body model at ${statusCode}.`
          + ' Did you mean "forClient"?'
        );
      }
    }

    this._responses.set(statusCode, {
      model: model,
      multiple: multiple,
      contentTypes: contentTypes,
      description: description
    });
    return this;
  }

  error(status, description) {
    return this.response(
      status,
      DEFAULT_ERROR_SCHEMA,
      null,
      description
    );
  }

  summary(text) {
    this._summary = text;
    return this;
  }

  description(text) {
    this._description = text;
    return this;
  }

  deprecated(flag) {
    this._deprecated = typeof flag === 'boolean' ? flag : true;
    return this;
  }

  _merge(swaggerObj, pathOnly) {
    if (!pathOnly) {
      for (const header of swaggerObj._headers.entries()) {
        this._headers.set(header[0], header[1]);
      }
      for (const queryParam of swaggerObj._queryParams.entries()) {
        this._queryParams.set(queryParam[0], queryParam[1]);
      }
      for (const response of swaggerObj._responses.entries()) {
        this._responses.set(response[0], response[1]);
      }
      if (swaggerObj._bodyParam) {
        if (!this._bodyParam || swaggerObj._bodyParam.type !== DEFAULT_BODY_SCHEMA) {
          this._bodyParam = swaggerObj._bodyParam;
        }
      }
      this._deprecated = swaggerObj._deprecated || this._deprecated;
      this._description = swaggerObj._description || this._description;
      this._summary = swaggerObj._summary || this._summary;
    }
    if (this.path.charAt(this.path.length - 1) === '*') {
      this.path = this.path.slice(0, this.path.length - 1);
    }
    if (this.path.charAt(this.path.length - 1) === '/') {
      this.path = this.path.slice(0, this.path.length - 1);
    }
    this._pathTokens.pop();
    this._pathTokens = this._pathTokens.concat(swaggerObj._pathTokens);
    for (const pathParam of swaggerObj._pathParams.entries()) {
      let name = pathParam[0];
      const def = pathParam[1];
      if (this._pathParams.has(name)) {
        let baseName = name;
        let i = 2;
        const match = name.match(/(^.+)([0-9]+)$/i);
        if (match) {
          baseName = match[1];
          i = Number(match[2]);
        }
        while (this._pathParams.has(baseName + i)) {
          i++;
        }
        name = baseName + i;
      }
      this._pathParams.set(name, def);
      this._pathParamNames.push(name);
    }
    this.path = tokenize.reverse(this._pathTokens, this._pathParamNames);
  }

  _buildOperation() {
    const operation = {
      produces: [],
      parameters: []
    };
    if (this._deprecated) {
      operation.deprecated = this._deprecated;
    }
    if (this._description) {
      operation.description = this._description;
    }
    if (this._summary) {
      operation.summary = this._summary;
    }
    if (this._bodyParam) {
      operation.consumes = (
        this._bodyParam.contentTypes
        ? this._bodyParam.contentTypes.slice()
        : []
      );
    }
    for (const response of this._responses.values()) {
      if (!response.contentTypes) {
        continue;
      }
      for (const contentType of response.contentTypes) {
        if (operation.produces.indexOf(contentType) === -1) {
          operation.produces.push(contentType);
        }
      }
    }
    if (operation.produces.indexOf('application/json') === -1) {
      // ArangoDB errors use 'application/json'
      operation.produces.push('application/json');
    }

    for (const param of this._pathParams.entries()) {
      const name = param[0];
      const def = param[1];
      const parameter = (
        def.schema
        ? swaggerifyParam(def.schema.isJoi ? def.schema : joi.object(def.schema))
        : {type: 'string'}
      );
      parameter.name = name;
      parameter.in = 'path';
      parameter.required = true;
      if (def.description) {
        parameter.description = def.description;
      }
      operation.parameters.push(parameter);
    }

    for (const param of this._queryParams.entries()) {
      const name = param[0];
      const def = param[1];
      const parameter = (
        def.schema
        ? swaggerifyParam(def.schema.isJoi ? def.schema : joi.object(def.schema))
        : {type: 'string'}
      );
      parameter.name = name;
      parameter.in = 'query';
      if (def.description) {
        parameter.description = def.description;
      }
      operation.parameters.push(parameter);
    }

    for (const param of this._headers.entries()) {
      const name = param[0];
      const def = param[1];
      const parameter = (
        def.schema
        ? swaggerifyParam(def.schema.isJoi ? def.schema : joi.object(def.schema))
        : {type: 'string'}
      );
      parameter.name = name;
      parameter.in = 'header';
      if (def.description) {
        parameter.description = def.description;
      }
      operation.parameters.push(parameter);
    }

    if (this._bodyParam && this._bodyParam.contentTypes) {
      const def = this._bodyParam;
      const schema = (
        def.model
        ? (def.model.isJoi ? def.model : def.model.schema)
        : null
      );
      const parameter = (
        schema
        ? swaggerifyBody(schema, def.multiple)
        : {schema: {type: 'string'}}
      );
      parameter.name = 'body';
      parameter.in = 'body';
      if (def.description) {
        parameter.description = def.description;
      }
      operation.parameters.push(parameter);
    }

    operation.responses = {
      default: {
        description: 'Unexpected error',
        schema: joi2schema(DEFAULT_ERROR_SCHEMA)
      }
    };

    for (const entry of this._responses.entries()) {
      const code = entry[0];
      const def = entry[1];
      const schema = (
        def.model
        ? (def.model.isJoi ? def.model : def.model.schema)
        : null
      );
      const response = {};
      if (def.contentTypes) {
        response.schema = (
          schema
          ? joi2schema(schema.isJoi ? schema : joi.object(schema), def.multiple)
          : {type: 'string'}
        );
      }
      if (schema && schema._description) {
        response.description = schema._description;
      }
      if (def.description) {
        response.description = def.description;
      }
      if (!response.description) {
        response.description = `The ${code} response body.`;
      }
      operation.responses[code] = response;
    }

    return operation;
  }
};

exports.DEFAULT_BODY_SCHEMA = DEFAULT_BODY_SCHEMA;

function swaggerifyType(joi) {
  switch (joi._type) {
    default:
      return ['string'];
    case 'binary':
      return ['string', 'binary'];
    case 'boolean':
      return ['boolean'];
    case 'date':
      return ['string', 'date-time'];
    case 'func':
      return ['string'];
    case 'number':
      if (joi._tests.some(function (test) {
        return test.name === 'integer';
      })) {
        return ['integer'];
      }
      return ['number'];
    case 'array':
      return ['array'];
    case 'object':
      return ['object'];
    case 'string':
      if (joi._meta.some(function (meta) {
        return meta.secret;
      })) {
        return ['string', 'password'];
      }
      return ['string'];
  }
}

function swaggerifyParam(joi) {
  const param = {
    required: joi._presence === 'required',
    description: joi._description
  };
  let item = param;
  if (joi._meta.some(function (meta) {
    return meta.allowMultiple;
  })) {
    param.type = 'array';
    param.collectionFormat = 'multi';
    param.items = {};
    item = param.items;
  }
  const type = swaggerifyType(joi);
  item.type = type[0];
  if (type.length > 1) {
    item.format = type[1];
  }
  if (joi._valids._set && joi._valids._set.length) {
    item.enum = joi._valids._set;
  }
  if (joi._flags.hasOwnProperty('default')) {
    item.default = joi._flags.default;
  }
  return param;
}

function swaggerifyBody(joi, multiple) {
  return {
    required: joi._presence === 'required',
    description: joi._description,
    schema: joi2schema(joi, multiple)
  };
}

function joi2schema(schema, multiple) {
  if (multiple) {
    schema = joi.array().items(schema);
  }
  return joiToJsonSchema(schema);
}
<commit_msg>Fix swagger responses<commit_after>'use strict';
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2015-2016 ArangoDB GmbH, Cologne, Germany
///
/// 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
///
///     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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Alan Plum
////////////////////////////////////////////////////////////////////////////////

const _ = require('lodash');
const joi = require('joi');
const assert = require('assert');
const mimeTypes = require('mime-types');
const mediaTyper = require('media-typer');
const joiToJsonSchema = require('joi-to-json-schema');
const tokenize = require('@arangodb/foxx/router/tokenize');

const MIME_JSON = 'application/json; charset=utf-8';
const MIME_BINARY = 'application/octet-stream';
const DEFAULT_BODY_SCHEMA = joi.object().unknown().meta({allowInvalid: true}).optional();
const DEFAULT_ERROR_SCHEMA = joi.object().keys({
  error: joi.allow(true).required(),
  errorNum: joi.number().integer().optional(),
  errorMessage: joi.string().optional(),
  code: joi.number().integer().optional()
});

module.exports = exports = class SwaggerContext {
  constructor(path) {
    if (!path) {
      path = '';
    }
    {
      const n = path.length - 1;
      if (path.charAt(n) === '/') {
        path = path.slice(0, n);
      }
      if (path.charAt(0) !== '/') {
        path = `/${path}`;
      }
    }
    this._headers = new Map();
    this._queryParams = new Map();
    this._bodyParam = null;
    this._responses = new Map();
    this._summary = null;
    this._description = null;
    this._deprecated = false;
    this.path = path;
    this._pathParams = new Map();
    this._pathParamNames = [];
    this._pathTokens = tokenize(path, this);
  }

  header(name, schema, description) {
    this._headers.set(name, {schema: schema, description: description});
    return this;
  }

  pathParam(name, schema, description) {
    this._pathParams.set(name, {schema: schema, description: description});
    return this;
  }

  queryParam(name, schema, description) {
    this._queryParams.set(name, {schema: schema, description: description});
    return this;
  }

  body(model, mimes, description) {
    if (
      typeof model === 'string'
      || (Array.isArray(model) && typeof model[0] === 'string')
    ) {
      description = mimes;
      mimes = model;
      model = undefined;
    }

    if (typeof mimes === 'string') {
      description = mimes;
      mimes = undefined;
    }

    let multiple = false;
    if (Array.isArray(model)) {
      if (model.length !== 1) {
        throw new Error(
          'Model must be a model or schema'
          + ' or an array containing exactly one model or schema.'
          + ' If you are trying to use multiple schemas'
          + ' try using joi.alternatives.'
        );
      }
      model = model[0];
      multiple = true;
    }

    if (!mimes) {
      mimes = [];
    }

    if (!mimes.length && model) {
      mimes.push(MIME_JSON);
    }

    const contentTypes = mimes.map(function (mime) {
      if (mime === 'binary') {
        mime = MIME_BINARY;
      }
      const contentType = mimeTypes.contentType(mime) || mime;
      const parsed = mediaTyper.parse(contentType);
      return mediaTyper.format(_.pick(parsed, [
        'type',
        'subtype',
        'suffix'
      ]));
    });

    if (model) {
      if (model.isJoi) {
        model = {schema: model};
      } else {
        model = _.clone(model);
      }
      if (model.schema && !model.schema.isJoi) {
        model.schema = joi.object(model.schema).required();
      }
      assert(
        !model.forClient || typeof model.forClient === 'function',
        `Request body model forClient handler must be a function, not ${typeof model.forClient}`
      );
      assert(
        !model.fromClient || typeof model.fromClient === 'function',
        `Request body model fromClient handler must be a function, not ${typeof model.fromClient}`
      );
      if (!model.forClient && typeof model.toClient === 'function') {
        console.log(
          `Found unexpected "toClient" method on request body model.`
          + ' Did you mean "forClient"?'
        );
      }
    }

    this._bodyParam = {
      model: model,
      multiple: multiple,
      contentTypes: contentTypes,
      description: description
    };
    return this;
  }

  response(status, model, mimes, description) {
    let statusCode = Number(status);
    if (!status || Number.isNaN(statusCode)) {
      description = mimes;
      mimes = model;
      model = status;
      statusCode = 200;
    }

    if (model === null && statusCode === 200) {
      this._responses.delete(200);
      statusCode = 204;
    }

    if (
      typeof model === 'string'
      || (Array.isArray(model) && typeof model[0] === 'string')
    ) {
      description = mimes;
      mimes = model;
      model = undefined;
    }

    if (typeof mimes === 'string') {
      description = mimes;
      mimes = undefined;
    }

    let multiple = false;
    if (Array.isArray(model)) {
      if (model.length !== 1) {
        throw new Error(
          'Model must be a model or schema'
          + ' or an array containing exactly one model or schema.'
          + ' If you are trying to use multiple schemas'
          + ' try using joi.alternatives.'
        );
      }
      model = model[0];
      multiple = true;
    }

    if (!mimes) {
      mimes = [];
    }

    if (!mimes.length && model) {
      mimes.push(MIME_JSON);
    }

    const contentTypes = mimes.map(function (mime) {
      if (mime === 'binary') {
        mime = MIME_BINARY;
      }
      const contentType = mimeTypes.contentType(mime) || mime;
      const parsed = mediaTyper.parse(contentType);
      return mediaTyper.format(_.pick(parsed, [
        'type',
        'subtype',
        'suffix'
      ]));
    });

    if (model) {
      if (model.isJoi) {
        model = {schema: model};
      } else {
        model = _.clone(model);
      }
      if (model.schema && !model.schema.isJoi) {
        model.schema = joi.object(model.schema).required();
      }
      assert(
        !model.forClient || typeof model.forClient === 'function',
        `Response body model forClient handler at ${statusCode} must be a function, not ${typeof model.forClient}`
      );
      assert(
        !model.fromClient || typeof model.fromClient === 'function',
        `Response body model fromClient handler at ${statusCode} must be a function, not ${typeof model.fromClient}`
      );
      if (!model.forClient && typeof model.toClient === 'function') {
        console.log(
          `Found unexpected "toClient" method on response body model at ${statusCode}.`
          + ' Did you mean "forClient"?'
        );
      }
    }

    this._responses.set(statusCode, {
      model: model,
      multiple: multiple,
      contentTypes: contentTypes,
      description: description
    });
    return this;
  }

  error(status, description) {
    return this.response(
      status,
      DEFAULT_ERROR_SCHEMA,
      null,
      description
    );
  }

  summary(text) {
    this._summary = text;
    return this;
  }

  description(text) {
    this._description = text;
    return this;
  }

  deprecated(flag) {
    this._deprecated = typeof flag === 'boolean' ? flag : true;
    return this;
  }

  _merge(swaggerObj, pathOnly) {
    if (!pathOnly) {
      for (const header of swaggerObj._headers.entries()) {
        this._headers.set(header[0], header[1]);
      }
      for (const queryParam of swaggerObj._queryParams.entries()) {
        this._queryParams.set(queryParam[0], queryParam[1]);
      }
      for (const response of swaggerObj._responses.entries()) {
        this._responses.set(response[0], response[1]);
      }
      if (swaggerObj._bodyParam) {
        if (!this._bodyParam || swaggerObj._bodyParam.type !== DEFAULT_BODY_SCHEMA) {
          this._bodyParam = swaggerObj._bodyParam;
        }
      }
      this._deprecated = swaggerObj._deprecated || this._deprecated;
      this._description = swaggerObj._description || this._description;
      this._summary = swaggerObj._summary || this._summary;
    }
    if (this.path.charAt(this.path.length - 1) === '*') {
      this.path = this.path.slice(0, this.path.length - 1);
    }
    if (this.path.charAt(this.path.length - 1) === '/') {
      this.path = this.path.slice(0, this.path.length - 1);
    }
    this._pathTokens.pop();
    this._pathTokens = this._pathTokens.concat(swaggerObj._pathTokens);
    for (const pathParam of swaggerObj._pathParams.entries()) {
      let name = pathParam[0];
      const def = pathParam[1];
      if (this._pathParams.has(name)) {
        let baseName = name;
        let i = 2;
        const match = name.match(/(^.+)([0-9]+)$/i);
        if (match) {
          baseName = match[1];
          i = Number(match[2]);
        }
        while (this._pathParams.has(baseName + i)) {
          i++;
        }
        name = baseName + i;
      }
      this._pathParams.set(name, def);
      this._pathParamNames.push(name);
    }
    this.path = tokenize.reverse(this._pathTokens, this._pathParamNames);
  }

  _buildOperation() {
    const operation = {
      produces: [],
      parameters: []
    };
    if (this._deprecated) {
      operation.deprecated = this._deprecated;
    }
    if (this._description) {
      operation.description = this._description;
    }
    if (this._summary) {
      operation.summary = this._summary;
    }
    if (this._bodyParam) {
      operation.consumes = (
        this._bodyParam.contentTypes
        ? this._bodyParam.contentTypes.slice()
        : []
      );
    }
    for (const response of this._responses.values()) {
      if (!response.contentTypes) {
        continue;
      }
      for (const contentType of response.contentTypes) {
        if (operation.produces.indexOf(contentType) === -1) {
          operation.produces.push(contentType);
        }
      }
    }
    if (operation.produces.indexOf('application/json') === -1) {
      // ArangoDB errors use 'application/json'
      operation.produces.push('application/json');
    }

    for (const param of this._pathParams.entries()) {
      const name = param[0];
      const def = param[1];
      const parameter = (
        def.schema
        ? swaggerifyParam(def.schema.isJoi ? def.schema : joi.object(def.schema))
        : {type: 'string'}
      );
      parameter.name = name;
      parameter.in = 'path';
      parameter.required = true;
      if (def.description) {
        parameter.description = def.description;
      }
      operation.parameters.push(parameter);
    }

    for (const param of this._queryParams.entries()) {
      const name = param[0];
      const def = param[1];
      const parameter = (
        def.schema
        ? swaggerifyParam(def.schema.isJoi ? def.schema : joi.object(def.schema))
        : {type: 'string'}
      );
      parameter.name = name;
      parameter.in = 'query';
      if (def.description) {
        parameter.description = def.description;
      }
      operation.parameters.push(parameter);
    }

    for (const param of this._headers.entries()) {
      const name = param[0];
      const def = param[1];
      const parameter = (
        def.schema
        ? swaggerifyParam(def.schema.isJoi ? def.schema : joi.object(def.schema))
        : {type: 'string'}
      );
      parameter.name = name;
      parameter.in = 'header';
      if (def.description) {
        parameter.description = def.description;
      }
      operation.parameters.push(parameter);
    }

    if (this._bodyParam && this._bodyParam.contentTypes) {
      const def = this._bodyParam;
      const schema = (
        def.model
        ? (def.model.isJoi ? def.model : def.model.schema)
        : null
      );
      const parameter = (
        schema
        ? swaggerifyBody(schema, def.multiple)
        : {schema: {type: 'string'}}
      );
      parameter.name = 'body';
      parameter.in = 'body';
      if (def.description) {
        parameter.description = def.description;
      }
      operation.parameters.push(parameter);
    }

    operation.responses = {
      default: {
        description: 'Unexpected error',
        schema: joi2schema(DEFAULT_ERROR_SCHEMA)
      }
    };

    for (const entry of this._responses.entries()) {
      const code = entry[0];
      const def = entry[1];
      const schema = (
        def.model
        ? (def.model.isJoi ? def.model : def.model.schema)
        : null
      );
      const response = {};
      if (def.contentTypes && def.contentTypes.length) {
        response.schema = (
          schema
          ? joi2schema(schema.isJoi ? schema : joi.object(schema), def.multiple)
          : {type: 'string'}
        );
      }
      if (schema && schema._description) {
        response.description = schema._description;
        delete response.schema.description;
      }
      if (def.description) {
        response.description = def.description;
      }
      if (!response.description) {
        if (response.schema) {
          response.description = `Undocumented ${code} response`;
        } else {
          response.description = `No ${code} response body`;
        }
      }
      operation.responses[code] = response;
    }

    return operation;
  }
};

exports.DEFAULT_BODY_SCHEMA = DEFAULT_BODY_SCHEMA;

function swaggerifyType(joi) {
  switch (joi._type) {
    default:
      return ['string'];
    case 'binary':
      return ['string', 'binary'];
    case 'boolean':
      return ['boolean'];
    case 'date':
      return ['string', 'date-time'];
    case 'func':
      return ['string'];
    case 'number':
      if (joi._tests.some(function (test) {
        return test.name === 'integer';
      })) {
        return ['integer'];
      }
      return ['number'];
    case 'array':
      return ['array'];
    case 'object':
      return ['object'];
    case 'string':
      if (joi._meta.some(function (meta) {
        return meta.secret;
      })) {
        return ['string', 'password'];
      }
      return ['string'];
  }
}

function swaggerifyParam(joi) {
  const param = {
    required: joi._presence === 'required',
    description: joi._description
  };
  let item = param;
  if (joi._meta.some(function (meta) {
    return meta.allowMultiple;
  })) {
    param.type = 'array';
    param.collectionFormat = 'multi';
    param.items = {};
    item = param.items;
  }
  const type = swaggerifyType(joi);
  item.type = type[0];
  if (type.length > 1) {
    item.format = type[1];
  }
  if (joi._valids._set && joi._valids._set.length) {
    item.enum = joi._valids._set;
  }
  if (joi._flags.hasOwnProperty('default')) {
    item.default = joi._flags.default;
  }
  return param;
}

function swaggerifyBody(joi, multiple) {
  return {
    required: joi._presence === 'required',
    description: joi._description,
    schema: joi2schema(joi, multiple)
  };
}

function joi2schema(schema, multiple) {
  if (multiple) {
    schema = joi.array().items(schema);
  }
  return joiToJsonSchema(schema);
}
<|endoftext|>


<commit_before>// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import * as Common from '../common/common.js';
import * as Persistence from '../persistence/persistence.js';
import * as QuickOpen from '../quick_open/quick_open.js';
import * as UI from '../ui/ui.js';
import * as Workspace from '../workspace/workspace.js';

import {FilePathScoreFunction} from './FilePathScoreFunction.js';

export class FilteredUISourceCodeListProvider extends QuickOpen.FilteredListWidget.Provider {
  constructor() {
    super();

    this._queryLineNumberAndColumnNumber = '';
    this._defaultScores = null;
    this._scorer = new FilePathScoreFunction('');

    /** @type {!Array.<!Workspace.UISourceCode.UISourceCode>} */
    this._uiSourceCodes = [];

    /** @type {string} */
    this._query;
  }

  /**
   * @param {!Common.EventTarget.EventTargetEvent} event
   */
  _projectRemoved(event) {
    const project = /** @type {!Workspace.Workspace.Project} */ (event.data);
    this._populate(project);
    this.refresh();
  }

  /**
   * @param {!Workspace.Workspace.Project=} skipProject
   */
  _populate(skipProject) {
    this._uiSourceCodes = [];
    const projects = Workspace.Workspace.WorkspaceImpl.instance().projects().filter(this.filterProject.bind(this));
    for (let i = 0; i < projects.length; ++i) {
      if (skipProject && projects[i] === skipProject) {
        continue;
      }
      const uiSourceCodes = projects[i].uiSourceCodes().filter(this._filterUISourceCode.bind(this));
      this._uiSourceCodes = this._uiSourceCodes.concat(uiSourceCodes);
    }
  }

  /**
   * @param {!Workspace.UISourceCode.UISourceCode} uiSourceCode
   * @return {boolean}
   */
  _filterUISourceCode(uiSourceCode) {
    const binding = Persistence.Persistence.PersistenceImpl.instance().binding(uiSourceCode);
    return !binding || binding.fileSystem === uiSourceCode;
  }

  /**
   * @param {?Workspace.UISourceCode.UISourceCode} uiSourceCode
   * @param {number=} lineNumber
   * @param {number=} columnNumber
   */
  uiSourceCodeSelected(uiSourceCode, lineNumber, columnNumber) {
    // Overridden by subclasses
  }

  /**
   * @param {!Workspace.Workspace.Project} project
   * @return {boolean}
   */
  filterProject(project) {
    return true;
    // Overridden by subclasses
  }

  /**
   * @override
   * @return {number}
   */
  itemCount() {
    return this._uiSourceCodes.length;
  }

  /**
   * @override
   * @param {number} itemIndex
   * @return {string}
   */
  itemKeyAt(itemIndex) {
    return this._uiSourceCodes[itemIndex].url();
  }

  /**
   * @protected
   * @param {?Map.<!Workspace.UISourceCode.UISourceCode, number>} defaultScores
   */
  setDefaultScores(defaultScores) {
    this._defaultScores = defaultScores;
  }

  /**
   * @override
   * @param {number} itemIndex
   * @param {string} query
   * @return {number}
   */
  itemScoreAt(itemIndex, query) {
    const uiSourceCode = this._uiSourceCodes[itemIndex];
    const score = this._defaultScores ? (this._defaultScores.get(uiSourceCode) || 0) : 0;
    if (!query || query.length < 2) {
      return score;
    }

    if (this._query !== query) {
      this._query = query;
      this._scorer = new FilePathScoreFunction(query);
    }

    let multiplier = 10;
    if (uiSourceCode.project().type() === Workspace.Workspace.projectTypes.FileSystem &&
        !Persistence.Persistence.PersistenceImpl.instance().binding(uiSourceCode)) {
      multiplier = 5;
    }

    const fullDisplayName = uiSourceCode.fullDisplayName();
    return score + multiplier * this._scorer.score(fullDisplayName, null);
  }

  /**
   * @override
   * @param {number} itemIndex
   * @param {string} query
   * @param {!Element} titleElement
   * @param {!Element} subtitleElement
   */
  renderItem(itemIndex, query, titleElement, subtitleElement) {
    query = this.rewriteQuery(query);
    const uiSourceCode = this._uiSourceCodes[itemIndex];
    const fullDisplayName = uiSourceCode.fullDisplayName();
    /** @type {!Array<number>} */
    const indexes = [];
    new FilePathScoreFunction(query).score(fullDisplayName, indexes);
    const fileNameIndex = fullDisplayName.lastIndexOf('/');

    titleElement.classList.add('monospace');
    subtitleElement.classList.add('monospace');
    titleElement.textContent = uiSourceCode.displayName() + (this._queryLineNumberAndColumnNumber || '');
    this._renderSubtitleElement(subtitleElement, fullDisplayName);
    /** @type {!HTMLElement} */ (subtitleElement).title = fullDisplayName;
    const ranges = [];
    for (let i = 0; i < indexes.length; ++i) {
      ranges.push({offset: indexes[i], length: 1});
    }

    if (indexes[0] > fileNameIndex) {
      for (let i = 0; i < ranges.length; ++i) {
        ranges[i].offset -= fileNameIndex + 1;
      }
      UI.UIUtils.highlightRangesWithStyleClass(titleElement, ranges, 'highlight');
    } else {
      UI.UIUtils.highlightRangesWithStyleClass(subtitleElement, ranges, 'highlight');
    }
  }

  /**
   * @param {!Element} element
   * @param {string} text
   */
  _renderSubtitleElement(element, text) {
    element.removeChildren();
    let splitPosition = text.lastIndexOf('/');
    if (text.length > 55) {
      splitPosition = text.length - 55;
    }
    const first = element.createChild('div', 'first-part');
    first.textContent = text.substring(0, splitPosition);
    const second = element.createChild('div', 'second-part');
    second.textContent = text.substring(splitPosition);
    /** @type {!HTMLElement} */ (element).title = text;
  }

  /**
   * @override
   * @param {?number} itemIndex
   * @param {string} promptValue
   */
  selectItem(itemIndex, promptValue) {
    const parsedExpression = promptValue.trim().match(/^([^:]*)(:\d+)?(:\d+)?$/);
    if (!parsedExpression) {
      return;
    }

    let lineNumber;
    let columnNumber;
    if (parsedExpression[2]) {
      lineNumber = parseInt(parsedExpression[2].substr(1), 10) - 1;
    }
    if (parsedExpression[3]) {
      columnNumber = parseInt(parsedExpression[3].substr(1), 10) - 1;
    }
    const uiSourceCode = itemIndex !== null ? this._uiSourceCodes[itemIndex] : null;
    this.uiSourceCodeSelected(uiSourceCode, lineNumber, columnNumber);
  }

  /**
   * @override
   * @param {string} query
   * @return {string}
   */
  rewriteQuery(query) {
    query = query ? query.trim() : '';
    if (!query || query === ':') {
      return '';
    }
    const lineNumberMatch = query.match(/^([^:]+)((?::[^:]*){0,2})$/);
    this._queryLineNumberAndColumnNumber = lineNumberMatch ? lineNumberMatch[2] : '';
    return lineNumberMatch ? lineNumberMatch[1] : query;
  }

  /**
   * @param {!Common.EventTarget.EventTargetEvent} event
   */
  _uiSourceCodeAdded(event) {
    const uiSourceCode = /** @type {!Workspace.UISourceCode.UISourceCode} */ (event.data);
    if (!this._filterUISourceCode(uiSourceCode) || !this.filterProject(uiSourceCode.project())) {
      return;
    }
    this._uiSourceCodes.push(uiSourceCode);
    this.refresh();
  }

  /**
   * @override
   * @return {string}
   */
  notFoundText() {
    return Common.UIString.UIString('No files found');
  }

  /**
   * @override
   */
  attach() {
    Workspace.Workspace.WorkspaceImpl.instance().addEventListener(
        Workspace.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
    Workspace.Workspace.WorkspaceImpl.instance().addEventListener(
        Workspace.Workspace.Events.ProjectRemoved, this._projectRemoved, this);
    this._populate();
  }

  /**
   * @override
   */
  detach() {
    Workspace.Workspace.WorkspaceImpl.instance().removeEventListener(
        Workspace.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
    Workspace.Workspace.WorkspaceImpl.instance().removeEventListener(
        Workspace.Workspace.Events.ProjectRemoved, this._projectRemoved, this);
    this._queryLineNumberAndColumnNumber = '';
    this._defaultScores = null;
  }
}
<commit_msg>De-duplicate file entries in QuickOpen window.<commit_after>// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import * as Common from '../common/common.js';
import * as Persistence from '../persistence/persistence.js';
import * as QuickOpen from '../quick_open/quick_open.js';
import * as UI from '../ui/ui.js';
import * as Workspace from '../workspace/workspace.js';

import {FilePathScoreFunction} from './FilePathScoreFunction.js';

export class FilteredUISourceCodeListProvider extends QuickOpen.FilteredListWidget.Provider {
  constructor() {
    super();

    this._queryLineNumberAndColumnNumber = '';
    this._defaultScores = null;
    this._scorer = new FilePathScoreFunction('');

    /** @type {!Array<!Workspace.UISourceCode.UISourceCode>} */
    this._uiSourceCodes = [];
    /** @type {!Set<string>} */
    this._uiSourceCodeUrls = new Set();

    /** @type {string} */
    this._query;
  }

  /**
   * @param {!Common.EventTarget.EventTargetEvent} event
   */
  _projectRemoved(event) {
    const project = /** @type {!Workspace.Workspace.Project} */ (event.data);
    this._populate(project);
    this.refresh();
  }

  /**
   * @param {!Workspace.Workspace.Project=} skipProject
   */
  _populate(skipProject) {
    this._uiSourceCodes = [];
    this._uiSourceCodeUrls.clear();
    for (const project of Workspace.Workspace.WorkspaceImpl.instance().projects()) {
      if (project !== skipProject && this.filterProject(project)) {
        for (const uiSourceCode of project.uiSourceCodes()) {
          if (this._filterUISourceCode(uiSourceCode)) {
            this._uiSourceCodes.push(uiSourceCode);
            this._uiSourceCodeUrls.add(uiSourceCode.url());
          }
        }
      }
    }
  }

  /**
   * @param {!Workspace.UISourceCode.UISourceCode} uiSourceCode
   * @return {boolean}
   */
  _filterUISourceCode(uiSourceCode) {
    if (this._uiSourceCodeUrls.has(uiSourceCode.url())) {
      return false;
    }
    const binding = Persistence.Persistence.PersistenceImpl.instance().binding(uiSourceCode);
    return !binding || binding.fileSystem === uiSourceCode;
  }

  /**
   * @param {?Workspace.UISourceCode.UISourceCode} uiSourceCode
   * @param {number=} lineNumber
   * @param {number=} columnNumber
   */
  uiSourceCodeSelected(uiSourceCode, lineNumber, columnNumber) {
    // Overridden by subclasses
  }

  /**
   * @param {!Workspace.Workspace.Project} project
   * @return {boolean}
   */
  filterProject(project) {
    return true;
    // Overridden by subclasses
  }

  /**
   * @override
   * @return {number}
   */
  itemCount() {
    return this._uiSourceCodes.length;
  }

  /**
   * @override
   * @param {number} itemIndex
   * @return {string}
   */
  itemKeyAt(itemIndex) {
    return this._uiSourceCodes[itemIndex].url();
  }

  /**
   * @protected
   * @param {?Map.<!Workspace.UISourceCode.UISourceCode, number>} defaultScores
   */
  setDefaultScores(defaultScores) {
    this._defaultScores = defaultScores;
  }

  /**
   * @override
   * @param {number} itemIndex
   * @param {string} query
   * @return {number}
   */
  itemScoreAt(itemIndex, query) {
    const uiSourceCode = this._uiSourceCodes[itemIndex];
    const score = this._defaultScores ? (this._defaultScores.get(uiSourceCode) || 0) : 0;
    if (!query || query.length < 2) {
      return score;
    }

    if (this._query !== query) {
      this._query = query;
      this._scorer = new FilePathScoreFunction(query);
    }

    let multiplier = 10;
    if (uiSourceCode.project().type() === Workspace.Workspace.projectTypes.FileSystem &&
        !Persistence.Persistence.PersistenceImpl.instance().binding(uiSourceCode)) {
      multiplier = 5;
    }

    const fullDisplayName = uiSourceCode.fullDisplayName();
    return score + multiplier * this._scorer.score(fullDisplayName, null);
  }

  /**
   * @override
   * @param {number} itemIndex
   * @param {string} query
   * @param {!Element} titleElement
   * @param {!Element} subtitleElement
   */
  renderItem(itemIndex, query, titleElement, subtitleElement) {
    query = this.rewriteQuery(query);
    const uiSourceCode = this._uiSourceCodes[itemIndex];
    const fullDisplayName = uiSourceCode.fullDisplayName();
    /** @type {!Array<number>} */
    const indexes = [];
    new FilePathScoreFunction(query).score(fullDisplayName, indexes);
    const fileNameIndex = fullDisplayName.lastIndexOf('/');

    titleElement.classList.add('monospace');
    subtitleElement.classList.add('monospace');
    titleElement.textContent = uiSourceCode.displayName() + (this._queryLineNumberAndColumnNumber || '');
    this._renderSubtitleElement(subtitleElement, fullDisplayName);
    /** @type {!HTMLElement} */ (subtitleElement).title = fullDisplayName;
    const ranges = [];
    for (let i = 0; i < indexes.length; ++i) {
      ranges.push({offset: indexes[i], length: 1});
    }

    if (indexes[0] > fileNameIndex) {
      for (let i = 0; i < ranges.length; ++i) {
        ranges[i].offset -= fileNameIndex + 1;
      }
      UI.UIUtils.highlightRangesWithStyleClass(titleElement, ranges, 'highlight');
    } else {
      UI.UIUtils.highlightRangesWithStyleClass(subtitleElement, ranges, 'highlight');
    }
  }

  /**
   * @param {!Element} element
   * @param {string} text
   */
  _renderSubtitleElement(element, text) {
    element.removeChildren();
    let splitPosition = text.lastIndexOf('/');
    if (text.length > 55) {
      splitPosition = text.length - 55;
    }
    const first = element.createChild('div', 'first-part');
    first.textContent = text.substring(0, splitPosition);
    const second = element.createChild('div', 'second-part');
    second.textContent = text.substring(splitPosition);
    /** @type {!HTMLElement} */ (element).title = text;
  }

  /**
   * @override
   * @param {?number} itemIndex
   * @param {string} promptValue
   */
  selectItem(itemIndex, promptValue) {
    const parsedExpression = promptValue.trim().match(/^([^:]*)(:\d+)?(:\d+)?$/);
    if (!parsedExpression) {
      return;
    }

    let lineNumber;
    let columnNumber;
    if (parsedExpression[2]) {
      lineNumber = parseInt(parsedExpression[2].substr(1), 10) - 1;
    }
    if (parsedExpression[3]) {
      columnNumber = parseInt(parsedExpression[3].substr(1), 10) - 1;
    }
    const uiSourceCode = itemIndex !== null ? this._uiSourceCodes[itemIndex] : null;
    this.uiSourceCodeSelected(uiSourceCode, lineNumber, columnNumber);
  }

  /**
   * @override
   * @param {string} query
   * @return {string}
   */
  rewriteQuery(query) {
    query = query ? query.trim() : '';
    if (!query || query === ':') {
      return '';
    }
    const lineNumberMatch = query.match(/^([^:]+)((?::[^:]*){0,2})$/);
    this._queryLineNumberAndColumnNumber = lineNumberMatch ? lineNumberMatch[2] : '';
    return lineNumberMatch ? lineNumberMatch[1] : query;
  }

  /**
   * @param {!Common.EventTarget.EventTargetEvent} event
   */
  _uiSourceCodeAdded(event) {
    const uiSourceCode = /** @type {!Workspace.UISourceCode.UISourceCode} */ (event.data);
    if (!this._filterUISourceCode(uiSourceCode) || !this.filterProject(uiSourceCode.project())) {
      return;
    }
    this._uiSourceCodes.push(uiSourceCode);
    this._uiSourceCodeUrls.add(uiSourceCode.url());
    this.refresh();
  }

  /**
   * @override
   * @return {string}
   */
  notFoundText() {
    return Common.UIString.UIString('No files found');
  }

  /**
   * @override
   */
  attach() {
    Workspace.Workspace.WorkspaceImpl.instance().addEventListener(
        Workspace.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
    Workspace.Workspace.WorkspaceImpl.instance().addEventListener(
        Workspace.Workspace.Events.ProjectRemoved, this._projectRemoved, this);
    this._populate();
  }

  /**
   * @override
   */
  detach() {
    Workspace.Workspace.WorkspaceImpl.instance().removeEventListener(
        Workspace.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
    Workspace.Workspace.WorkspaceImpl.instance().removeEventListener(
        Workspace.Workspace.Events.ProjectRemoved, this._projectRemoved, this);
    this._queryLineNumberAndColumnNumber = '';
    this._defaultScores = null;
  }
}
<|endoftext|>


<commit_before>import React from 'react'
import { connect } from 'react-redux'
import { List, ListItem, Divider } from 'material-ui'

import { toggleDeveloperMode } from '../core/actions/action-creators/app'

const About = ({ appVersion, enableDeveloperMode }) => {
  return (

      <List>
        <ListItem primaryText='App version' secondaryText={appVersion} onTouchTap={enableDeveloperMode} />
        <Divider />
      </List>

  )
}

const mapStateToProps = state => {
  const { version: appVersion } = state.get('app').toJS()

  return {
    appVersion
  }
}

const mapDispatchToProps = dispatch => {
  return {
    enableDeveloperMode: () => {
      dispatch(toggleDeveloperMode(true))
    }
  }
}

export {
  About
}
export default connect(mapStateToProps, mapDispatchToProps)(About)
<commit_msg>[gh-48]: renamed label<commit_after>import React from 'react'
import { connect } from 'react-redux'
import { List, ListItem, Divider } from 'material-ui'

import { toggleDeveloperMode } from '../core/actions/action-creators/app'

const About = ({ version, enableDeveloperMode }) => {
  return (

      <List>
        <ListItem primaryText='Version' secondaryText={version} onTouchTap={enableDeveloperMode} />
        <Divider />
      </List>

  )
}

const mapStateToProps = state => {
  const { version } = state.get('app').toJS()

  return {
    version
  }
}

const mapDispatchToProps = dispatch => {
  return {
    enableDeveloperMode: () => {
      dispatch(toggleDeveloperMode(true))
    }
  }
}

export {
  About
}
export default connect(mapStateToProps, mapDispatchToProps)(About)
<|endoftext|>