geonetwork-ui 2.10.3-dev.4154db07d → 2.11.0-dev.1cf4ab0c6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/geonetwork-ui.mjs +1540 -839
- package/fesm2022/geonetwork-ui.mjs.map +1 -1
- package/index.d.ts +242 -92
- package/index.d.ts.map +1 -1
- package/package.json +9 -8
- package/src/libs/api/metadata-converter/src/lib/fixtures/generic.records.ts +5 -5
- package/src/libs/api/metadata-converter/src/lib/fixtures/metawal.records.ts +5 -5
- package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +43 -13
- package/src/libs/api/metadata-converter/src/lib/gn4/types/elasticsearch.model.ts +13 -1
- package/src/libs/api/metadata-converter/src/lib/iso19115-3/write-parts.ts +2 -2
- package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +9 -5
- package/src/libs/api/metadata-converter/src/lib/iso19139/utils/association-type.mapper.ts +12 -0
- package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +2 -2
- package/src/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.ts +99 -37
- package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +40 -16
- package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +40 -2
- package/src/libs/common/domain/src/lib/model/search/filter.model.ts +13 -1
- package/src/libs/common/domain/src/lib/model/search/sort-by.model.ts +1 -5
- package/src/libs/common/domain/src/lib/repository/records-repository.interface.ts +2 -2
- package/src/libs/feature/dataviz/src/lib/chart-view/chart-view.component.ts +3 -2
- package/src/libs/feature/dataviz/src/lib/geo-table-view/geo-table-view.component.ts +2 -1
- package/src/libs/feature/dataviz/src/lib/service/data.service.ts +22 -22
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-associated-records/form-field-associated-records.component.css +0 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-associated-records/form-field-associated-records.component.html +33 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-associated-records/form-field-associated-records.component.ts +94 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-temporal-extents/form-field-temporal-extents.component.html +16 -12
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html +6 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts +6 -0
- package/src/libs/feature/editor/src/lib/fields.config.ts +5 -0
- package/src/libs/feature/map/src/lib/add-layer-from-file/add-layer-from-file.component.html +1 -0
- package/src/libs/feature/notifications/src/lib/notifications.service.ts +6 -4
- package/src/libs/feature/record/src/lib/state/mdview.actions.ts +4 -8
- package/src/libs/feature/record/src/lib/state/mdview.effects.ts +7 -16
- package/src/libs/feature/record/src/lib/state/mdview.facade.ts +1 -3
- package/src/libs/feature/record/src/lib/state/mdview.reducer.ts +4 -9
- package/src/libs/feature/record/src/lib/state/mdview.selectors.ts +2 -7
- package/src/libs/feature/router/src/lib/default/router.service.ts +1 -1
- package/src/libs/feature/router/src/lib/default/state/query-params.utils.ts +1 -1
- package/src/libs/feature/search/src/lib/filter-dropdown/filter-dropdown.component.html +12 -4
- package/src/libs/feature/search/src/lib/filter-dropdown/filter-dropdown.component.ts +58 -19
- package/src/libs/feature/search/src/lib/search-filters-summary-item/search-filters-summary-item.component.ts +18 -8
- package/src/libs/feature/search/src/lib/sort-by/sort-by.component.ts +1 -1
- package/src/libs/feature/search/src/lib/utils/service/fields.service.ts +9 -1
- package/src/libs/feature/search/src/lib/utils/service/fields.ts +43 -2
- package/src/libs/ui/dataviz/src/lib/data-table/data-table.component.html +6 -7
- package/src/libs/ui/dataviz/src/lib/data-table/data-table.component.ts +31 -19
- package/src/libs/ui/dataviz/src/lib/data-table/data-table.fixtures.ts +2 -2
- package/src/libs/ui/elements/src/lib/service-capabilities/service-capabilities.component.ts +2 -1
- package/src/libs/ui/inputs/src/index.ts +2 -0
- package/src/libs/ui/inputs/src/lib/date-adapter.providers.ts +30 -0
- package/src/libs/ui/inputs/src/lib/date-picker/date-picker.component.ts +3 -24
- package/src/libs/ui/inputs/src/lib/date-range-dropdown/date-range-dropdown.component.css +37 -3
- package/src/libs/ui/inputs/src/lib/date-range-dropdown/date-range-dropdown.component.html +135 -16
- package/src/libs/ui/inputs/src/lib/date-range-dropdown/date-range-dropdown.component.ts +166 -29
- package/src/libs/ui/inputs/src/lib/date-range-picker/date-range-picker.component.ts +3 -7
- package/src/libs/ui/inputs/src/lib/drag-and-drop-file-input/drag-and-drop-file-input.component.css +1 -0
- package/src/libs/ui/inputs/src/lib/drag-and-drop-file-input/drag-and-drop-file-input.component.html +20 -7
- package/src/libs/ui/inputs/src/lib/drag-and-drop-file-input/drag-and-drop-file-input.component.ts +46 -5
- package/src/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.html +1 -1
- package/src/libs/ui/inputs/src/lib/spatial-extent-dropdown/spatial-extent-dropdown.component.css +0 -0
- package/src/libs/ui/inputs/src/lib/spatial-extent-dropdown/spatial-extent-dropdown.component.html +111 -0
- package/src/libs/ui/inputs/src/lib/spatial-extent-dropdown/spatial-extent-dropdown.component.ts +215 -0
- package/src/libs/util/app-config/src/lib/app-config.ts +3 -0
- package/src/libs/util/app-config/src/lib/model.ts +1 -0
- package/src/libs/util/data-fetcher/src/lib/data-fetcher.ts +19 -22
- package/src/libs/util/data-fetcher/src/lib/engine/duckdb.ts +185 -0
- package/src/libs/util/data-fetcher/src/lib/engine/results.ts +63 -0
- package/src/libs/util/data-fetcher/src/lib/{sql-utils.ts → engine/sql-utils.ts} +28 -13
- package/src/libs/util/data-fetcher/src/lib/model.ts +2 -1
- package/src/libs/util/data-fetcher/src/lib/readers/base-file.ts +53 -38
- package/src/libs/util/data-fetcher/src/lib/readers/base.ts +11 -0
- package/src/libs/util/data-fetcher/src/lib/readers/csv.ts +9 -47
- package/src/libs/util/data-fetcher/src/lib/readers/excel.ts +27 -27
- package/src/libs/util/data-fetcher/src/lib/readers/geojson.ts +5 -24
- package/src/libs/util/data-fetcher/src/lib/readers/gml.ts +5 -49
- package/src/libs/util/data-fetcher/src/lib/readers/json.ts +5 -23
- package/src/libs/util/data-fetcher/src/lib/readers/wfs.ts +184 -128
- package/src/libs/util/data-fetcher/src/lib/utils.ts +0 -143
- package/src/libs/util/shared/src/index.ts +1 -0
- package/src/libs/util/shared/src/lib/autofocus.directive.ts +26 -0
- package/src/libs/util/shared/src/lib/gn-ui-version.ts +1 -1
- package/src/libs/util/shared/src/lib/links/link-utils.ts +19 -10
- package/src/libs/util/shared/src/lib/services/date.service.ts +3 -3
- package/src/libs/util/shared/src/lib/utils/file.ts +15 -0
- package/src/libs/util/shared/src/lib/utils/geojson.ts +8 -0
- package/src/libs/util/shared/src/lib/utils/index.ts +1 -0
- package/tailwind.base.css +5 -0
- package/translations/de.json +30 -3
- package/translations/en.json +29 -2
- package/translations/es.json +27 -0
- package/translations/fr.json +30 -3
- package/translations/it.json +28 -1
- package/translations/nl.json +27 -0
- package/translations/pt.json +27 -0
- package/translations/sk.json +28 -1
- package/src/libs/util/data-fetcher/src/lib/readers/base-cache.ts +0 -14
|
@@ -1,65 +1,80 @@
|
|
|
1
1
|
import { DataItem, DatasetInfo, PropertyInfo } from '../model'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { generateSqlQuery } from '../engine/sql-utils'
|
|
3
|
+
import { Engine, getEngine } from '../engine/duckdb'
|
|
4
|
+
import { BaseReader } from './base'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
/**
|
|
7
|
+
* This reader handles file formats supported natively by DuckDB
|
|
8
|
+
*/
|
|
9
|
+
export class BaseFileReader extends BaseReader {
|
|
10
|
+
protected engine: Engine
|
|
11
|
+
protected datasetId: string
|
|
12
|
+
protected properties_: PropertyInfo[]
|
|
13
|
+
protected geometryColumn: string
|
|
14
|
+
protected rowsCount: number
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
// a table id should not exceed 63 chars
|
|
17
|
+
protected generateDatasetId() {
|
|
18
|
+
// generate a hash out of the url
|
|
19
|
+
let hash = 0
|
|
20
|
+
for (const char of this.url) {
|
|
21
|
+
hash = (hash << 5) - hash + char.charCodeAt(0)
|
|
22
|
+
hash = hash >>> 0 // make it unsigned
|
|
23
|
+
}
|
|
24
|
+
return `datafetcher_${hash.toString(16)}`
|
|
25
|
+
}
|
|
13
26
|
|
|
14
|
-
protected
|
|
27
|
+
protected async getLoadQuery(): Promise<string> {
|
|
15
28
|
throw new Error('not implemented')
|
|
16
29
|
}
|
|
17
30
|
|
|
18
|
-
load() {
|
|
19
|
-
this.
|
|
31
|
+
async load() {
|
|
32
|
+
this.datasetId = this.generateDatasetId()
|
|
33
|
+
this.loadPromise_ = getEngine()
|
|
34
|
+
.then((engine) => {
|
|
35
|
+
this.engine = engine
|
|
36
|
+
return this.getLoadQuery()
|
|
37
|
+
})
|
|
38
|
+
.then((loadQuery) =>
|
|
39
|
+
this.engine.loadFile(this.datasetId, loadQuery, !this.cacheEnabled)
|
|
40
|
+
)
|
|
41
|
+
.then((datasetInfo) => {
|
|
42
|
+
this.properties_ = datasetInfo.properties
|
|
43
|
+
this.geometryColumn = datasetInfo.geometryColumn
|
|
44
|
+
this.rowsCount = datasetInfo.rowsCount
|
|
45
|
+
// returns void for the loaded promise
|
|
46
|
+
})
|
|
20
47
|
}
|
|
21
48
|
|
|
22
49
|
get properties(): Promise<PropertyInfo[]> {
|
|
23
|
-
return this.
|
|
50
|
+
return this.isLoaded.then(() => this.properties_)
|
|
24
51
|
}
|
|
25
52
|
|
|
26
53
|
get info(): Promise<DatasetInfo> {
|
|
27
|
-
return this.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}) as DatasetInfo
|
|
32
|
-
)
|
|
54
|
+
return this.isLoaded.then(() => ({
|
|
55
|
+
itemsCount: this.rowsCount,
|
|
56
|
+
hasGeometry: !!this.geometryColumn,
|
|
57
|
+
}))
|
|
33
58
|
}
|
|
34
59
|
|
|
35
60
|
async read(): Promise<DataItem[]> {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if
|
|
39
|
-
|
|
40
|
-
this.aggregations == null &&
|
|
41
|
-
this.selected == null &&
|
|
42
|
-
this.sort == null &&
|
|
43
|
-
this.filter == null &&
|
|
44
|
-
this.startIndex == null &&
|
|
45
|
-
this.count == null
|
|
46
|
-
) {
|
|
47
|
-
return items
|
|
48
|
-
}
|
|
61
|
+
await this.isLoaded
|
|
62
|
+
|
|
63
|
+
// if only certain fields are selected, omit the geometry
|
|
64
|
+
const geometryColumn = this.selected === null ? this.geometryColumn : null
|
|
49
65
|
|
|
50
|
-
const jsonItems = getJsonDataItemsProxy(items)
|
|
51
66
|
const query = generateSqlQuery(
|
|
67
|
+
this.datasetId,
|
|
52
68
|
this.selected,
|
|
53
69
|
this.filter,
|
|
54
70
|
this.sort,
|
|
55
71
|
this.startIndex,
|
|
56
72
|
this.count,
|
|
57
73
|
this.groupedBy,
|
|
58
|
-
this.aggregations
|
|
74
|
+
this.aggregations,
|
|
75
|
+
geometryColumn
|
|
59
76
|
)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
)
|
|
63
|
-
return result.map(jsonToGeojsonFeature)
|
|
77
|
+
|
|
78
|
+
return this.engine.queryItems(query)
|
|
64
79
|
}
|
|
65
80
|
}
|
|
@@ -17,13 +17,24 @@ export class BaseReader {
|
|
|
17
17
|
protected sort: FieldSort[] = null
|
|
18
18
|
protected startIndex: number = null
|
|
19
19
|
protected count: number = null
|
|
20
|
+
protected loadPromise_: Promise<void> = Promise.resolve()
|
|
21
|
+
|
|
22
|
+
protected cacheEnabled = false
|
|
20
23
|
|
|
21
24
|
constructor(protected url: string) {}
|
|
22
25
|
|
|
26
|
+
enableCache(enabled: boolean) {
|
|
27
|
+
this.cacheEnabled = enabled
|
|
28
|
+
}
|
|
29
|
+
|
|
23
30
|
load() {
|
|
24
31
|
throw new Error('not implemented')
|
|
25
32
|
}
|
|
26
33
|
|
|
34
|
+
get isLoaded() {
|
|
35
|
+
return this.loadPromise_
|
|
36
|
+
}
|
|
37
|
+
|
|
27
38
|
get properties(): Promise<PropertyInfo[]> {
|
|
28
39
|
throw new Error('not implemented')
|
|
29
40
|
}
|
|
@@ -1,52 +1,14 @@
|
|
|
1
|
-
import * as Papa from 'papaparse'
|
|
2
|
-
import { DataItem, PropertyInfo } from '../model'
|
|
3
|
-
import {
|
|
4
|
-
fetchDataAsText,
|
|
5
|
-
jsonToGeojsonFeature,
|
|
6
|
-
processItemProperties,
|
|
7
|
-
} from '../utils'
|
|
8
1
|
import { BaseFileReader } from './base-file'
|
|
9
2
|
|
|
10
|
-
export function parseCsv(text: string): {
|
|
11
|
-
items: DataItem[]
|
|
12
|
-
properties: PropertyInfo[]
|
|
13
|
-
} {
|
|
14
|
-
// first parse the header to guess the delimiter
|
|
15
|
-
// note that we do that to not rely on Papaparse logic for guessing delimiter
|
|
16
|
-
let delimiter
|
|
17
|
-
try {
|
|
18
|
-
const header = text.split('\n')[0]
|
|
19
|
-
const result = Papa.parse(header, {
|
|
20
|
-
header: false,
|
|
21
|
-
})
|
|
22
|
-
delimiter = result.meta.delimiter
|
|
23
|
-
} catch (e) {
|
|
24
|
-
throw new Error('CSV parsing failed: the delimiter could not be guessed')
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const parsed = Papa.parse(text, {
|
|
28
|
-
header: true,
|
|
29
|
-
skipEmptyLines: true,
|
|
30
|
-
delimiter,
|
|
31
|
-
})
|
|
32
|
-
if (parsed.errors.length) {
|
|
33
|
-
throw new Error(
|
|
34
|
-
'CSV parsing failed for the following reasons:\n' +
|
|
35
|
-
parsed.errors
|
|
36
|
-
.map(
|
|
37
|
-
(error) =>
|
|
38
|
-
`* ${error.message} at row ${error.row}, column ${error.index}`
|
|
39
|
-
)
|
|
40
|
-
.join('\n')
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const items = (parsed.data as any[]).map(jsonToGeojsonFeature)
|
|
45
|
-
return processItemProperties(items, true)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
3
|
export class CsvReader extends BaseFileReader {
|
|
49
|
-
|
|
50
|
-
|
|
4
|
+
async getLoadQuery() {
|
|
5
|
+
// first we get a list of columns hich have a detected type of VARCHAR
|
|
6
|
+
// then we make sure that for those columns, we don't cast an empty string to null; instead we want to keep the empty string
|
|
7
|
+
return `
|
|
8
|
+
SET VARIABLE strColumns = (SELECT list(name) FROM (SELECT unnest(Columns, recursive := true) FROM sniff_csv("${this.url}")) WHERE type = 'VARCHAR');
|
|
9
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM read_csv("${this.url}",
|
|
10
|
+
force_not_null = getvariable('strColumns'),
|
|
11
|
+
auto_type_candidates = ['NULL', 'BOOLEAN', 'INTEGER', 'DOUBLE', 'DATE', 'VARCHAR']
|
|
12
|
+
);`
|
|
51
13
|
}
|
|
52
14
|
}
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import { DataItem, PropertyInfo } from '../model'
|
|
2
|
-
import {
|
|
3
|
-
fetchDataAsArrayBuffer,
|
|
4
|
-
jsonToGeojsonFeature,
|
|
5
|
-
processItemProperties,
|
|
6
|
-
} from '../utils'
|
|
7
1
|
import { BaseFileReader } from './base-file'
|
|
2
|
+
import { fetchDataAsArrayBuffer } from '../utils'
|
|
8
3
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
4
|
+
export class ExcelReader extends BaseFileReader {
|
|
5
|
+
protected async getLoadQuery(): Promise<string> {
|
|
6
|
+
// we download the file as an array buffer first, in order to be able to check if it's an XLS file
|
|
7
|
+
let buffer = await fetchDataAsArrayBuffer(this.url, this.cacheEnabled)
|
|
8
|
+
const bufferHandle = `B${this.datasetId}`
|
|
9
|
+
|
|
10
|
+
// checking against the magic number at the beginning of XLS files, see https://en.wikipedia.org/wiki/List_of_file_signatures
|
|
11
|
+
const magicNumber = new Uint8Array(buffer, 0, 8) // first 8 bytes
|
|
12
|
+
const isXls =
|
|
13
|
+
Array.from(magicNumber)
|
|
14
|
+
.map((n) => n.toString(16).toUpperCase())
|
|
15
|
+
.join(' ') === 'D0 CF 11 E0 A1 B1 1A E1'
|
|
16
|
+
|
|
17
|
+
// uh oh, this is an XLS file (not supported by duckdb); convert it to CSV using the xlsx package
|
|
18
|
+
if (isXls) {
|
|
19
|
+
buffer = await import('xlsx').then(({ read, utils }) => {
|
|
20
|
+
const workbook = read(buffer)
|
|
21
|
+
const json = utils.sheet_to_json(
|
|
22
|
+
workbook.Sheets[workbook.SheetNames[0]]
|
|
23
|
+
)
|
|
24
|
+
return new TextEncoder().encode(JSON.stringify(json)).buffer
|
|
25
|
+
})
|
|
24
26
|
}
|
|
25
|
-
|
|
26
|
-
})
|
|
27
|
-
}
|
|
27
|
+
const duckDbFn = isXls ? 'read_json' : 'read_xlsx'
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
await this.engine.registerData(bufferHandle, new Uint8Array(buffer))
|
|
30
|
+
return `
|
|
31
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM ${duckDbFn}("${bufferHandle}", ignore_errors = true);`
|
|
32
32
|
}
|
|
33
33
|
}
|
|
@@ -1,29 +1,10 @@
|
|
|
1
|
-
import { DataItem, PropertyInfo } from '../model'
|
|
2
|
-
import { fetchDataAsText, processItemProperties } from '../utils'
|
|
3
1
|
import { BaseFileReader } from './base-file'
|
|
4
2
|
|
|
5
|
-
/**
|
|
6
|
-
* This parser supports both Geojson Feature collections or arrays
|
|
7
|
-
* of Features
|
|
8
|
-
* @param text
|
|
9
|
-
*/
|
|
10
|
-
export function parseGeojson(text: string): {
|
|
11
|
-
items: DataItem[]
|
|
12
|
-
properties: PropertyInfo[]
|
|
13
|
-
} {
|
|
14
|
-
const parsed = JSON.parse(text)
|
|
15
|
-
const features =
|
|
16
|
-
parsed.type === 'FeatureCollection' ? parsed.features : parsed
|
|
17
|
-
if (!Array.isArray(features)) {
|
|
18
|
-
throw new Error(
|
|
19
|
-
'Could not parse GeoJSON, expected a features collection or an array of features at root level'
|
|
20
|
-
)
|
|
21
|
-
}
|
|
22
|
-
return processItemProperties(features)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
3
|
export class GeojsonReader extends BaseFileReader {
|
|
26
|
-
|
|
27
|
-
return
|
|
4
|
+
async getLoadQuery() {
|
|
5
|
+
return `
|
|
6
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM st_read("${this.url}",
|
|
7
|
+
allowed_drivers = ['GeoJSON']
|
|
8
|
+
);`
|
|
28
9
|
}
|
|
29
10
|
}
|
|
@@ -1,54 +1,10 @@
|
|
|
1
1
|
import { BaseFileReader } from './base-file'
|
|
2
|
-
import { DataItem, PropertyInfo } from '../model'
|
|
3
|
-
import { fetchDataAsText, processItemProperties } from '../utils'
|
|
4
|
-
import { GeoJSON, WFS } from 'ol/format.js'
|
|
5
|
-
import { WfsVersion } from '@camptocamp/ogc-client'
|
|
6
|
-
|
|
7
|
-
export function parseGml(
|
|
8
|
-
text: string,
|
|
9
|
-
namespace: string,
|
|
10
|
-
version: string
|
|
11
|
-
): {
|
|
12
|
-
items: DataItem[]
|
|
13
|
-
properties: PropertyInfo[]
|
|
14
|
-
} {
|
|
15
|
-
const splittedNamespace = namespace.split(':')
|
|
16
|
-
const regex = new RegExp(`xmlns:${splittedNamespace[0]}=["']([^'"]*)["']`)
|
|
17
|
-
const match = regex.exec(text)
|
|
18
|
-
|
|
19
|
-
if (match && match.length >= 2) {
|
|
20
|
-
const wf = new WFS({
|
|
21
|
-
featureNS: match[1],
|
|
22
|
-
featureType: splittedNamespace[1],
|
|
23
|
-
version: version,
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
let features
|
|
27
|
-
try {
|
|
28
|
-
features = wf.readFeatures(text)
|
|
29
|
-
} catch (e) {
|
|
30
|
-
throw Error("Couldn't parse WFS with GML features")
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const geojsonItem = new GeoJSON().writeFeaturesObject(features)
|
|
34
|
-
return processItemProperties(geojsonItem.features, true)
|
|
35
|
-
}
|
|
36
|
-
throw Error("Couldn't retrieve namespace url")
|
|
37
|
-
}
|
|
38
2
|
|
|
39
3
|
export class GmlReader extends BaseFileReader {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
) {
|
|
46
|
-
super(url)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
protected getData() {
|
|
50
|
-
return fetchDataAsText(this.url, this.cacheActive).then((text) =>
|
|
51
|
-
parseGml(text, this.namespace, this.version)
|
|
52
|
-
)
|
|
4
|
+
async getLoadQuery() {
|
|
5
|
+
return `
|
|
6
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM st_read("${this.url}",
|
|
7
|
+
allowed_drivers = ['GML']
|
|
8
|
+
);`
|
|
53
9
|
}
|
|
54
10
|
}
|
|
@@ -1,28 +1,10 @@
|
|
|
1
|
-
import { DataItem, PropertyInfo } from '../model'
|
|
2
|
-
import {
|
|
3
|
-
fetchDataAsText,
|
|
4
|
-
jsonToGeojsonFeature,
|
|
5
|
-
processItemProperties,
|
|
6
|
-
} from '../utils'
|
|
7
1
|
import { BaseFileReader } from './base-file'
|
|
8
2
|
|
|
9
|
-
/**
|
|
10
|
-
* This parser only supports arrays of simple flat objects with properties
|
|
11
|
-
* @param text
|
|
12
|
-
*/
|
|
13
|
-
export function parseJson(text: string): {
|
|
14
|
-
items: DataItem[]
|
|
15
|
-
properties: PropertyInfo[]
|
|
16
|
-
} {
|
|
17
|
-
const parsed = JSON.parse(text) as any[]
|
|
18
|
-
if (!Array.isArray(parsed)) {
|
|
19
|
-
throw new Error('Could not parse JSON, expected an array at root level')
|
|
20
|
-
}
|
|
21
|
-
return processItemProperties(parsed.map(jsonToGeojsonFeature))
|
|
22
|
-
}
|
|
23
|
-
|
|
24
3
|
export class JsonReader extends BaseFileReader {
|
|
25
|
-
|
|
26
|
-
return
|
|
4
|
+
async getLoadQuery() {
|
|
5
|
+
return `
|
|
6
|
+
CREATE TABLE ${this.datasetId} AS SELECT * FROM read_json("${this.url}",
|
|
7
|
+
maximum_object_size = 536870912 -- 500MB
|
|
8
|
+
);`
|
|
27
9
|
}
|
|
28
10
|
}
|