@opengis/gis 0.2.0 → 0.2.1

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 (33) hide show
  1. package/dist/index.css +1 -1
  2. package/dist/index.js +4018 -2967
  3. package/dist/index.umd.cjs +48 -38
  4. package/module/cls.json +2 -1
  5. package/module/gis/form/gis.maps.form.json +2 -2
  6. package/module/gis/form/gis.registers.form.json +8 -199
  7. package/module/gis/form/gis.services.form.json +11 -200
  8. package/module/gis/table/gis.maps.table.json +5 -7
  9. package/module/gis/table/gis.ogc_service.table.json +14 -3
  10. package/module/gis/table/gis.registers.table.json +2 -3
  11. package/module/gis/table/gis.services.table.json +19 -6
  12. package/module/test/cls/ts.temp_status.json +18 -0
  13. package/module/test/cls/ts.temp_type.json +10 -0
  14. package/module/test/map/bp_myo.json +10 -6
  15. package/module/test/select/address_id.json +3 -0
  16. package/module/test/select/address_id.sql +8 -0
  17. package/module/test/table/data_bp_myo.bp.table.json +123 -0
  18. package/package.json +4 -4
  19. package/server/migrations/ogc.sql +107 -0
  20. package/server/routes/gis/index.mjs +16 -2
  21. package/server/routes/gis/ogc/map.info.point.js +120 -0
  22. package/server/routes/gis/registers/funcs/classifiers.js +6 -3
  23. package/server/routes/gis/registers/funcs/handleRegistryRequest.js +15 -22
  24. package/server/routes/gis/registers/gis.registry.js +3 -2
  25. package/server/routes/gis/services/add.service.js +5 -5
  26. package/server/routes/gis/services/get.services.col.js +19 -11
  27. package/server/routes/gis/services/get.services.js +25 -12
  28. package/server/routes/map/controllers/layerList.js +14 -2
  29. package/server/routes/map/controllers/mapFeatures.js +11 -2
  30. package/server/routes/map/controllers/mapFormat.js +13 -16
  31. package/server/routes/map/controllers/vtile.js +1 -1
  32. package/server/routes/map/maps/get.map.js +13 -11
  33. package/server/routes/map/vtile1.js +30 -2
