geonetwork-ui 2.11.0-dev.96d0c6ce2 → 2.11.0-dev.a5c259d9e

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.
Files changed (67) hide show
  1. package/fesm2022/geonetwork-ui.mjs +971 -585
  2. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  3. package/index.d.ts +165 -59
  4. package/index.d.ts.map +1 -1
  5. package/package.json +11 -11
  6. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +43 -13
  7. package/src/libs/api/metadata-converter/src/lib/gn4/types/elasticsearch.model.ts +13 -1
  8. package/src/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.ts +23 -3
  9. package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +40 -16
  10. package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +12 -0
  11. package/src/libs/common/domain/src/lib/model/search/sort-by.model.ts +1 -5
  12. package/src/libs/common/domain/src/lib/repository/records-repository.interface.ts +2 -2
  13. package/src/libs/feature/dataviz/src/lib/chart-view/chart-view.component.ts +3 -2
  14. package/src/libs/feature/dataviz/src/lib/geo-table-view/geo-table-view.component.ts +2 -1
  15. package/src/libs/feature/dataviz/src/lib/service/data.service.ts +22 -22
  16. package/src/libs/feature/map/src/lib/add-layer-from-file/add-layer-from-file.component.html +1 -0
  17. package/src/libs/feature/notifications/src/lib/notifications.service.ts +6 -4
  18. package/src/libs/feature/record/src/lib/state/mdview.actions.ts +4 -8
  19. package/src/libs/feature/record/src/lib/state/mdview.effects.ts +7 -16
  20. package/src/libs/feature/record/src/lib/state/mdview.facade.ts +1 -3
  21. package/src/libs/feature/record/src/lib/state/mdview.reducer.ts +4 -9
  22. package/src/libs/feature/record/src/lib/state/mdview.selectors.ts +2 -7
  23. package/src/libs/feature/router/src/lib/default/router.service.ts +1 -1
  24. package/src/libs/feature/search/src/lib/filter-dropdown/filter-dropdown.component.html +7 -0
  25. package/src/libs/feature/search/src/lib/filter-dropdown/filter-dropdown.component.ts +39 -0
  26. package/src/libs/feature/search/src/lib/sort-by/sort-by.component.ts +1 -1
  27. package/src/libs/feature/search/src/lib/utils/service/fields.service.ts +3 -1
  28. package/src/libs/feature/search/src/lib/utils/service/fields.ts +16 -1
  29. package/src/libs/ui/dataviz/src/lib/data-table/data-table.component.html +6 -7
  30. package/src/libs/ui/dataviz/src/lib/data-table/data-table.component.ts +31 -19
  31. package/src/libs/ui/dataviz/src/lib/data-table/data-table.fixtures.ts +2 -2
  32. package/src/libs/ui/inputs/src/index.ts +1 -0
  33. package/src/libs/ui/inputs/src/lib/drag-and-drop-file-input/drag-and-drop-file-input.component.css +1 -0
  34. package/src/libs/ui/inputs/src/lib/drag-and-drop-file-input/drag-and-drop-file-input.component.html +20 -7
  35. package/src/libs/ui/inputs/src/lib/drag-and-drop-file-input/drag-and-drop-file-input.component.ts +46 -5
  36. package/src/libs/ui/inputs/src/lib/spatial-extent-dropdown/spatial-extent-dropdown.component.css +0 -0
  37. package/src/libs/ui/inputs/src/lib/spatial-extent-dropdown/spatial-extent-dropdown.component.html +117 -0
  38. package/src/libs/ui/inputs/src/lib/spatial-extent-dropdown/spatial-extent-dropdown.component.ts +191 -0
  39. package/src/libs/ui/map/src/lib/components/map-container/map-container.component.ts +4 -5
  40. package/src/libs/util/app-config/src/lib/app-config.ts +3 -0
  41. package/src/libs/util/app-config/src/lib/model.ts +1 -0
  42. package/src/libs/util/data-fetcher/src/lib/data-fetcher.ts +19 -22
  43. package/src/libs/util/data-fetcher/src/lib/engine/duckdb.ts +185 -0
  44. package/src/libs/util/data-fetcher/src/lib/engine/results.ts +63 -0
  45. package/src/libs/util/data-fetcher/src/lib/{sql-utils.ts → engine/sql-utils.ts} +28 -13
  46. package/src/libs/util/data-fetcher/src/lib/model.ts +2 -1
  47. package/src/libs/util/data-fetcher/src/lib/readers/base-file.ts +53 -38
  48. package/src/libs/util/data-fetcher/src/lib/readers/base.ts +11 -0
  49. package/src/libs/util/data-fetcher/src/lib/readers/csv.ts +9 -47
  50. package/src/libs/util/data-fetcher/src/lib/readers/excel.ts +27 -27
  51. package/src/libs/util/data-fetcher/src/lib/readers/geojson.ts +5 -24
  52. package/src/libs/util/data-fetcher/src/lib/readers/gml.ts +5 -49
  53. package/src/libs/util/data-fetcher/src/lib/readers/json.ts +5 -23
  54. package/src/libs/util/data-fetcher/src/lib/readers/wfs.ts +184 -128
  55. package/src/libs/util/data-fetcher/src/lib/utils.ts +0 -143
  56. package/src/libs/util/shared/src/lib/utils/file.ts +15 -0
  57. package/src/libs/util/shared/src/lib/utils/index.ts +1 -0
  58. package/tailwind.base.css +5 -0
  59. package/translations/de.json +11 -1
  60. package/translations/en.json +11 -1
  61. package/translations/es.json +10 -0
  62. package/translations/fr.json +11 -1
  63. package/translations/it.json +11 -1
  64. package/translations/nl.json +10 -0
  65. package/translations/pt.json +10 -0
  66. package/translations/sk.json +11 -1
  67. package/src/libs/util/data-fetcher/src/lib/readers/base-cache.ts +0 -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
