Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | 4x 4x 4x 4x 4x 4x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 40x 11x 11x 21x 21x 11x 33x 23x 23x 11x 22x 20x 20x 20x 20x 11x 11x 11x 11x 1x 2x 2x 2x 2x 10x 14x 11x 11x 44x 44x 36x 36x 36x 36x 11x 11x 11x 11x 11x 11x 11x 11x | import * as params from './export_params' import {group_checks, export_checks} from './checks' import {passes_filter, passes_feature_filter} from './filter_check' import {patterns} from './patterns' import * as row_writers from './row_writers' import type {Query, Entity, Features, Entities, RawQuery} from '../types' import DataHandler from './index' export async function exporter( this: DataHandler, query_string?: RawQuery, entities?: Entities, in_browser?: boolean, all_data?: boolean ) { if (!in_browser) await this.data_ready const query: Query = this.parse_query(query_string) entities = entities || this.entities Iif (-1 === params.options.file_format.indexOf(query.file_format)) query.file_format = params.defaults.file_format Iif (!(query.table_format in row_writers)) query.table_format = params.defaults.table_format const res = { statusCode: 400, headers: {'Content-Type': 'text/plain; charset=utf-8', 'Content-Disposition': 'attachment; filename='}, body: 'Invalid Request', }, inc: string[] = query.include && query.include.length ? 'string' === typeof query.include ? query.include in this.variables ? [query.include] : query.include.split(',') : query.include : Object.keys(this.variables), exc = query.exclude || [], vars: string[] = [], feats: Features = query.features || JSON.parse(JSON.stringify(params.defaults.features)), rows: string[] = [], range = [Infinity, -Infinity], sep = 'csv' === query.file_format ? ',' : '\t', rw: Function = row_writers[query.table_format].bind(this), no_filter = !query.variables.filter_by.length, no_feature_filter = !query.feature_conditions.length, in_group: Function = !('dataset' in query) ? () => true : group_checks[query.dataset.operator].bind( 'number' === typeof query.dataset.value ? query.dataset.value + '' : query.dataset.value ) let malformed = '' inc.forEach(ii => { Iif (ii in this.features && !(ii in feats)) { feats[ii] = this.format_label(ii) } else Iif (!(ii in this.variables)) { malformed += ii + ',' Iif (malformed in this.variables) { inc.push(malformed) malformed = '' } } }) for (const k in export_checks) if (k in query) { const r: string = export_checks[k]('include' === k ? inc : query[k as keyof Query], this.variables) Iif (r) { res.body = 'Failed check for ' + k + ': ' + r return res } } Object.keys(this.variable_codes).forEach(k => { if (-1 !== inc.indexOf(this.variable_codes[k].name) && -1 === exc.indexOf(this.variable_codes[k].name)) { vars.push(this.variable_codes[k].name) const tr: [number, number] = this.meta.ranges[this.variable_codes[k].name] if (tr[0] < range[0]) range[0] = tr[0] if (tr[1] > range[1]) range[1] = tr[1] } }) Iif (query.time_range[0] < range[0]) query.time_range[0] = range[0] Iif (query.time_range[1] > range[1]) query.time_range[1] = range[1] rows.push(Object.keys(feats).join(sep)) if ('wide' === query.table_format) { vars.forEach(vi => { const tr: [number, number] = this.meta.ranges[vi], yn = Math.min(query.time_range[1], tr[1]) + 1 for (let y = Math.max(query.time_range[0], tr[0]); y < yn; y++) { rows[0] += sep + '"' + vi + '_' + this.meta.overall.value[y] + '"' } }) } else rows[0] += sep + 'time' + sep + ('mixed' === query.table_format ? vars.map(n => '"' + n + '"') : ['variable', 'value']).join(sep) let first_entity = '' Object.keys(entities).forEach(k => { const e: Entity = entities[k] if ( in_group(e.group) && (no_feature_filter || passes_feature_filter(entities, k, query.feature_conditions)) && (no_filter || passes_filter(e, query.time_range, query.variables, this.variables)) ) { const r: string = rw(e, query.time_range, feats, vars, sep) if (r) { if (!first_entity) first_entity = k rows.push(r) } } }) res.headers['Content-Type'] = 'text/' + (',' === sep ? 'csv' : 'plain') + '; charset=utf-8' res.body = rows.join('\n') const times: number[] = this.meta.overall.value, filename = 'export_' + (in_browser && !all_data && first_entity ? entities[first_entity].group + '_' : query.dataset ? query.dataset.value + '_' : '') + (query.time_range[0] === query.time_range[1] ? times[query.time_range[0]] : times[query.time_range[0]] + '-' + times[query.time_range[1]]) + '_' + (1 === vars.length ? this.variables[vars[0]].meta.short_name.toLowerCase().replace(patterns.non_letter_num, '-') : vars.length + '-variables') + '_' + (rows.join('\n').split('\n').length - 1) + 'x' + rows[0].split(sep).length Iif (in_browser) { const e = document.createElement('a') document.body.appendChild(e) e.rel = 'noreferrer' e.target = '_blank' e.download = filename + '.' + query.file_format e.href = URL.createObjectURL(new Blob([res.body], {type: res.headers['Content-Type']})) setTimeout(function () { e.dispatchEvent(new MouseEvent('click')) URL.revokeObjectURL.bind(null, e.href) document.body.removeChild(e) }, 0) } res.statusCode = 200 res.headers['Content-Disposition'] += filename + '.' + query.file_format return res } |