@opengis/gis 0.2.1 → 0.2.3
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/dist/index.css +1 -1
- package/dist/index.js +4617 -3764
- package/dist/index.umd.cjs +57 -37
- package/module/test/layer/bp1.yml +33 -0
- package/module/test/layer/individual.yml +54 -0
- package/module/test/map/addr.yml +21 -0
- package/module/test/map/bp_myo.json +15 -12
- package/module/test/map/bpf.json +44 -0
- package/module/test/map/mbd.json +13 -13
- package/module/test/map/ts.json +15 -11
- package/package.json +11 -5
- package/plugin.js +4 -2
- package/server/plugins/vite.js +3 -7
- package/server/routes/gis/services/get.services.col.js +19 -18
- package/server/routes/gis/services/get.services.js +60 -55
- package/server/routes/map/controllers/layerList.js +42 -32
- package/server/routes/map/controllers/mapFormat.js +76 -116
- package/server/routes/map/maps/get.map.js +7 -4
- package/server/routes/map/vtile1.js +76 -94
- package/module/test/map/address/addr.yml +0 -6
- package/module/test/map/address/index.yml +0 -22
- package/module/test/map/address/street.yml +0 -16
- package/module/test/map/address2/addr.json +0 -9
- package/module/test/map/address2/index.json +0 -35
- package/module/test/map/address2/street.json +0 -19
- package/module/test/map/address3.yml +0 -52
- package/module/test/map/address4.json +0 -34
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
source_path: data_bp_myo.bp
|
|
2
|
+
name: Будівельні паспорти Template
|
|
3
|
+
visible: true
|
|
4
|
+
style:
|
|
5
|
+
type: point
|
|
6
|
+
color: '#d970d5'
|
|
7
|
+
width: 2
|
|
8
|
+
radius: 10
|
|
9
|
+
border: 1
|
|
10
|
+
opacity: 0.4
|
|
11
|
+
popup:
|
|
12
|
+
- ua: Назва замовника
|
|
13
|
+
name: bp_customer_name
|
|
14
|
+
meta: title
|
|
15
|
+
- label: Реєстраційний номер БП
|
|
16
|
+
name: bp_code
|
|
17
|
+
format: badge
|
|
18
|
+
- label: Адреса
|
|
19
|
+
name: address
|
|
20
|
+
card:
|
|
21
|
+
- label: Реєстраційний номер БП
|
|
22
|
+
name: bp_code
|
|
23
|
+
- ua: Адреса
|
|
24
|
+
name: address
|
|
25
|
+
- ua: Вид будівництва
|
|
26
|
+
data: bp_build_type
|
|
27
|
+
name: bp_build_type
|
|
28
|
+
- ua: Назва замовника
|
|
29
|
+
name: bp_customer_name
|
|
30
|
+
- ua: Статус документа
|
|
31
|
+
data: doc_status
|
|
32
|
+
name: bp_doc_status
|
|
33
|
+
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Title: Parcel Polygon
|
|
2
|
+
|
|
3
|
+
name: ФОП
|
|
4
|
+
source_path: economy_profile.individual
|
|
5
|
+
query: 1=1
|
|
6
|
+
|
|
7
|
+
style:
|
|
8
|
+
type: point
|
|
9
|
+
color: orange
|
|
10
|
+
width: 1
|
|
11
|
+
border: 1
|
|
12
|
+
opacity: 0.6
|
|
13
|
+
stroke: "#eee"
|
|
14
|
+
|
|
15
|
+
popup:
|
|
16
|
+
- name: registration_date
|
|
17
|
+
meta: title
|
|
18
|
+
- ua: Назва замовника
|
|
19
|
+
name: bp_customer_name
|
|
20
|
+
meta: title
|
|
21
|
+
- label: Реєстраційний номер БП
|
|
22
|
+
name: bp_code
|
|
23
|
+
format: badge
|
|
24
|
+
- label: Адреса
|
|
25
|
+
name: address
|
|
26
|
+
|
|
27
|
+
card:
|
|
28
|
+
- label: Адреса
|
|
29
|
+
name: address
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
filters:
|
|
33
|
+
- name: registration_date
|
|
34
|
+
label: Дата реєстрації
|
|
35
|
+
type: date
|
|
36
|
+
- name: fop_status
|
|
37
|
+
label: Статус
|
|
38
|
+
type: Autocomplete
|
|
39
|
+
data: fop_status
|
|
40
|
+
|
|
41
|
+
- name: address_id
|
|
42
|
+
label: Адреса
|
|
43
|
+
type: Autocomplete
|
|
44
|
+
data: reg_address_id
|
|
45
|
+
- name: kved_main
|
|
46
|
+
label: КВЕД (основний)
|
|
47
|
+
type: Autocomplete
|
|
48
|
+
data: kved_main
|
|
49
|
+
- name: before_local_budget
|
|
50
|
+
label: Податковий борг перед місцевим бюджетом
|
|
51
|
+
type: Range
|
|
52
|
+
- name: before_state_budget
|
|
53
|
+
label: Податковий борг перед державним бюджетом
|
|
54
|
+
type: Range
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
history: true
|
|
2
|
+
name: Адресний реєстр
|
|
3
|
+
height: calc(100vh - 65px)
|
|
4
|
+
center:
|
|
5
|
+
- 34.65450
|
|
6
|
+
- 48.51174
|
|
7
|
+
zoom: 11
|
|
8
|
+
layers:
|
|
9
|
+
- faafbea5263a
|
|
10
|
+
widgets:
|
|
11
|
+
- type: search
|
|
12
|
+
position: top-left
|
|
13
|
+
- type: info
|
|
14
|
+
position: top-left
|
|
15
|
+
config:
|
|
16
|
+
title: Адресний реєстр
|
|
17
|
+
content: "<p style='font-size: 14px; color: #34495E;'>Карта адресного реєстру відображає офіційно зареєстровані адреси на території громади або населеного пункту. До складу інформації входять дані про вулиці, будинки, типи об'єктів (житлові, комерційні, адміністративні тощо), а також структуровані компоненти адреси: назва вулиці, номер будинку, корпус, літера, тощо.</p>"
|
|
18
|
+
- type: layers
|
|
19
|
+
position: top-left
|
|
20
|
+
- type: basemaps
|
|
21
|
+
position: bottom-left
|
|
@@ -7,7 +7,11 @@
|
|
|
7
7
|
48.51174
|
|
8
8
|
],
|
|
9
9
|
"zoom": 11,
|
|
10
|
-
"
|
|
10
|
+
"layers": [
|
|
11
|
+
"3c95e341465d",
|
|
12
|
+
"dbcb186818e3"
|
|
13
|
+
],
|
|
14
|
+
"widgets": [
|
|
11
15
|
{
|
|
12
16
|
"type": "search",
|
|
13
17
|
"position": "top-left"
|
|
@@ -15,14 +19,18 @@
|
|
|
15
19
|
{
|
|
16
20
|
"type": "info",
|
|
17
21
|
"position": "top-left",
|
|
18
|
-
"config":{
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
"config": {
|
|
23
|
+
"title": "Містобудівна документація",
|
|
24
|
+
"content": "<p style='font-size: 14px; color: #34495E;'>Затверджені текстові і графічні матеріали, якими регулюється планування, забудова та інше використання територій.</p>"
|
|
21
25
|
}
|
|
22
26
|
},
|
|
23
|
-
|
|
27
|
+
{
|
|
24
28
|
"type": "layers",
|
|
25
|
-
"position": "top-left"
|
|
29
|
+
"position": "top-left",
|
|
30
|
+
"config": {
|
|
31
|
+
"title": "Шари мапи",
|
|
32
|
+
"description": "Доступні шари мапи містобудівна документація"
|
|
33
|
+
}
|
|
26
34
|
},
|
|
27
35
|
{
|
|
28
36
|
"type": "basemaps",
|
|
@@ -32,10 +40,5 @@
|
|
|
32
40
|
"type": "legend",
|
|
33
41
|
"position": "bottom-right"
|
|
34
42
|
}
|
|
35
|
-
],
|
|
36
|
-
"old":["bp","3c95e341465d"],
|
|
37
|
-
"layers": [
|
|
38
|
-
"3c95e341465d",
|
|
39
|
-
"dbcb186818e3"
|
|
40
43
|
]
|
|
41
|
-
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"history": true,
|
|
3
|
+
"height": "calc(100vh - 65px)",
|
|
4
|
+
"center": [
|
|
5
|
+
34.65450,
|
|
6
|
+
48.51174
|
|
7
|
+
],
|
|
8
|
+
"layers":["bp1"],
|
|
9
|
+
"widgets": [
|
|
10
|
+
{
|
|
11
|
+
"type": "info",
|
|
12
|
+
"position": "top-left",
|
|
13
|
+
"config": {
|
|
14
|
+
"title": "Будівельні паспорти",
|
|
15
|
+
"content": "<p style='font-size: 14px; color: #34495E;'>Затверджені текстові і графічні матеріали, якими регулюється планування, забудова та інше використання територій.</p>"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"type": "layers",
|
|
20
|
+
"position": "top-left",
|
|
21
|
+
"visible": true
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"type": "dataset",
|
|
25
|
+
"position": "top-right",
|
|
26
|
+
"title": "Густота населення",
|
|
27
|
+
"config": {
|
|
28
|
+
"layer": "bp",
|
|
29
|
+
"attribute": "status"
|
|
30
|
+
},
|
|
31
|
+
"visible": true
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
{
|
|
36
|
+
"type": "basemaps",
|
|
37
|
+
"position": "bottom-left",
|
|
38
|
+
"title": "Базові карти",
|
|
39
|
+
"visible": true
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
}
|
package/module/test/map/mbd.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"history": true,
|
|
3
|
-
"height": "calc(100vh - 65px)",
|
|
4
|
-
"center": [
|
|
3
|
+
"height": "calc(100vh - 65px)",
|
|
4
|
+
"center": [
|
|
5
5
|
34.65450,
|
|
6
|
-
48.51174
|
|
6
|
+
48.51174
|
|
7
7
|
],
|
|
8
8
|
"layers":["9587e69d35fd"],
|
|
9
9
|
"widgets": [
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"config": {
|
|
14
14
|
"title": "Містобудівна документація",
|
|
15
15
|
"content": "<p style='font-size: 14px; color: #34495E;'>Затверджені текстові і графічні матеріали, якими регулюється планування, забудова та інше використання територій.</p>"
|
|
16
|
-
}
|
|
16
|
+
}
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
"type": "layers",
|
|
@@ -22,16 +22,16 @@
|
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
"type": "dataset",
|
|
25
|
-
"position": "top-
|
|
25
|
+
"position": "top-left",
|
|
26
26
|
"title": "Густота населення",
|
|
27
27
|
"config": {
|
|
28
|
-
"
|
|
29
|
-
"
|
|
28
|
+
"layer": "9587e69d35fd",
|
|
29
|
+
"list":[{"id":"status","text":"Статус" },{"id":"type_work_id","text":"Тип робіт"}]
|
|
30
30
|
},
|
|
31
31
|
"visible": true
|
|
32
32
|
},
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
|
|
34
|
+
|
|
35
35
|
{
|
|
36
36
|
"type": "legend",
|
|
37
37
|
"position": "bottom-right",
|
|
@@ -75,12 +75,12 @@
|
|
|
75
75
|
{
|
|
76
76
|
"type": "basemaps",
|
|
77
77
|
"position": "bottom-left",
|
|
78
|
-
"title": "Базові карти",
|
|
78
|
+
"title": "Базові карти",
|
|
79
79
|
"visible": true
|
|
80
80
|
}
|
|
81
|
-
|
|
81
|
+
|
|
82
82
|
],
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
"tools": [
|
|
85
85
|
"home",
|
|
86
86
|
"geolocation",
|
|
@@ -88,4 +88,4 @@
|
|
|
88
88
|
"area",
|
|
89
89
|
"print"
|
|
90
90
|
]
|
|
91
|
-
}
|
|
91
|
+
}
|
package/module/test/map/ts.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"history": true,
|
|
3
|
-
"height": "calc(100vh - 65px)",
|
|
4
|
-
"center": [
|
|
3
|
+
"height": "calc(100vh - 65px)",
|
|
4
|
+
"center": [
|
|
5
5
|
34.65450,
|
|
6
|
-
48.51174
|
|
6
|
+
48.51174
|
|
7
7
|
],
|
|
8
8
|
"zoom": 11,
|
|
9
9
|
"layers": ["ed67980cd690"],
|
|
@@ -13,31 +13,35 @@
|
|
|
13
13
|
"position": "top-left",
|
|
14
14
|
"config": {
|
|
15
15
|
"title": "Тимчасові споруди",
|
|
16
|
-
"content": "<p style='font-size: 14px; color: #34495E;'>Інформація про тимчасові споруди встановлені на території м. Кам'янське</p>"
|
|
16
|
+
"content": "<p style='font-size: 14px; color: #34495E;'>Інформація про тимчасові споруди встановлені на території м. Кам'янське</p>"
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
20
|
"type": "dataset",
|
|
21
21
|
"position": "top-left",
|
|
22
22
|
"config": {
|
|
23
|
-
"layer":"ed67980cd690",
|
|
24
|
-
"attribute":"
|
|
23
|
+
"layer":"ed67980cd690",
|
|
24
|
+
"attribute":"temp_structure_type",
|
|
25
|
+
"colors":{
|
|
26
|
+
"1":"#3a7a57",
|
|
27
|
+
"2":"#8e4484"
|
|
28
|
+
}
|
|
25
29
|
}
|
|
26
30
|
},
|
|
27
31
|
{
|
|
28
32
|
"type": "layers",
|
|
29
|
-
"visible":false
|
|
33
|
+
"visible":false
|
|
30
34
|
},
|
|
31
35
|
{
|
|
32
36
|
"type": "legend",
|
|
33
|
-
"position":"bottom-right"
|
|
37
|
+
"position":"bottom-right"
|
|
34
38
|
},
|
|
35
39
|
{
|
|
36
40
|
"type": "basemaps",
|
|
37
41
|
"position": "bottom-left",
|
|
38
|
-
"title": "Базові карти"
|
|
42
|
+
"title": "Базові карти"
|
|
39
43
|
}
|
|
40
|
-
],
|
|
44
|
+
],
|
|
41
45
|
"tools": [
|
|
42
46
|
"home",
|
|
43
47
|
"geolocation",
|
|
@@ -45,4 +49,4 @@
|
|
|
45
49
|
"area",
|
|
46
50
|
"print"
|
|
47
51
|
]
|
|
48
|
-
}
|
|
52
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengis/gis",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "Softpro",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|
|
18
18
|
"start1": "bun server",
|
|
19
|
+
"lint": "eslint src --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts",
|
|
20
|
+
"fix": "eslint src --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix",
|
|
19
21
|
"patch": "npm version patch && git push && npm publish",
|
|
20
22
|
"dev": "bun --hot server",
|
|
21
23
|
"front": "vite dev",
|
|
@@ -35,21 +37,25 @@
|
|
|
35
37
|
"carto": "0.16.3"
|
|
36
38
|
},
|
|
37
39
|
"peerDependencies": {
|
|
38
|
-
"@opengis/fastify-table": "^2.0.
|
|
40
|
+
"@opengis/fastify-table": "^2.0.32"
|
|
39
41
|
},
|
|
40
42
|
"resolutions": {
|
|
41
43
|
"rollup": "4.30.0"
|
|
42
44
|
},
|
|
43
45
|
"devDependencies": {
|
|
44
46
|
"@opengis/core": "^0.0.23",
|
|
45
|
-
"@opengis/fastify-table": "^2.0.
|
|
47
|
+
"@opengis/fastify-table": "^2.0.32",
|
|
46
48
|
"@opengis/filter": "^0.1.7",
|
|
47
|
-
"@opengis/form": "^0.0.
|
|
49
|
+
"@opengis/form": "^0.0.48",
|
|
48
50
|
"@opengis/table": "^0.0.27",
|
|
49
51
|
"@vitejs/plugin-vue": "^5.2.3",
|
|
50
52
|
"axios": "^1.11.0",
|
|
51
53
|
"eslint": "8.49.0",
|
|
52
54
|
"eslint-config-airbnb": "19.0.4",
|
|
55
|
+
"eslint-plugin-import": "^2.25.3",
|
|
56
|
+
"eslint-plugin-vue": "^9.17.0",
|
|
57
|
+
"@vue/eslint-config-typescript": "^12.0.0",
|
|
58
|
+
"vue-eslint-parser": "^10.2.0",
|
|
53
59
|
"lucide-vue-next": "^0.514.0",
|
|
54
60
|
"sass-embedded": "1.86.3",
|
|
55
61
|
"typescript": "^5.9.2",
|
|
@@ -58,4 +64,4 @@
|
|
|
58
64
|
"vue-router": "4.5.1",
|
|
59
65
|
"vuedraggable": "^4.1.0"
|
|
60
66
|
}
|
|
61
|
-
}
|
|
67
|
+
}
|
package/plugin.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import fp from 'fastify-plugin';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
config, addHook, getMeta, pgClients, execMigrations,
|
|
5
|
+
} from '@opengis/fastify-table/utils.js';
|
|
4
6
|
|
|
5
7
|
config.prefix = config.prefix || '/api';
|
|
6
8
|
|
|
@@ -38,4 +40,4 @@ async function plugin(app, opts = config) {
|
|
|
38
40
|
Object.assign(payload, { fields: columns?.map?.(({ name, title, dataTypeID }) => ({ name, title: title || name, type: columnType[pg?.pgType?.[dataTypeID] || 'text'] })).filter(el => el.type) });
|
|
39
41
|
});
|
|
40
42
|
}
|
|
41
|
-
export default fp(plugin)
|
|
43
|
+
export default fp(plugin);
|
package/server/plugins/vite.js
CHANGED
|
@@ -9,9 +9,8 @@ const isProduction = process.env.NODE_ENV === 'production' || config.production;
|
|
|
9
9
|
console.log({ isProduction });
|
|
10
10
|
|
|
11
11
|
async function plugin(fastify, opts) {
|
|
12
|
-
|
|
13
12
|
const viteServer = !isProduction ? await createServer({
|
|
14
|
-
root:
|
|
13
|
+
root: 'admin',
|
|
15
14
|
server: {
|
|
16
15
|
middlewareMode: true,
|
|
17
16
|
},
|
|
@@ -21,7 +20,6 @@ async function plugin(fastify, opts) {
|
|
|
21
20
|
const dir1 = process.cwd();
|
|
22
21
|
viteServer.watcher.add(dir1);
|
|
23
22
|
viteServer.watcher.on('all', (d, t) => {
|
|
24
|
-
|
|
25
23
|
if (!t.includes('module')) return;
|
|
26
24
|
console.log(d, t);
|
|
27
25
|
viteServer.ws.send({ type: 'full-reload' });
|
|
@@ -49,7 +47,7 @@ async function plugin(fastify, opts) {
|
|
|
49
47
|
const filePath = fs.existsSync(filePathDist) ? filePathDist : filePathAssets; // check dist or assets
|
|
50
48
|
const ext = path.extname(filePath);
|
|
51
49
|
|
|
52
|
-
if (!fs.existsSync(filePath)) return { status: 404, message: 'not found' }
|
|
50
|
+
if (!fs.existsSync(filePath)) return { status: 404, message: 'not found' };
|
|
53
51
|
const mime = {
|
|
54
52
|
'.js': 'text/javascript', '.css': 'text/css', '.woff2': 'application/font-woff', '.png': 'image/png', '.svg': 'image/svg+xml', '.jpg': 'image/jpg',
|
|
55
53
|
}[ext];
|
|
@@ -69,9 +67,7 @@ async function plugin(fastify, opts) {
|
|
|
69
67
|
if (!isProduction) return null; // admin vite
|
|
70
68
|
const stream = fs.createReadStream('admin/dist/index.html');
|
|
71
69
|
return reply.type('text/html').send(stream);
|
|
72
|
-
|
|
73
|
-
})
|
|
70
|
+
});
|
|
74
71
|
}
|
|
75
72
|
|
|
76
73
|
export default plugin;
|
|
77
|
-
|
|
@@ -1,32 +1,33 @@
|
|
|
1
|
-
import { metaFormat, pgClients } from
|
|
1
|
+
import { metaFormat, pgClients, getTemplate } from '@opengis/fastify-table/utils.js';
|
|
2
2
|
|
|
3
3
|
export default async function getServicesCol({ params = {}, pg = pgClients.client }, reply) {
|
|
4
|
-
|
|
4
|
+
const row = await getTemplate('layer', params.id) || await pg.query(`
|
|
5
5
|
SELECT
|
|
6
6
|
service_id, source_path, attributes
|
|
7
7
|
FROM gis.services where ${params.id ? 'service_id=$1' : '1=1'}
|
|
8
8
|
`, [params.id].filter(Boolean)).then(el => el.rows[0] || {});
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
if (!row.source_path) {
|
|
11
|
+
return reply.status(404).send({ code: 404, message: 'source not found' });
|
|
12
|
+
}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
const fields = await pg.query(` SELECT * FROM ${row.source_path} limit 0`).then(el => el.fields);
|
|
15
|
+
const field = fields.find(el => el.name === params.col);
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
if (!field) {
|
|
18
|
+
return reply.status(404).send({ message: { error: 'column not found', fields }, code: 404 });
|
|
19
|
+
}
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
where ${params.col} is not null group by ${params.col} order by count(*) desc limit 10`
|
|
23
|
-
).then(el => el.rows || []);
|
|
21
|
+
const rows = await pg.query(`SELECT ${params.col}::text as id, ${params.col}, count(*) FROM ${row.source_path}
|
|
22
|
+
where ${params.col} is not null group by ${params.col} order by count(*) desc limit 10`).then(el => el.rows || []);
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
const cls = row.attributes?.filter?.((col) => col.name && col.data && ['select', 'badge', 'tags'].includes(col.format)).reduce((acc, curr) => ({ ...acc, [curr.name]: curr.data }), {}) || {};
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
await metaFormat({ rows, table: row.source_path, cls });
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
const rows1 = rows.map(row => ({
|
|
29
|
+
...row[`${params.col}_data`], ...row, [`${params.col}_data`]: undefined, [params.col]: undefined,
|
|
30
|
+
}));
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
}
|
|
32
|
+
return reply.status(200).send({ rows: rows1, field, fields });
|
|
33
|
+
}
|
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
dataUpdate, getMeta, pgClients, yml2json, getTemplate,
|
|
3
|
+
} from '@opengis/fastify-table/utils.js';
|
|
2
4
|
|
|
3
5
|
const columnType = {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
text: 'text',
|
|
7
|
+
date: 'date',
|
|
8
|
+
bool: 'yes/no',
|
|
9
|
+
numeric: 'number',
|
|
10
|
+
integer: 'number',
|
|
11
|
+
'timestamp without time zone': 'date',
|
|
12
|
+
'timestamp with time zone': 'date',
|
|
11
13
|
};
|
|
12
14
|
|
|
13
15
|
export default async function getServices({ params = {}, pg = pgClients.client }, reply) {
|
|
14
|
-
|
|
16
|
+
const t = await getTemplate('layer', params.id);
|
|
17
|
+
if (t) return t;
|
|
18
|
+
if (!pg.tlist.includes('gis.services')) return { status: 404, message: 'not found' };
|
|
19
|
+
const rows = await pg.query(`
|
|
15
20
|
SELECT
|
|
16
21
|
service_id, service_key, name, description, keywords, category, holder, group_id, b.group_name, service_type,
|
|
17
22
|
source_type, service_url, source_path, query, geom_type, geometry_column, sql_list, attributes, filters,
|
|
@@ -22,58 +27,58 @@ export default async function getServices({ params = {}, pg = pgClients.client }
|
|
|
22
27
|
where ${params.id ? 'service_id=$1' : '1=1'}
|
|
23
28
|
`, [params.id].filter(Boolean)).then(el => el.rows || []);
|
|
24
29
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
if (params.id && !rows.length) {
|
|
31
|
+
return reply.status(404).send('service not found');
|
|
32
|
+
}
|
|
28
33
|
|
|
34
|
+
const totals = pg.queryCache ? await pg.queryCache('select json_object_agg(oid::regclass, reltuples) from pg_class')
|
|
35
|
+
.then(el => el.rows?.[0]?.json_object_agg || {}) : {};
|
|
29
36
|
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
if (params.id) {
|
|
38
|
+
const html = await pg.query('select body from admin.templates where template_id=$1', [params.id]).then(el => el.rows?.[0]?.body);
|
|
39
|
+
Object.assign(rows[0], { html });
|
|
40
|
+
}
|
|
32
41
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
42
|
+
rows.filter(row => row.source_path).forEach(row => {
|
|
43
|
+
Object.assign(row, { count: totals[row.source_path] || 0 });
|
|
44
|
+
});
|
|
37
45
|
|
|
38
|
-
|
|
39
|
-
Object.assign(row, { count: totals[row.source_path] || 0 });
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
const { columns = [] } = await getMeta({ pg, table: rows[0].source_path }) || {};
|
|
43
|
-
|
|
44
|
-
const fields = columns.map(({ name, dataTypeID, title }) => ({ name, type: columnType[pg.pgType?.[dataTypeID] || 'text'], label: title || name }));
|
|
45
|
-
|
|
46
|
-
const noCenterIds = rows.filter(row => !row.center && row.bbox).map(row => row.service_id);
|
|
47
|
-
|
|
48
|
-
const centers = noCenterIds.length ? await pg.query(`SELECT json_object_agg(service_id, st_pointonsurface(bbox)::json) FROM gis.services where service_id=any($1)`, [noCenterIds].filter(Boolean)).then(el => el.rows?.[0]?.json_object_agg || {}) : {};
|
|
49
|
-
|
|
50
|
-
await Promise.all(rows.filter(row => centers[row.service_id]).map(async (row) => {
|
|
51
|
-
// console.log('update service center', row.service_id, JSON.stringify(centers[row.service_id]));
|
|
52
|
-
await dataUpdate({ pg, id: row.service_id, table: 'gis.services', data: { center: centers[row.service_id] } });
|
|
53
|
-
Object.assign(row, { center: centers[row.service_id] });
|
|
54
|
-
}));
|
|
55
|
-
|
|
56
|
-
rows.forEach(row => Object.assign(row, {
|
|
57
|
-
center: row.center?.coordinates,
|
|
58
|
-
style: row.style ? yml2json(row.style) : undefined
|
|
59
|
-
}));
|
|
60
|
-
rows.filter(row => row.extent).forEach(row => Object.assign(row, {
|
|
61
|
-
extent: row.extent.match(/BOX\(([^)]+)\)/)?.[1]
|
|
62
|
-
?.replace?.(/ /g, ",")
|
|
63
|
-
?.split?.(",")
|
|
64
|
-
}));
|
|
46
|
+
const { columns = [] } = await getMeta({ pg, table: rows[0].source_path }) || {};
|
|
65
47
|
|
|
48
|
+
const fields = columns.map(({ name, dataTypeID, title }) => ({ name, type: columnType[pg.pgType?.[dataTypeID] || 'text'], label: title || name }));
|
|
66
49
|
|
|
67
|
-
|
|
68
|
-
filters: row.filters.map(filter => ({ ...filter, api: '/api/suggest/' + row.source_path + ':' + filter.name + (filter.data && filter.name !== filter.data ? `?sel=${filter.data}` : '') }))
|
|
69
|
-
}));
|
|
50
|
+
const noCenterIds = rows.filter(row => !row.center && row.bbox).map(row => row.service_id);
|
|
70
51
|
|
|
71
|
-
|
|
72
|
-
return reply.status(200).send({ ...rows[0], fields });
|
|
73
|
-
}
|
|
52
|
+
const centers = noCenterIds.length ? await pg.query('SELECT json_object_agg(service_id, st_pointonsurface(bbox)::json) FROM gis.services where service_id=any($1)', [noCenterIds].filter(Boolean)).then(el => el.rows?.[0]?.json_object_agg || {}) : {};
|
|
74
53
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
54
|
+
await Promise.all(rows.filter(row => centers[row.service_id]).map(async (row) => {
|
|
55
|
+
// console.log('update service center', row.service_id, JSON.stringify(centers[row.service_id]));
|
|
56
|
+
await dataUpdate({
|
|
57
|
+
pg, id: row.service_id, table: 'gis.services', data: { center: centers[row.service_id] },
|
|
78
58
|
});
|
|
79
|
-
}
|
|
59
|
+
Object.assign(row, { center: centers[row.service_id] });
|
|
60
|
+
}));
|
|
61
|
+
|
|
62
|
+
rows.forEach(row => Object.assign(row, {
|
|
63
|
+
center: row.center?.coordinates,
|
|
64
|
+
style: row.style ? yml2json(row.style) : undefined,
|
|
65
|
+
}));
|
|
66
|
+
rows.filter(row => row.extent).forEach(row => Object.assign(row, {
|
|
67
|
+
extent: row.extent.match(/BOX\(([^)]+)\)/)?.[1]
|
|
68
|
+
?.replace?.(/ /g, ',')
|
|
69
|
+
?.split?.(','),
|
|
70
|
+
}));
|
|
71
|
+
|
|
72
|
+
rows.filter(row => row.filters).forEach(row => Object.assign(row, {
|
|
73
|
+
filters: row.filters.map(filter => ({ ...filter, api: `/api/suggest/${row.source_path}:${filter.name}${filter.data && filter.name !== filter.data ? `?sel=${filter.data}` : ''}` })),
|
|
74
|
+
}));
|
|
75
|
+
|
|
76
|
+
if (params.id) {
|
|
77
|
+
return reply.status(200).send({ ...rows[0], fields });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return reply.status(200).send({
|
|
81
|
+
rows,
|
|
82
|
+
fields,
|
|
83
|
+
});
|
|
84
|
+
}
|