- * This will read the first sheet of the excel workbook and expect the first
11
- * line to contain the properties names
12
- * @param buffer
13
- */
14
- export function parseExcel(buffer: ArrayBuffer): Promise<{
15
- items: DataItem[]
16
- properties: PropertyInfo[]
17
- }> {
18
- return import('xlsx').then(({ read, utils }) => {
19
- const workbook = read(buffer)
20
- const sheet = workbook.Sheets[workbook.SheetNames[0]]
21
- let json = utils.sheet_to_json(sheet)
22
- if (!json.length) {
23
- json = []
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
- return processItemProperties(json.map(jsonToGeojsonFeature), true)
26
- })
27
- }
27
+ const duckDbFn = isXls ? 'read_json' : 'read_xlsx'
28
28
 
29
- export class ExcelReader extends BaseFileReader {
30
- getData() {
31
- return fetchDataAsArrayBuffer(this.url, this.cacheActive).then(parseExcel)
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
- getData() {
27
- return fetchDataAsText(this.url, this.cacheActive).then(parseGeojson)
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
- constructor(
41
- protected url: string,
42
- protected namespace: string,
43
- protected version: WfsVersion,
44
- protected cacheActive = true
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
- getData() {
26
- return fetchDataAsText(this.url, this.cacheActive).then(parseJson)
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
  }
@@ -1,14 +1,58 @@
1
- import { EndpointError, WfsEndpoint, WfsVersion } from '@camptocamp/ogc-client'
2
- import { DataItem, DatasetInfo, FetchError, PropertyInfo } from '../model'
3
1
  import {
4
- fetchDataAsText,
5
- getJsonDataItemsProxy,
6
- jsonToGeojsonFeature,
7
- } from '../utils'
8
- import { GmlReader, parseGml } from './gml'
9
- import { GeojsonReader, parseGeojson } from './geojson'
10
- import { BaseCacheReader } from './base-cache'
11
- import { generateSqlQuery } from '../sql-utils'
2
+ EndpointError,
3
+ WfsEndpoint,
4
+ WfsFeatureTypeFull,
5
+ } from '@camptocamp/ogc-client'
6
+ import { DataItem, DatasetInfo, FetchError, PropertyInfo } from '../model'
7
+ import { fetchDataAsText } from '../utils'
8
+ import WFS from 'ol/format/WFS'
9
+ import GeoJSON from 'ol/format/GeoJSON'
10
+ import Feature from 'ol/Feature'
11
+ import { GeojsonReader } from './geojson'
12
+ import { GmlReader } from './gml'
13
+ import { BaseReader } from './base'
14
+
15
+ const formatGeojson = new GeoJSON()
16
+
17
+ export function parseGeojson(text: string): DataItem[] {
18
+ const parsed = JSON.parse(text)
19
+ const features =
20
+ parsed.type === 'FeatureCollection' ? parsed.features : parsed
21
+ if (!Array.isArray(features)) {
22
+ throw new Error(
23
+ 'Could not parse GeoJSON, expected a features collection or an array of features at root level'
24
+ )
25
+ }
26
+ return features
27
+ }
28
+
29
+ export function parseGml(
30
+ text: string,
31
+ featureType: string,
32
+ version: string
33
+ ): DataItem[] {
34
+ const parts = featureType.split(':')
35
+ const regex = new RegExp(`xmlns:${parts[0]}=["']([^'"]*)["']`)
36
+ const match = regex.exec(text)
37
+ if (match && match.length >= 2) {
38
+ const wfs = new WFS({
39
+ featureNS: match[1],
40
+ featureType: parts[1],
41
+ version: version,
42
+ })
43
+ let features: Feature[]
44
+ try {
45
+ features = wfs.readFeatures(text)
46
+ } catch (e: unknown) {
47
+ throw Error(
48
+ `Couldn't parse WFS with GML features: ${(e as Error).message}`
49
+ )
50
+ }
51
+ const geojsonItem = formatGeojson.writeFeaturesObject(features)
52
+ return geojsonItem.features
53
+ }
54
+ throw Error("Couldn't retrieve namespace url")
55
+ }
12
56
 
13
57
  export async function getWfsEndpoint(wfsUrl: string): Promise<WfsEndpoint> {
14
58
  try {
@@ -36,151 +80,163 @@ export async function getWfsEndpoint(wfsUrl: string): Promise<WfsEndpoint> {
36
80
  }
37
81
  }
38
82
 
39
- export class WfsReader extends BaseCacheReader {
40
- endpoint: WfsEndpoint
41
- featureTypeName: string
42
- version: WfsVersion
43
-
44
- constructor(
45
- url: string,
46
- wfsEndpoint: WfsEndpoint,
47
- featureTypeName: string,
48
- cacheActive?: boolean
49
- ) {
50
- super(url, cacheActive)
51
- this.endpoint = wfsEndpoint
52
- this.featureTypeName = featureTypeName
53
- this.version = this.endpoint.getVersion()
83
+ export class WfsReader extends BaseReader {
84
+ endpoint: Promise<WfsEndpoint>
85
+ featureType: Promise<WfsFeatureTypeFull>
86
+
87
+ /**
88
+ * This dataset reader will read the whole data as geojson or gml instead of
89
+ * using the WFS protocol; it is used in the following situations:
90
+ * - the endpoint does not support pagination
91
+ * - aggregations or grouping are set on the dataset (i.e. for chart view)
92
+ */
93
+ backupReader_: Promise<BaseReader>
94
+
95
+ constructor(url: string, featureTypeName: string) {
96
+ super(url)
97
+ this.endpoint = getWfsEndpoint(url)
98
+
99
+ this.featureType = this.endpoint
100
+ .then((endpoint) => {
101
+ const featureTypes = endpoint.getFeatureTypes()
102
+ return endpoint.getFeatureTypeFull(
103
+ featureTypes.length === 1 && !featureTypeName
104
+ ? featureTypes[0].name
105
+ : featureTypeName
106
+ )
107
+ })
108
+ .then((featureType) => {
109
+ if (!featureType) {
110
+ throw new Error('wfs.featuretype.notfound')
111
+ }
112
+ return featureType
113
+ })
54
114
  }
55
115
 
56
- get properties(): Promise<PropertyInfo[]> {
57
- return this.endpoint
58
- .getFeatureTypeFull(this.featureTypeName)
59
- .then((featureType) =>
60
- Object.keys(featureType.properties).map((prop) => {
61
- const originalType = featureType.properties[prop]
62
- const type =
63
- originalType === 'float' || originalType === 'integer'
64
- ? 'number'
65
- : (originalType as PropertyInfo['type']) // FIXME: ogc-client typing is incorrect, should be a string union
66
- return {
67
- name: prop,
68
- label: prop,
69
- type,
116
+ get backupReader(): Promise<BaseReader> {
117
+ if (this.backupReader_) {
118
+ return this.backupReader_
119
+ }
120
+
121
+ this.backupReader_ = Promise.all([this.endpoint, this.featureType]).then(
122
+ ([endpoint, featureType]) => {
123
+ let reader: BaseReader
124
+ if (endpoint.supportsJson(featureType.name)) {
125
+ reader = new GeojsonReader(
126
+ endpoint.getFeatureUrl(featureType.name, {
127
+ asJson: true,
128
+ outputCrs: 'EPSG:4326',
129
+ })
130
+ )
131
+ } else {
132
+ if (
133
+ featureType.outputFormats.find((f) =>
134
+ f.toLowerCase().includes('gml')
135
+ ) &&
136
+ (featureType.defaultCrs === 'EPSG:4326' ||
137
+ featureType.otherCrs?.includes('EPSG:4326'))
138
+ ) {
139
+ reader = new GmlReader(
140
+ endpoint.getFeatureUrl(featureType.name, {
141
+ outputFormat: featureType.outputFormats.find((f) =>
142
+ f.toLowerCase().includes('gml')
143
+ ),
144
+ outputCrs: 'EPSG:4326',
145
+ })
146
+ )
70
147
  }
71
- })
72
- )
148
+ }
149
+ reader.enableCache(this.cacheEnabled)
150
+ reader.load()
151
+ return reader
152
+ }
153
+ )
154
+ return this.backupReader_
155
+ }
156
+
157
+ get properties(): Promise<PropertyInfo[]> {
158
+ return this.featureType.then((featureType) =>
159
+ Object.keys(featureType.properties).map((prop) => {
160
+ const originalType = featureType.properties[prop]
161
+ let type: PropertyInfo['type']
162
+ if (originalType === 'float' || originalType === 'integer') {
163
+ type = 'number'
164
+ } else if (originalType === 'boolean') {
165
+ type = 'string' // we don't handle booleans yet in the data fetcher
166
+ } else {
167
+ type = originalType
168
+ }
169
+ return {
170
+ name: prop,
171
+ label: prop,
172
+ type,
173
+ }
174
+ })
175
+ )
73
176
  }
74
177
 
75
178
  get info(): Promise<DatasetInfo> {
76
- return this.endpoint.getFeatureTypeFull(this.featureTypeName).then(
179
+ return this.featureType.then(
77
180
  (result) =>
78
181
  ({
79
182
  itemsCount: result.objectCount,
183
+ hasGeometry: !!result.geometryName,
80
184
  }) as DatasetInfo
81
185
  )
82
186
  }
83
187
 
84
- static async createReader(wfsUrlEndpoint: string, featureTypeName?: string) {
85
- const wfsEndpoint = await getWfsEndpoint(wfsUrlEndpoint)
86
- const featureTypes = wfsEndpoint.getFeatureTypes()
87
- const featureType = wfsEndpoint.getFeatureTypeSummary(
88
- featureTypes.length === 1 && !featureTypeName
89
- ? featureTypes[0].name
90
- : featureTypeName
91
- )
92
- if (!featureType) {
93
- throw new Error('wfs.featuretype.notfound')
94
- }
188
+ load() {
189
+ // Nothing to load for Wfs
190
+ }
95
191
 
96
- if (wfsEndpoint.supportsStartIndex()) {
97
- return new WfsReader(wfsUrlEndpoint, wfsEndpoint, featureType.name)
98
- } else if (wfsEndpoint.supportsJson(featureType.name)) {
99
- return new GeojsonReader(
100
- wfsEndpoint.getFeatureUrl(featureType.name, {
101
- asJson: true,
102
- outputCrs: 'EPSG:4326',
103
- })
104
- )
105
- } else {
106
- if (
107
- featureType.outputFormats.find((f) =>
108
- f.toLowerCase().includes('gml')
109
- ) &&
110
- (featureType.defaultCrs === 'EPSG:4326' ||
111
- featureType.otherCrs?.includes('EPSG:4326'))
112
- ) {
113
- return new GmlReader(
114
- wfsEndpoint.getFeatureUrl(featureType.name, {
115
- outputFormat: featureType.outputFormats.find((f) =>
116
- f.toLowerCase().includes('gml')
117
- ),
118
- outputCrs: 'EPSG:4326',
119
- }),
120
- featureType.name,
121
- wfsEndpoint.getVersion()
122
- )
192
+ async read(): Promise<DataItem[]> {
193
+ const endpoint = await this.endpoint
194
+ const featureType = await this.featureType
195
+
196
+ // if we can't use the WFS protocol we fall back to the backup reader
197
+ if (this.aggregations || this.groupedBy || !endpoint.supportsStartIndex()) {
198
+ const backupReader = await this.backupReader
199
+ backupReader.selectAll()
200
+ if (this.selected) {
201
+ backupReader.select(...this.selected)
202
+ }
203
+ if (this.aggregations) {
204
+ backupReader.aggregate(...this.aggregations)
205
+ }
206
+ if (this.groupedBy) {
207
+ backupReader.groupBy(...this.groupedBy)
208
+ }
209
+ if (this.sort) {
210
+ backupReader.orderBy(...this.sort)
123
211
  }
124
- throw new Error('wfs.geojsongml.notsupported')
212
+ if (this.startIndex !== null && this.count !== null) {
213
+ backupReader.limit(this.startIndex, this.count)
214
+ }
215
+ return backupReader.read()
125
216
  }
126
- }
127
217
 
128
- public async getData(aggregation?, groupedBy?) {
129
- if (aggregation || groupedBy) {
130
- return { items: await this.getQueryData() }
131
- }
132
- const asJson = this.endpoint.supportsJson(this.featureTypeName)
218
+ const asJson = endpoint.supportsJson(featureType.name)
133
219
  const attributes = this.selected ?? undefined
134
- let url = this.endpoint.getFeatureUrl(this.featureTypeName, {
220
+ let sortBy = null
221
+ if (this.sort) {
222
+ const mapSort = (s) => [s[0] === 'desc' ? 'D' : 'A', s[1]]
223
+ sortBy = Array.isArray(this.sort[0])
224
+ ? this.sort.map(mapSort)
225
+ : mapSort(this.sort)
226
+ }
227
+ const url = endpoint.getFeatureUrl(featureType.name, {
135
228
  ...(this.startIndex !== null && { startIndex: this.startIndex }),
136
229
  ...(this.count !== null && { maxFeatures: this.count }),
137
230
  asJson,
138
231
  outputCrs: 'EPSG:4326',
139
232
  attributes,
140
- // sortBy: this.sort // TODO: no sort in ogc-client?
233
+ sortBy,
141
234
  })
142
235
 
143
- if (Array.isArray(this.sort) && this.sort.length > 0) {
144
- const finalUrl = new URL(url)
145
- const sorts = this.sort
146
- .map(
147
- (fieldSort) => `${fieldSort[1]}+${fieldSort[0] === 'asc' ? 'A' : 'D'}`
148
- )
149
- .join(',')
150
- // Direct update on string url to prevent encoding of +A and +D
151
- url = `${url}${finalUrl.search ? '&' : ''}SORTBY=${sorts}`
152
- }
153
-
154
- return fetchDataAsText(url, this.cacheActive).then((text) =>
236
+ return fetchDataAsText(url, this.cacheEnabled).then((text) =>
155
237
  asJson
156
238
  ? parseGeojson(text)
157
- : parseGml(text, this.featureTypeName, this.version)
158
- )
159
- }
160
-
161
- public async getQueryData() {
162
- const items = (await this.getData()).items
163
- const jsonItems = getJsonDataItemsProxy(items)
164
- const query = generateSqlQuery(
165
- this.selected,
166
- this.filter,
167
- this.sort,
168
- this.startIndex,
169
- this.count,
170
- this.groupedBy,
171
- this.aggregations
172
- )
173
- const result: any[] = await import('alasql').then((module) =>
174
- module.default(query, [jsonItems])
239
+ : parseGml(text, featureType.name, endpoint.getVersion())
175
240
  )
176
- return result.map(jsonToGeojsonFeature)
177
- }
178
-
179
- load() {
180
- // Nothing to load for Wfs
181
- }
182
-
183
- async read(): Promise<DataItem[]> {
184
- return (await this.getData(this.aggregations, this.groupedBy)).items
185
241
  }
186
242
  }