@@ -0,0 +1,18 @@
1
+ [
2
+ {
3
+ "id": "1",
4
+ "text": "Демонтована"
5
+ },
6
+ {
7
+ "id": "2",
8
+ "text": "Підлягає демонтажу у зв’язку з анулюванням паспорту прив'язки"
9
+ },
10
+ {
11
+ "id": "3",
12
+ "text": "Підлягає демонтажу у зв’язку з самовільним встановленням ТС"
13
+ },
14
+ {
15
+ "id": "4",
16
+ "text": "Підлягає демонтажу у зв’язку завершенням терміну дії паспорту прив’язки"
17
+ }
18
+ ]
@@ -0,0 +1,10 @@
1
+ [
2
+ {
3
+ "id": "1",
4
+ "text": "Тимчасова споруда з паспортом прив’язки"
5
+ },
6
+ {
7
+ "id": "2",
8
+ "text": "Самовільно встановлена"
9
+ }
10
+ ]
@@ -1,13 +1,17 @@
1
1
  {
2
2
  "history": true,
3
3
  "name": "Буд. паспорти та Містобудівні умови й обмеження",
4
- "height": "calc(100vh - 65px)",
5
- "center": [
4
+ "height": "calc(100vh - 65px)",
5
+ "center": [
6
6
  34.65450,
7
- 48.51174
8
- ],
7
+ 48.51174
8
+ ],
9
9
  "zoom": 11,
10
10
  "widgets":[
11
+ {
12
+ "type": "search",
13
+ "position": "top-left"
14
+ },
11
15
  {
12
16
  "type": "info",
13
17
  "position": "top-left",
@@ -32,6 +36,6 @@
32
36
  "old":["bp","3c95e341465d"],
33
37
  "layers": [
34
38
  "3c95e341465d",
35
- "dbcb186818e3"
39
+ "dbcb186818e3"
36
40
  ]
37
- }
41
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "extra": true
3
+ }
@@ -0,0 +1,8 @@
1
+ SELECT addr_id,
2
+ coalesce(c.name , ' ') || ' ' || (select name from data_address.street where str_id=a.parent limit 1) ||
3
+ coalesce(', ' ||addr_num,'')
4
+ FROM data_address.address a
5
+ left join data_address.street b on a.parent=b.str_id
6
+ left join admin.cls c on c.parent='str_type' and c.code=b.type::text
7
+ order by
8
+ b.name
@@ -0,0 +1,123 @@
1
+ {
2
+ "key": "bp_id",
3
+ "table": "data_bp_myo.bp",
4
+ "actions": [
5
+ "add",
6
+ "edit",
7
+ "del"
8
+ ],
9
+ "controls": [
10
+ "search",
11
+ "list",
12
+ "add"
13
+ ],
14
+ "access": "user",
15
+ "order": "cdate desc",
16
+ "meta": {
17
+ "title": "bp_code",
18
+ "search": "bp_code,bp_number,bp_reg_num,bp_issued_name,bp_customer_name,bp_object_name"
19
+ },
20
+ "title": "Будівельні паспорти",
21
+ "form": "data_bp_myo.bp.form",
22
+ "columns": [
23
+ {
24
+ "ua": "Реєстраційний номер МБК",
25
+ "name": "bp_number",
26
+ "width": 100,
27
+ "format": "text"
28
+ },
29
+ {
30
+ "ua": "Реєстраційний номер в ЄДЕССБ",
31
+ "meta": "title",
32
+ "name": "bp_code",
33
+ "hidden": true,
34
+ "format": "text"
35
+ },
36
+ {
37
+ "ua": "Реєстраційний номер",
38
+ "name": "bp_reg_num",
39
+ "width": 100,
40
+ "format": "text"
41
+ },
42
+ {
43
+ "ua": "Назва об’єкта будівництва",
44
+ "name": "bp_object_name",
45
+ "width": 300,
46
+ "format": "text"
47
+ },
48
+ {
49
+ "ua": "Адреса",
50
+ "name": "address",
51
+ "width": 300,
52
+ "format": "text"
53
+ },
54
+ {
55
+ "ua": "Вид будівництва",
56
+ "name": "bp_build_type",
57
+ "data": "bp_build_type",
58
+ "width": 150,
59
+ "format": "badge"
60
+ },
61
+ {
62
+ "ua": "Дата видачі",
63
+ "name": "bp_issued_date",
64
+ "width": 100,
65
+ "format": "date"
66
+ },
67
+ {
68
+ "ua": "Статус реєстрації",
69
+ "name": "bp_doc_status",
70
+ "data": "doc_status",
71
+ "width": 150,
72
+ "hidden": true,
73
+ "format": "badge"
74
+ },
75
+ {
76
+ "ua": "Назва органу, що видав",
77
+ "name": "bp_issued_name",
78
+ "width": 300,
79
+ "hidden": true,
80
+ "format": "text"
81
+ },
82
+ {
83
+ "ua": "Замовник",
84
+ "name": "bp_customer_name",
85
+ "width": 300,
86
+ "format": "text"
87
+ },
88
+ {
89
+ "ua": "Кадастрові номери",
90
+ "name": "land_number",
91
+ "format": "slot",
92
+ "hidden": true,
93
+ "slot": {
94
+ "content": "<p v-for=\"item in data?.land_number\">{{item}}</p>"
95
+ }
96
+ },
97
+ {
98
+ "ua": "Версія документу",
99
+ "name": "obj_version",
100
+ "format": "text",
101
+ "hidden": true
102
+ }
103
+ ],
104
+ "filterList": [
105
+ {
106
+ "ua": "Вид будівництва",
107
+ "name": "bp_build_type",
108
+ "data": "bp_build_type",
109
+ "type": "Check"
110
+ },
111
+ {
112
+ "ua": "Дата видачі",
113
+ "name": "bp_issued_date",
114
+ "type": "Date"
115
+ },
116
+ {
117
+ "ua": "Статус документа",
118
+ "name": "bp_doc_status",
119
+ "data": "doc_status",
120
+ "type": "Check"
121
+ }
122
+ ]
123
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/gis",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "author": "Softpro",
6
6
  "main": "./dist/index.js",
@@ -35,16 +35,16 @@
35
35
  "carto": "0.16.3"
36
36
  },
37
37
  "peerDependencies": {
38
- "@opengis/fastify-table": "^2.0.13"
38
+ "@opengis/fastify-table": "^2.0.23"
39
39
  },
40
40
  "resolutions": {
41
41
  "rollup": "4.30.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@opengis/core": "^0.0.23",
45
- "@opengis/fastify-table": "^2.0.13",
45
+ "@opengis/fastify-table": "^2.0.23",
46
46
  "@opengis/filter": "^0.1.7",
47
- "@opengis/form": "^0.0.28",
47
+ "@opengis/form": "^0.0.42",
48
48
  "@opengis/table": "^0.0.27",
49
49
  "@vitejs/plugin-vue": "^5.2.3",
50
50
  "axios": "^1.11.0",
@@ -0,0 +1,107 @@
1
+ CREATE TABLE if not exists gis.ogc_service
2
+ (
3
+ ogc_service_id text NOT NULL DEFAULT admin.next_id(),
4
+ name text, -- Назва
5
+ service text, -- TMS/WMS/WFS
6
+ url text, -- Шлях
7
+ enabled boolean, -- Опис
8
+ geom geometry, -- Баунд
9
+ updated_by text,
10
+ updated_at timestamp without time zone,
11
+ created_at timestamp without time zone DEFAULT date_trunc('minutes'::text, now()),
12
+ created_by text,
13
+ group_id text, -- Ідентифікатор групи
14
+ ispublic boolean DEFAULT false, -- Чи є сервіс публічним
15
+ service_id text DEFAULT admin.next_id(), -- ID
16
+ srid text, -- srid
17
+ info text,
18
+ scheme text, -- Схема
19
+ category text, -- Категорія
20
+ attribution text, -- Атрибуція
21
+ editor_id text,
22
+ editor_date timestamp without time zone,
23
+ cdate timestamp without time zone DEFAULT date_trunc('minutes'::text, now()),
24
+ uid text,
25
+ files json,
26
+ access_level text DEFAULT 'public'::text, -- Рівень доступу (public, user, admin)
27
+ sub_layers text, -- Під шари (Для WMS)
28
+ isadmin boolean DEFAULT false, -- Ознака доступу лише для адмін частини порталу
29
+ user_group_id text, -- Група користувачів
30
+ url_list text[], -- URL List
31
+ table_name text, -- Таблиця на клік (інтерактивний шар)
32
+ setting json, -- Додаткові налаштування
33
+ CONSTRAINT ogc_service_pkey PRIMARY KEY (ogc_service_id),
34
+ CONSTRAINT gis_ogc_service_group_id_fkey FOREIGN KEY (group_id)
35
+ REFERENCES gis.group_list (group_id) MATCH SIMPLE
36
+ ON UPDATE NO ACTION ON DELETE NO ACTION
37
+ );
38
+
39
+ COMMENT ON TABLE gis.ogc_service IS 'Сервіси';
40
+
41
+ COMMENT ON COLUMN gis.ogc_service.name IS 'Назва';
42
+ COMMENT ON COLUMN gis.ogc_service.service IS 'TMS/WMS/WFS';
43
+ COMMENT ON COLUMN gis.ogc_service.url IS 'Шлях';
44
+ COMMENT ON COLUMN gis.ogc_service.enabled IS 'Опис';
45
+ COMMENT ON COLUMN gis.ogc_service.geom IS 'Баунд';
46
+ COMMENT ON COLUMN gis.ogc_service.group_id IS 'Ідентифікатор групи';
47
+ COMMENT ON COLUMN gis.ogc_service.ispublic IS 'Чи є сервіс публічним';
48
+ COMMENT ON COLUMN gis.ogc_service.service_id IS 'ID';
49
+ COMMENT ON COLUMN gis.ogc_service.srid IS 'srid';
50
+ COMMENT ON COLUMN gis.ogc_service.scheme IS 'Схема';
51
+ COMMENT ON COLUMN gis.ogc_service.category IS 'Категорія';
52
+ COMMENT ON COLUMN gis.ogc_service.attribution IS 'Атрибуція';
53
+ COMMENT ON COLUMN gis.ogc_service.access_level IS 'Рівень доступу (public, user, admin)';
54
+ COMMENT ON COLUMN gis.ogc_service.sub_layers IS 'Під шари (Для WMS)';
55
+ COMMENT ON COLUMN gis.ogc_service.isadmin IS 'Ознака доступу лише для адмін частини порталу';
56
+ COMMENT ON COLUMN gis.ogc_service.user_group_id IS 'Група користувачів';
57
+ COMMENT ON COLUMN gis.ogc_service.url_list IS 'URL List';
58
+ COMMENT ON COLUMN gis.ogc_service.table_name IS 'Таблиця на клік (інтерактивний шар)';
59
+ COMMENT ON COLUMN gis.ogc_service.setting IS 'Додаткові налаштування';
60
+
61
+ CREATE INDEX if not exists gis_ogc_service_category_trgm_idx
62
+ ON gis.ogc_service
63
+ USING gin
64
+ (category COLLATE pg_catalog."default" gin_trgm_ops);
65
+
66
+ CREATE INDEX if not exists gis_ogc_service_enabled_btree_idx
67
+ ON gis.ogc_service
68
+ USING btree
69
+ (enabled);
70
+
71
+ CREATE INDEX if not exists gis_ogc_service_isadmin_btree_idx
72
+ ON gis.ogc_service
73
+ USING btree
74
+ (ispublic);
75
+
76
+ CREATE INDEX if not exists gis_ogc_service_ispublic_btree_idx
77
+ ON gis.ogc_service
78
+ USING btree
79
+ (ispublic);
80
+
81
+ CREATE INDEX if not exists gis_ogc_service_name_gin_idx
82
+ ON gis.ogc_service
83
+ USING gin
84
+ (name COLLATE pg_catalog."default" gin_trgm_ops);
85
+
86
+ CREATE INDEX if not exists gis_ogc_service_name_gin_idx_lower
87
+ ON gis.ogc_service
88
+ USING gin
89
+ (lower(name) COLLATE pg_catalog."default" gin_trgm_ops);
90
+
91
+ CREATE INDEX if not exists gis_ogc_service_name_trgm_idx
92
+ ON gis.ogc_service
93
+ USING gin
94
+ (name COLLATE pg_catalog."default" gin_trgm_ops);
95
+
96
+ CREATE INDEX if not exists gis_ogc_service_service_btree_idx
97
+ ON gis.ogc_service
98
+ USING btree
99
+ (service COLLATE pg_catalog."default");
100
+
101
+ CREATE INDEX if not exists gis_ogc_service_srid_btree_idx
102
+ ON gis.ogc_service
103
+ USING btree
104
+ (srid COLLATE pg_catalog."default");
105
+
106
+ alter table gis.ogc_service add column if not exists html text;
107
+ comment on column gis.ogc_service.html is 'HTML картки';
@@ -1,5 +1,3 @@
1
- import fp from 'fastify-plugin';
2
-
3
1
  import insertColumns from './registers/insert.columns.js';
4
2
  import insertFilters from './registers/insert.filters.js';
5
3
  import metadataXML from './metadata/metadataXML.js';
@@ -16,6 +14,20 @@ import addGisRegistry from './registers/add.registry.js';
16
14
  import deleteGisRegistry from './registers/del.registry.js';
17
15
  import getServicesCol from './services/get.services.col.js';
18
16
  import legendAuto from './services/legend.auto.js';
17
+ import mapInfoPoint from './ogc/map.info.point.js';
18
+
19
+ const mapInfoPointSchema = {
20
+ querystring: {
21
+ type: 'object',
22
+ properties: {
23
+ x: { type: 'number' },
24
+ y: { type: 'number' },
25
+ layers: { type: 'string' },
26
+ index: { type: 'number', minimum: 0 }
27
+ },
28
+ required: ['x', 'y', 'layers']
29
+ }
30
+ };
19
31
 
20
32
  async function route(app) {
21
33
  app.put('/insert-columns/:token', insertColumns);
@@ -40,6 +52,8 @@ async function route(app) {
40
52
  app.put('/gis-service/:id', { config: { policy: ['public'] } }, addService);
41
53
  app.delete('/gis-service/:id', { config: { policy: ['public'] } }, deleteService);
42
54
  app.get('/legend-auto/:id', { config: { policy: ['public'] } }, legendAuto);
55
+
56
+ app.get('/map-info-point', { config: { policy: ['public'] }, schema: mapInfoPointSchema }, mapInfoPoint);
43
57
  }
44
58
 
45
59
  export default route;
@@ -0,0 +1,120 @@
1
+ import { pgClients, handlebars, getMeta, getTemplate, getFilterSQL } from "@opengis/fastify-table/utils.js";
2
+
3
+ const columnType = {
4
+ text: 'text',
5
+ date: 'date',
6
+ bool: 'yes/no',
7
+ numeric: 'number',
8
+ integer: 'number',
9
+ 'timestamp without time zone': 'date',
10
+ 'timestamp with time zone': 'date',
11
+ };
12
+
13
+ export default async function mapInfoPoint(req, reply) {
14
+ const { pg = pgClients.client, query = {} } = req;
15
+ const { x, y, layers, index = 0 } = query;
16
+ const time = Date.now();
17
+
18
+ if (!x || !y || !layers) {
19
+ return reply.status(400).send('not enough query params: x, y, layers are required');
20
+ }
21
+
22
+ const rows = pg?.pk?.['gis.ogc_service'] ? await pg.query(`select * from gis.ogc_service WHERE enabled and table_name is not null and ogc_service_id = any($1)`, [layers.split(',')]).then(el => el.rows || []) : [];
23
+
24
+ if (!rows.length) {
25
+ return reply.status(404).send('layers not found');
26
+ }
27
+
28
+ const point = `srid=4326;point(${x} ${y})`; // 30, 50
29
+
30
+ const srids = pg.queryCache ? await pg.queryCache('select json_agg(srid) as srids from spatial_ref_sys').then(el => el.rows?.[0]?.srids || {}) : {};
31
+
32
+ await Promise.all(rows.map(async (layer, idx) => {
33
+ const { table_name: source, ogc_service_id: layerId } = layer;
34
+ const loadTable = await getTemplate('table', source);
35
+ const meta = await getMeta({ pg, table: loadTable?.table || source });
36
+ const { geom = 'geom' } = meta || {};
37
+ const { table = source, columns = meta?.columns } = loadTable || {};
38
+ const { srid, x } = await pg.query(`select st_srid(${geom}) as srid, st_x(st_pointonsurface(${geom})) as x from ${table} where geom is not null limit 1`).then(el => el.rows?.[0] || {});
39
+
40
+ const cls = columns
41
+ ?.filter(el => el.name && el.data)
42
+ ?.reduce?.((acc, curr) => ({ ...acc, [curr.name]: curr.data }), {});
43
+
44
+ const pk = pg.pk?.[table] || loadTable?.key;
45
+
46
+ const { optimizedSQL } = await getFilterSQL({ pg, table: source, query: layer?.query });
47
+
48
+ Object.assign(layer, {
49
+ layer: (layerId || idx.toString())?.replace?.(/'/g, "''"),
50
+ table,
51
+ pk,
52
+ cls,
53
+ geomColumn: srid === 4326 ? geom : `st_transform(${geom},4326)`,
54
+ optimizedSQL,
55
+ srid,
56
+ step: srids?.includes?.(srid - 0) && srid !== 4326 && x > 100 ? 10 : 0.0002,
57
+ });
58
+ }));
59
+
60
+ const unique = rows.filter((el, idx, arr) => el.table && arr.map((item) => item.table).indexOf(el.table) === idx);
61
+
62
+ const qList = unique.map((el) => ({
63
+ query: `select ${el.pk}::text as pk, '${el.layer}' as layer, '${el.table}' as table,
64
+ row_to_json(t) as data,
65
+ st_distance(${el.geomColumn},'${point.replace(/'/g, "''")}') as distance,
66
+ st_asgeojson(${el.geomColumn})::json as geom from (${el.optimizedSQL}) t
67
+ where 1=1`,
68
+ queryCount: `select 1 from (${el.optimizedSQL})t where 1=1`,
69
+ /*where: `case
70
+ when ST_GeometryType(${el.geomColumn}) in ('ST_Polygon','ST_MultiPolygon')
71
+ then st_intersects(${el.geomColumn},st_buffer('${point.replace(/'/g, "''")}',${el.step}))
72
+
73
+ when ST_GeometryType(${el.geomColumn}) in ('ST_Line','ST_MultiLineString', 'ST_MultiPoint', 'ST_Point')
74
+ then st_distance(${el.geomColumn},'${point.replace(/'/g, "''")}') < ${el.step}
75
+ else false
76
+ end`,*/
77
+ where: `${el.geomColumn} && '${point.replace(/'/g, "''")}'`
78
+ }));
79
+
80
+ const q = qList.map(el => el.query + ' and ' + el.where).join(' union all ').concat(` order by distance limit 1 offset ${Math.max(+index || 0, 0)}`);
81
+
82
+ const qCount = qList.map(el => el.queryCount + ' and ' + el.where).join(' union all ');
83
+
84
+ if (query.sql === '1') return q;
85
+ if (query.sql === '2') return qCount;
86
+
87
+ const count = await pg.query(qCount).then(el => el.rowCount);
88
+
89
+ const row = await pg.query(q).then(el => el.rows?.[0]);
90
+
91
+ if (!row) {
92
+ return reply.status(404).send('object not found');
93
+ }
94
+
95
+ const { columns = [] } = await getMeta({ pg, table: row.table }) || {};
96
+ const fields = columns.map(({ name, dataTypeID, title }) => ({ name, type: columnType[pg.pgType?.[dataTypeID] || 'text'], label: title || name }));
97
+
98
+ const htmlTemplate = pg?.pk?.['admin.template'] && row.layer && false
99
+ ? await pg.query('select body from admin.templates where name=$1 limit 1', [row.layer]).then(el => el.rows?.[0]?.body)
100
+ : rows.find(el => el.ogc_service_id === row.layer)?.html;
101
+
102
+ const html = await handlebars.compile(htmlTemplate || 'template not found')(row.data);
103
+
104
+ const res = {
105
+ time: Date.now() - time,
106
+ index,
107
+ count,
108
+ data: {
109
+ layer: row.layer,
110
+ geom: row.geom,
111
+ id: row.pk,
112
+ distance: row.distance,
113
+ data: row.data,
114
+ },
115
+ fields,
116
+ html
117
+ };
118
+
119
+ return res;
120
+ }
@@ -5,11 +5,13 @@ export async function attachClassifiers(rowOrRows, classifiers, table) {
5
5
 
6
6
  const list = getTemplates(['cls', 'select']);
7
7
 
8
+ // classifiers as object
8
9
  if (table) {
9
10
  await Promise.all(rows.map(async row => {
10
- await Promise.all(Object.keys(row).filter(key => list.map(el => el[0]).includes(`${table}.${key}`)).map(async key => {
11
- const arr = await getSelectVal({ name: `${table}.${key}`, values: [row[key]], ar: true });
12
- const val = arr?.find?.(el => el.id === row[key]);
11
+ await Promise.all(Object.keys(row).filter(key => classifiers?.[key] || list.map(el => el[0]).includes(`${table}.${key}`) || list.map(el => el[0]).includes(key)).map(async key => {
12
+ const clsAsColumn = list.map(el => el[0]).includes(key);
13
+ const arr = await getSelectVal({ name: classifiers?.[key] || (clsAsColumn ? key : `${table}.${key}`), values: [row[key]], ar: true });
14
+ const val = arr?.find?.(el => el.id && el.id.toString() === row[key].toString());
13
15
  if (val?.text) { row[`${key}_data`] = val; }
14
16
  row[key] = val?.text || val || row[key]; // for frontend
15
17
  row[`${key}_text`] = val?.text || val || row[key]; // legacy?
@@ -18,6 +20,7 @@ export async function attachClassifiers(rowOrRows, classifiers, table) {
18
20
  return rowOrRows;
19
21
  }
20
22
 
23
+ // classifiers as array of objects
21
24
  await Promise.all(rows.map(async row => {
22
25
  (classifiers || []).filter(item => item.classifier && item.name && row[item.name]).map(async ({ name, classifier }) => {
23
26
  const arr = await getSelectVal({ name: classifier, values: [row[name]], ar: true });
@@ -1,6 +1,6 @@
1
- import { attachClassifiers, populateFilterOptions } from './classifiers.js';
1
+ import { populateFilterOptions } from './classifiers.js';
2
2
  import { extractVisibleColumns } from './columns.js';
3
- import { getMeta, getFilterSQL } from "@opengis/fastify-table/utils.js";
3
+ import { getMeta, getFilterSQL, metaFormat } from "@opengis/fastify-table/utils.js";
4
4
 
5
5
  const columnType = {
6
6
  text: 'text',
@@ -12,11 +12,11 @@ const columnType = {
12
12
  'timestamp with time zone': 'date',
13
13
  };
14
14
 
15
- export async function handleRegistryRequest({ settings, query, object_id, offset = 0, limit = 16, page = 1, pg }) {
15
+ export async function handleRegistryRequest({ settings, query, object_id, offset = 0, limit = 16, page = 1, pg, sql }) {
16
16
  const { name, table_name, description, card, columns, filters, query: whereQuery, order, pk, register_id, is_files, view } = settings;
17
17
  const parsedColumns = Array.isArray(columns) ? columns : JSON.parse(columns);
18
18
  const filtersParsed = Array.isArray(filters) ? filters : JSON.parse(filters);
19
- const activeFilters = (filtersParsed || []).filter((f) => f.disabled !== true);
19
+ const activeFilters = (filtersParsed || []).filter((f) => f.disabled !== true).map(el => ({ ...el, id: el.name || el.id, type: el.type, api: '/api/suggest/' + table_name + ':' + el.name + (el.data ? `?sel=${el.data}` : '') }));
20
20
  const { columns: fields1, geom } = await getMeta({ pg, table: table_name });
21
21
 
22
22
  const fields = fields1?.map?.(({ name, dataTypeID, title }) => ({ name, type: columnType[pg.pgType?.[dataTypeID] || 'text'] || 'text', label: title || name }));
@@ -34,7 +34,7 @@ export async function handleRegistryRequest({ settings, query, object_id, offset
34
34
 
35
35
  const classifiers = visibleColumns
36
36
  .filter((col) => col.data && ["select", "badge", "tags"].includes(col.format))
37
- .map((col) => ({ name: col.name, classifier: col.data }));
37
+ .reduce((acc, curr) => ({ ...acc, [curr.name]: curr.data }), {});
38
38
 
39
39
  if (object_id) {
40
40
  const sql = `
@@ -42,17 +42,13 @@ export async function handleRegistryRequest({ settings, query, object_id, offset
42
42
  FROM ${table_name}
43
43
  WHERE ${pk} = $1
44
44
  `;
45
- const {
46
- rows: [row],
47
- } = await pg.query(sql, [object_id]);
45
+ const rows = await pg.query(sql, [object_id]).then(el => el.rows || []);
46
+ if (!rows.length) throw new Error('Object not found');
48
47
 
49
- //if (!row) return reply.code(404).send({ message: 'Object not found', status: 404 });
50
- if (!row) throw new Error('Object not found');
51
-
52
- await attachClassifiers(row, classifiers, table_name);
48
+ await metaFormat({ rows, table: table_name, cls: classifiers, sufix: true });
53
49
 
54
50
  return {
55
- row,
51
+ row: rows[0],
56
52
  card,
57
53
  d: 1,
58
54
  columns: visibleColumns,
@@ -68,8 +64,7 @@ export async function handleRegistryRequest({ settings, query, object_id, offset
68
64
  table: table_name,
69
65
  search: search,
70
66
  filter: filter,
71
- filterList: filters,
72
- json: 1
67
+ filterList: activeFilters,
73
68
  })
74
69
  : { q: '1=1' };
75
70
 
@@ -81,15 +76,13 @@ export async function handleRegistryRequest({ settings, query, object_id, offset
81
76
 
82
77
  const sqlSelect = `SELECT "${pk}" as id ${selectColumns.length ? `, ${selectColumns.join(", ")}` : ''} ${geom ? `, st_asgeojson(${geom})::json as geom` : ''} ${sqlBase}`;
83
78
  const dataQuery = `${sqlSelect} ${sqlOrder} ${sqlLimit}`;
84
- const totalQuery = `SELECT COUNT(*) ${sqlBase}`;
85
79
 
86
- const [dataRes, countRes] = await Promise.all([
87
- pg.query(dataQuery, [limit, offset]),
88
- pg.query(totalQuery),
89
- ]);
80
+ if (sql) return dataQuery;
81
+
82
+ const rows = await pg.query(dataQuery, [limit, offset]).then(el => el.rows || []);
83
+ const total = await pg.query(`SELECT COUNT(*) ${sqlBase}`).then(el => +(el.rows[0]?.count || 0));
90
84
 
91
- const rows = await attachClassifiers(dataRes.rows, classifiers, table_name);
92
- const total = parseInt(countRes.rows[0]?.count || 0, 10);
85
+ await metaFormat({ rows, table: table_name, cls: classifiers, sufix: true });
93
86
 
94
87
  const listConfig = {};
95
88
 
@@ -9,6 +9,7 @@ export default async function gisRegistry({
9
9
  pg = pgClients.client, params = {}, query = {},
10
10
  }) {
11
11
  const { slug, objectId } = params;
12
+ const { sql } = query;
12
13
 
13
14
  const limit = Math.min(query.limit || defaultLimit, maxLimit);
14
15
  const offset = query.page && query.page > 0 && !objectId ? (query.page - 1) * limit : 0;
@@ -26,12 +27,12 @@ export default async function gisRegistry({
26
27
  );
27
28
 
28
29
  if (registry) {
29
- return handleRegistryRequest({ settings: registry, query, object_id: objectId, offset, limit, page: query.page, pg });
30
+ return handleRegistryRequest({ settings: registry, query, object_id: objectId, offset, limit, page: query.page, pg, sql });
30
31
  }
31
32
 
32
33
  const registryTemplate = await getTemplate('registry', slug);
33
34
  //if (!registryTemplate) return reply.code(404).send({ message: 'Template not found', status: 404 });
34
35
  if (!registryTemplate) throw new Error('Template not found');
35
36
 
36
- return handleRegistryRequest({ settings: registryTemplate, query, object_id: objectId, offset, limit, page: query.page, pg });
37
+ return handleRegistryRequest({ settings: registryTemplate, query, object_id: objectId, offset, limit, page: query.page, pg, sql });
37
38
  }
@@ -1,7 +1,7 @@
1
1
  import { dataDelete, dataInsert, dataUpdate, pgClients } from "@opengis/fastify-table/utils.js";
2
2
 
3
- async function updateTemplate(client, body, name, uid, id) {
4
- if (!body || !name || !id) return;
3
+ async function updateTemplate(client, body, uid, id) {
4
+ if (!body || !id) return;
5
5
 
6
6
  await dataDelete({
7
7
  pg: client,
@@ -13,7 +13,7 @@ async function updateTemplate(client, body, name, uid, id) {
13
13
  pg: client,
14
14
  id,
15
15
  table: 'admin.templates',
16
- data: { body, name },
16
+ data: { body, name: id },
17
17
  uid,
18
18
  }).then(el => el.rowCount);
19
19
  return rowCount;
@@ -39,7 +39,7 @@ export default async function addService({
39
39
  data: body,
40
40
  uid,
41
41
  });
42
- const istemplate = await updateTemplate(client, body.html, body.template, uid, rows[0]?.service_id);
42
+ const istemplate = await updateTemplate(client, body.html, uid, rows[0]?.service_id);
43
43
  await client.query('commit');
44
44
  return reply.status(200).send(rows[0]);
45
45
  }
@@ -52,7 +52,7 @@ export default async function addService({
52
52
  data: body,
53
53
  uid,
54
54
  });
55
- const istemplate = await updateTemplate(client, body.html, body.template, uid, params.id);
55
+ const istemplate = await updateTemplate(client, body.html, uid, params.id);
56
56
  await client.query('commit');
57
57
  return reply.status(200).send(row);
58
58