@opengis/fastify-table 1.0.8 → 1.0.9
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/.eslintrc.cjs +42 -42
- package/Changelog.md +47 -0
- package/README.md +26 -26
- package/config.js +11 -3
- package/crud/controllers/deleteCrud.js +10 -10
- package/crud/controllers/insert.js +28 -9
- package/crud/controllers/update.js +29 -10
- package/crud/controllers/utils/checkXSS.js +45 -0
- package/crud/controllers/utils/xssInjection.js +72 -0
- package/crud/funcs/dataDelete.js +15 -15
- package/crud/funcs/dataInsert.js +24 -24
- package/crud/funcs/getIdByToken.js +29 -0
- package/crud/funcs/isFileExists.js +13 -13
- package/crud/funcs/setTokenById.js +55 -0
- package/helper.js +28 -28
- package/index.js +32 -22
- package/package.json +22 -22
- package/pg/funcs/autoIndex.js +89 -89
- package/pg/funcs/getMeta.js +27 -27
- package/pg/funcs/init.js +42 -42
- package/pg/funcs/pgClients.js +2 -2
- package/pg/index.js +35 -35
- package/pg/pgClients.js +17 -17
- package/policy/funcs/checkPolicy.js +74 -0
- package/policy/funcs/sqlInjection.js +33 -0
- package/policy/index.js +14 -0
- package/redis/client.js +8 -8
- package/redis/funcs/redisClients.js +2 -2
- package/redis/index.js +19 -19
- package/server/templates/form/test.dataset.form.json +412 -0
- package/server.js +14 -14
- package/table/controllers/data.js +55 -55
- package/table/controllers/filter.js +24 -24
- package/table/controllers/form.js +10 -10
- package/table/controllers/suggest.js +60 -60
- package/table/controllers/utils/getSelect.js +20 -20
- package/table/controllers/utils/getSelectMeta.js +66 -66
- package/table/funcs/getFilterSQL/index.js +75 -75
- package/table/funcs/getFilterSQL/util/formatValue.js +142 -142
- package/table/funcs/getFilterSQL/util/getCustomQuery.js +13 -13
- package/table/funcs/getFilterSQL/util/getFilterQuery.js +73 -73
- package/table/funcs/getFilterSQL/util/getOptimizedQuery.js +12 -12
- package/table/funcs/getFilterSQL/util/getTableSql.js +34 -34
- package/table/index.js +14 -14
- package/test/api/crud.test.js +50 -48
- package/test/api/crud.xss.test.js +70 -0
- package/test/api/table.test.js +49 -49
- package/test/config.example +18 -18
- package/test/funcs/crud.test.js +77 -51
- package/test/funcs/pg.test.js +32 -32
- package/test/funcs/redis.test.js +19 -19
- package/test/funcs/table.test.js +48 -48
- package/test/templates/cls/test.json +9 -9
- package/test/templates/form/cp_building.form.json +32 -32
- package/test/templates/select/account_id.json +3 -3
- package/test/templates/select/storage.data.json +2 -2
- package/test/templates/table/gis.dataset.table.json +20 -20
- package/changelog.md +0 -26
package/redis/client.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import redisClients from './funcs/redisClients.js';
|
|
2
|
-
import getRedis from './funcs/getRedis.js';
|
|
3
|
-
|
|
4
|
-
if (!redisClients[0]) {
|
|
5
|
-
getRedis({ db: 0 });
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export default redisClients[0];
|
|
1
|
+
import redisClients from './funcs/redisClients.js';
|
|
2
|
+
import getRedis from './funcs/getRedis.js';
|
|
3
|
+
|
|
4
|
+
if (!redisClients[0]) {
|
|
5
|
+
getRedis({ db: 0 });
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default redisClients[0];
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const redisClients = {};
|
|
2
|
-
export default redisClients;
|
|
1
|
+
const redisClients = {};
|
|
2
|
+
export default redisClients;
|
package/redis/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
// import client from './client.js';
|
|
2
|
-
import getRedis from './funcs/getRedis.js';
|
|
3
|
-
// import client from './funcs/redisClients.js';
|
|
4
|
-
|
|
5
|
-
function close(fastify) {
|
|
6
|
-
fastify.rclient.quit();
|
|
7
|
-
// fastify.rclient2.quit();
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
async function plugin(fastify) {
|
|
11
|
-
const client = getRedis({ db: 0 });
|
|
12
|
-
client.getJSON = client.get;
|
|
13
|
-
fastify.decorate('rclient', client);
|
|
14
|
-
fastify.decorate('getRedis', getRedis);
|
|
15
|
-
// fastify.decorate('rclient2', client2);
|
|
16
|
-
fastify.addHook('onClose', close);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export default plugin;
|
|
1
|
+
// import client from './client.js';
|
|
2
|
+
import getRedis from './funcs/getRedis.js';
|
|
3
|
+
// import client from './funcs/redisClients.js';
|
|
4
|
+
|
|
5
|
+
function close(fastify) {
|
|
6
|
+
fastify.rclient.quit();
|
|
7
|
+
// fastify.rclient2.quit();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async function plugin(fastify) {
|
|
11
|
+
const client = getRedis({ db: 0, funcs: fastify });
|
|
12
|
+
client.getJSON = client.get;
|
|
13
|
+
fastify.decorate('rclient', client);
|
|
14
|
+
fastify.decorate('getRedis', getRedis);
|
|
15
|
+
// fastify.decorate('rclient2', client2);
|
|
16
|
+
fastify.addHook('onClose', close);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default plugin;
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
{
|
|
2
|
+
"label_style": "vertical",
|
|
3
|
+
"saveButton": false,
|
|
4
|
+
"schema": {
|
|
5
|
+
"dataset_name": {
|
|
6
|
+
"type": "Text",
|
|
7
|
+
"ua": "Назва набору українською",
|
|
8
|
+
"validators": [
|
|
9
|
+
"required"
|
|
10
|
+
],
|
|
11
|
+
"col": 12
|
|
12
|
+
},
|
|
13
|
+
"enabled": {
|
|
14
|
+
"type": "Switcher",
|
|
15
|
+
"ua": "On / Off",
|
|
16
|
+
"col": 3
|
|
17
|
+
},
|
|
18
|
+
"home_is": {
|
|
19
|
+
"ua": "Виводити на публічці",
|
|
20
|
+
"type": "Switcher",
|
|
21
|
+
"col": 2
|
|
22
|
+
},
|
|
23
|
+
"isadmin": {
|
|
24
|
+
"type": "Switcher",
|
|
25
|
+
"ua": "Admin only",
|
|
26
|
+
"col": 3
|
|
27
|
+
},
|
|
28
|
+
"is_map": {
|
|
29
|
+
"type": "Switcher",
|
|
30
|
+
"ua": "Наявність переходу на карту",
|
|
31
|
+
"col": 3
|
|
32
|
+
},
|
|
33
|
+
"is_register": {
|
|
34
|
+
"type": "Switcher",
|
|
35
|
+
"ua": "Наявність переходу до реєстру",
|
|
36
|
+
"col": 3
|
|
37
|
+
},
|
|
38
|
+
"table_name": {
|
|
39
|
+
"type": "Text",
|
|
40
|
+
"ua": "Назва таблиці в БД"
|
|
41
|
+
},
|
|
42
|
+
"pk": {
|
|
43
|
+
"type": "Text",
|
|
44
|
+
"ua": "Primary key",
|
|
45
|
+
"validators": [
|
|
46
|
+
"required"
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
"query": {
|
|
50
|
+
"type": "Text",
|
|
51
|
+
"ru": "Запит до таблиці",
|
|
52
|
+
"ua": "Запит до таблиці"
|
|
53
|
+
},
|
|
54
|
+
"order_by": {
|
|
55
|
+
"type": "Text",
|
|
56
|
+
"ua": "Умова на сортування"
|
|
57
|
+
},
|
|
58
|
+
"group_id": {
|
|
59
|
+
"type": "Autocomplete",
|
|
60
|
+
"data": "gis.category.select",
|
|
61
|
+
"ua": "Група"
|
|
62
|
+
},
|
|
63
|
+
"service_type": {
|
|
64
|
+
"type": "Select2",
|
|
65
|
+
"data": "dataset.service_type",
|
|
66
|
+
"col": 12,
|
|
67
|
+
"ua": "Тип сервісу"
|
|
68
|
+
},
|
|
69
|
+
"setting.popup": {
|
|
70
|
+
"type": "Text",
|
|
71
|
+
"ua": "Popup"
|
|
72
|
+
},
|
|
73
|
+
"setting.card": {
|
|
74
|
+
"type": "Text",
|
|
75
|
+
"ua": "Шаблон"
|
|
76
|
+
},
|
|
77
|
+
"geom": {
|
|
78
|
+
"type": "Geom",
|
|
79
|
+
"ua": "Баунд"
|
|
80
|
+
},
|
|
81
|
+
"export_columns": {
|
|
82
|
+
"type": "Tags",
|
|
83
|
+
"data1": "column.list.select",
|
|
84
|
+
"parent": "table_name",
|
|
85
|
+
"ua": "Колонки для экспорту"
|
|
86
|
+
},
|
|
87
|
+
"column_list": {
|
|
88
|
+
"type": "DataTable",
|
|
89
|
+
"font-size": "10",
|
|
90
|
+
"ua": "Колонки",
|
|
91
|
+
"import": true,
|
|
92
|
+
"height": 600,
|
|
93
|
+
"colModel": [
|
|
94
|
+
{
|
|
95
|
+
"name": "name",
|
|
96
|
+
"type": "Text",
|
|
97
|
+
"ua": "Назва колонки в БД"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"name": "ua",
|
|
101
|
+
"type": "Text",
|
|
102
|
+
"ua": "Назва колонки українською",
|
|
103
|
+
"validators": [
|
|
104
|
+
"required"
|
|
105
|
+
]
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"name": "meta",
|
|
109
|
+
"type": "Autocomplete",
|
|
110
|
+
"data": "gis.meta_type",
|
|
111
|
+
"ua": "Meta",
|
|
112
|
+
"hide_column": true,
|
|
113
|
+
"column_hide": true
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"name": "format",
|
|
117
|
+
"type": "Autocomplete",
|
|
118
|
+
"data": "gis.column_list_type",
|
|
119
|
+
"default": "text",
|
|
120
|
+
"ua": "Тип колонки",
|
|
121
|
+
"validators": [
|
|
122
|
+
"required"
|
|
123
|
+
]
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"name": "data",
|
|
127
|
+
"ua": "Класифікатор",
|
|
128
|
+
"ru": "Класификатор",
|
|
129
|
+
"en": "Domen"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"name": "values",
|
|
133
|
+
"type": "DataTable",
|
|
134
|
+
"hide_column": true,
|
|
135
|
+
"column_hide": true,
|
|
136
|
+
"ua": "Домени",
|
|
137
|
+
"help": "Використовується для створення випадаючих списків",
|
|
138
|
+
"colModel": [
|
|
139
|
+
{
|
|
140
|
+
"name": "ua",
|
|
141
|
+
"ua": "Назва домена"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"name": "color",
|
|
145
|
+
"ua": "Колір"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"name": "icon",
|
|
149
|
+
"ua": "Іконка"
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"name": "hidden_table_public",
|
|
155
|
+
"type": "Switcher",
|
|
156
|
+
"ua": "Приховати поле в прев'ю",
|
|
157
|
+
"i": "Чи приховати поле при перегляді об'єктів набора"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"name": "hidden_public",
|
|
161
|
+
"type": "Switcher",
|
|
162
|
+
"ua": "Приховати поле в картоці об'єкта"
|
|
163
|
+
}
|
|
164
|
+
]
|
|
165
|
+
},
|
|
166
|
+
"filter_list": {
|
|
167
|
+
"type": "DataTable",
|
|
168
|
+
"height": 600,
|
|
169
|
+
"import": true,
|
|
170
|
+
"title": false,
|
|
171
|
+
"colModel": [
|
|
172
|
+
{
|
|
173
|
+
"name": "name",
|
|
174
|
+
"type": "Text",
|
|
175
|
+
"ua": "Колонка"
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"name": "type",
|
|
179
|
+
"edittype": "Autocomplete",
|
|
180
|
+
"ua": "Формат",
|
|
181
|
+
"data": "gis.filter_type"
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"name": "data",
|
|
185
|
+
"ua": "Класифікатор",
|
|
186
|
+
"ru": "Класификатор",
|
|
187
|
+
"width": 30,
|
|
188
|
+
"en": "Domen"
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
"name": "disabled",
|
|
192
|
+
"width": 10,
|
|
193
|
+
"ru": "Відключити",
|
|
194
|
+
"ua": "Відключити",
|
|
195
|
+
"type": "Switcher",
|
|
196
|
+
"col": 2
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"name": "ua",
|
|
200
|
+
"width": 30,
|
|
201
|
+
"ua": "Назва українською"
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
},
|
|
205
|
+
"style.geometry_type": {
|
|
206
|
+
"type": "Autocomplete",
|
|
207
|
+
"ua": "Тип геометрії",
|
|
208
|
+
"default": "point",
|
|
209
|
+
"validators": [
|
|
210
|
+
"required"
|
|
211
|
+
],
|
|
212
|
+
"options": [
|
|
213
|
+
{
|
|
214
|
+
"id": "point",
|
|
215
|
+
"text": "Точкові об'єкти"
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"id": "line",
|
|
219
|
+
"text": "Лінійні об'єкти"
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"id": "polygon",
|
|
223
|
+
"text": "Полігональні об'єкти"
|
|
224
|
+
}
|
|
225
|
+
],
|
|
226
|
+
"behavior": {
|
|
227
|
+
"point": {
|
|
228
|
+
"show": "style.as_icon,style.icon,style.pointFillColor,style.pointFillOpacity,style.pointStrokeColor,style.pointStrokeOpacity,style.pointStrokeWidth,style.radius,style.pointWidth,style.pointHeight",
|
|
229
|
+
"hide": "style.line_dotted,style.color,style.weight,style.fillColor,style.fillOpacity"
|
|
230
|
+
},
|
|
231
|
+
"line": {
|
|
232
|
+
"show": "style.line_dotted,style.color,style.weight",
|
|
233
|
+
"hide": "style.as_icon,style.icon,style.pointFillColor,style.pointFillOpacity,style.pointStrokeColor,style.pointStrokeOpacity,style.pointStrokeWidth,style.radius,style.pointWidth,style.pointHeight,style.fillColor,style.fillOpacity"
|
|
234
|
+
},
|
|
235
|
+
"polygon": {
|
|
236
|
+
"show": "style.fillColor,style.fillOpacity",
|
|
237
|
+
"hide": "style.as_icon,style.icon,style.pointFillColor,style.pointFillOpacity,style.pointStrokeColor,style.pointStrokeOpacity,style.pointStrokeWidth,style.radius,style.pointWidth,style.pointHeight,style.line_dotted,style.color,style.weight"
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
"style.as_icon": {
|
|
242
|
+
"type": "Autocomplete",
|
|
243
|
+
"ua": "Відображення іконкою",
|
|
244
|
+
"default": "yes",
|
|
245
|
+
"options": [
|
|
246
|
+
{
|
|
247
|
+
"id": "yes",
|
|
248
|
+
"text": "Так"
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
"id": "no",
|
|
252
|
+
"text": "Ні"
|
|
253
|
+
}
|
|
254
|
+
],
|
|
255
|
+
"behavior": {
|
|
256
|
+
"yes": {
|
|
257
|
+
"show": "style.icon",
|
|
258
|
+
"hide": "style.fillColor,style.fillOpacity,style.pointFillColor,style.pointFillOpacity,style.pointHeight,style.pointWidth,style.radius,style.pointStrokeWidth,style.pointStrokeOpacity,style.pointStrokeColor"
|
|
259
|
+
},
|
|
260
|
+
"no": {
|
|
261
|
+
"show": "style.fillColor,style.fillOpacity,style.pointFillColor,style.pointFillOpacity,style.pointHeight,style.pointWidth,style.radius,style.pointStrokeWidth,style.pointStrokeOpacity,style.pointStrokeColor",
|
|
262
|
+
"hide": "style.icon"
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
"style.icon": {
|
|
267
|
+
"type": "Text",
|
|
268
|
+
"ru": "Иконка",
|
|
269
|
+
"ua": "Іконка",
|
|
270
|
+
"help": "Приклад pin-l-bar+AA0000+2+2+4+20+20.png повна інструкція <a target='_blank' href='/api-user/marker_icon/'>/marker_icon/</a>"
|
|
271
|
+
},
|
|
272
|
+
"style.pointFillColor": {
|
|
273
|
+
"type": "colorpicker",
|
|
274
|
+
"ru": "Цвет точки",
|
|
275
|
+
"ua": "Колір точки",
|
|
276
|
+
"help": "Приклади: #aaa, red, #fa5050. По замовчуванню blue."
|
|
277
|
+
},
|
|
278
|
+
"style.pointFillOpacity": {
|
|
279
|
+
"type": "Number",
|
|
280
|
+
"ru": "Прозрачность точки",
|
|
281
|
+
"ua": "Прозорість точки",
|
|
282
|
+
"help": "Значення від 0.0 до 1.0. По замовчуванню 1.0."
|
|
283
|
+
},
|
|
284
|
+
"style.pointStrokeColor": {
|
|
285
|
+
"type": "colorpicker",
|
|
286
|
+
"ru": "Цвет контура",
|
|
287
|
+
"ua": "Колір контуру",
|
|
288
|
+
"help": "Приклади: #aaa, red, #fa5050. По замовчуванню black."
|
|
289
|
+
},
|
|
290
|
+
"style.pointStrokeOpacity": {
|
|
291
|
+
"type": "Number",
|
|
292
|
+
"ru": "Прозрачность контура",
|
|
293
|
+
"ua": "Прозорість контуру",
|
|
294
|
+
"help": "Значення від 0.0 до 1.0. По замовчуванню 1.0."
|
|
295
|
+
},
|
|
296
|
+
"style.pointStrokeWidth": {
|
|
297
|
+
"type": "Number",
|
|
298
|
+
"ru": "Ширина контура",
|
|
299
|
+
"ua": "Ширина контуру",
|
|
300
|
+
"help": "По замовчуванню 1."
|
|
301
|
+
},
|
|
302
|
+
"style.radius": {
|
|
303
|
+
"type": "Text",
|
|
304
|
+
"ru": "Radius",
|
|
305
|
+
"ua": "Radius",
|
|
306
|
+
"help": "По замовчуванню 10."
|
|
307
|
+
},
|
|
308
|
+
"style.pointWidth": {
|
|
309
|
+
"type": "Number",
|
|
310
|
+
"ru": "Ширина точки",
|
|
311
|
+
"ua": "Ширина точки",
|
|
312
|
+
"help": "По замовчуванню 10."
|
|
313
|
+
},
|
|
314
|
+
"style.pointHeight": {
|
|
315
|
+
"type": "Number",
|
|
316
|
+
"ru": "Высота точки",
|
|
317
|
+
"ua": "Висота точки",
|
|
318
|
+
"help": "По замовчуванню 10."
|
|
319
|
+
},
|
|
320
|
+
"style.fillColor": {
|
|
321
|
+
"type": "colorpicker",
|
|
322
|
+
"ru": "Цвет полигонов",
|
|
323
|
+
"ua": "Колір полігонів",
|
|
324
|
+
"help": "Приклади: #aaa, red, #fa5050."
|
|
325
|
+
},
|
|
326
|
+
"style.fillOpacity": {
|
|
327
|
+
"type": "Number",
|
|
328
|
+
"ru": "Прозрачность полигонов",
|
|
329
|
+
"ua": "Прозорість полігонів",
|
|
330
|
+
"help": "Значення від 0.0 до 1.0. По замовчуванню 1.0."
|
|
331
|
+
},
|
|
332
|
+
"style.color": {
|
|
333
|
+
"type": "colorpicker",
|
|
334
|
+
"ru": "Цвет линий",
|
|
335
|
+
"ua": "Колір ліній",
|
|
336
|
+
"help": "Приклади: #aaa, red, #fa5050."
|
|
337
|
+
},
|
|
338
|
+
"style.weight": {
|
|
339
|
+
"type": "Number",
|
|
340
|
+
"ru": "Ширина линий",
|
|
341
|
+
"ua": "Ширина ліній",
|
|
342
|
+
"help": "Значення в px. По замовчуванню 1.0."
|
|
343
|
+
},
|
|
344
|
+
"style.line_dotted": {
|
|
345
|
+
"type": "Text",
|
|
346
|
+
"ru": "Пунктирная линия",
|
|
347
|
+
"ua": "Пунктирна лінія",
|
|
348
|
+
"help": "Приклад: '10, 5', де значення задається з двох чисел через кому: перше - довжина пунктиру в px, а друге - відстань між пунктирами, в px. По замовчуванню відключено."
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
"fieldsets": [
|
|
352
|
+
{
|
|
353
|
+
"legend": "Основні налаштування",
|
|
354
|
+
"ua": "Основні налаштування",
|
|
355
|
+
"fields": [
|
|
356
|
+
"dataset_name",
|
|
357
|
+
"group_id",
|
|
358
|
+
"table_name",
|
|
359
|
+
"pk",
|
|
360
|
+
"query",
|
|
361
|
+
"service_type",
|
|
362
|
+
"enabled",
|
|
363
|
+
"isadmin",
|
|
364
|
+
"is_map",
|
|
365
|
+
"is_register",
|
|
366
|
+
"setting.popup",
|
|
367
|
+
"setting.card",
|
|
368
|
+
"geom"
|
|
369
|
+
]
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
"legend": "Колонки",
|
|
373
|
+
"ru": "Колонки",
|
|
374
|
+
"ua": "Колонки",
|
|
375
|
+
"fields": [
|
|
376
|
+
"column_list",
|
|
377
|
+
"export_columns"
|
|
378
|
+
]
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
"legend": "Фільтри",
|
|
382
|
+
"ru": "Фильтры",
|
|
383
|
+
"ua": "Фільтри",
|
|
384
|
+
"fields": [
|
|
385
|
+
"filter_list"
|
|
386
|
+
]
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
"legend": "Стилі",
|
|
390
|
+
"ru": "Стили",
|
|
391
|
+
"ua": "Стилі",
|
|
392
|
+
"fields": [
|
|
393
|
+
"style.geometry_type",
|
|
394
|
+
"style.as_icon",
|
|
395
|
+
"style.icon",
|
|
396
|
+
"style.pointFillColor",
|
|
397
|
+
"style.pointFillOpacity",
|
|
398
|
+
"style.pointStrokeColor",
|
|
399
|
+
"style.pointStrokeOpacity",
|
|
400
|
+
"style.pointStrokeWidth",
|
|
401
|
+
"style.radius",
|
|
402
|
+
"style.pointWidth",
|
|
403
|
+
"style.pointHeight",
|
|
404
|
+
"style.line_dotted",
|
|
405
|
+
"style.color",
|
|
406
|
+
"style.weight",
|
|
407
|
+
"style.fillColor",
|
|
408
|
+
"style.fillOpacity"
|
|
409
|
+
]
|
|
410
|
+
}
|
|
411
|
+
]
|
|
412
|
+
}
|
package/server.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
// This file contains code that we reuse
|
|
2
|
-
// between our tests.
|
|
3
|
-
import Fastify from 'fastify';
|
|
4
|
-
import config from './test/config.js';
|
|
5
|
-
import appService from './index.js';
|
|
6
|
-
|
|
7
|
-
const app = Fastify({ logger: false });
|
|
8
|
-
app.register(appService, config);
|
|
9
|
-
app.listen({ host: '0.0.0.0', port: process.env.PORT || 3000 }, (err) => {
|
|
10
|
-
if (err) {
|
|
11
|
-
app.log.error(err);
|
|
12
|
-
process.exit(1);
|
|
13
|
-
}
|
|
14
|
-
});
|
|
1
|
+
// This file contains code that we reuse
|
|
2
|
+
// between our tests.
|
|
3
|
+
import Fastify from 'fastify';
|
|
4
|
+
import config from './test/config.js';
|
|
5
|
+
import appService from './index.js';
|
|
6
|
+
|
|
7
|
+
const app = Fastify({ logger: false });
|
|
8
|
+
app.register(appService, config);
|
|
9
|
+
app.listen({ host: '0.0.0.0', port: process.env.PORT || 3000 }, (err) => {
|
|
10
|
+
if (err) {
|
|
11
|
+
app.log.error(err);
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
import getTemplate from './utils/getTemplate.js';
|
|
2
|
-
import getFilterSQL from '../funcs/getFilterSQL/index.js';
|
|
3
|
-
import getMeta from '../../pg/funcs/getMeta.js';
|
|
4
|
-
|
|
5
|
-
const maxLimit = 100;
|
|
6
|
-
export default async function data(req) {
|
|
7
|
-
const time = Date.now();
|
|
8
|
-
const {
|
|
9
|
-
pg, params, query = {},
|
|
10
|
-
} = req;
|
|
11
|
-
|
|
12
|
-
const loadTable = await getTemplate('table', params.table);
|
|
13
|
-
|
|
14
|
-
if (!loadTable) { return { status: 404, message: 'not found' }; }
|
|
15
|
-
|
|
16
|
-
const {
|
|
17
|
-
table, columns, sql, filters, form, meta,
|
|
18
|
-
} = loadTable;
|
|
19
|
-
const { pk } = await getMeta(table);
|
|
20
|
-
|
|
21
|
-
const cols = columns.map((el) => el.name || el).join(',');
|
|
22
|
-
const sqlTable = sql?.filter?.((el) => !el?.disabled && el?.sql?.replace).map((el, i) => ` left join lateral (${el.sql}) ${el.name || `t${i}`} on 1=1 `)?.join('') || '';
|
|
23
|
-
|
|
24
|
-
const fData = query.filter ? await getFilterSQL({
|
|
25
|
-
filter: query.filter,
|
|
26
|
-
table,
|
|
27
|
-
json: 1,
|
|
28
|
-
}) : {};
|
|
29
|
-
|
|
30
|
-
const keyQuery = query.key && loadTable.key && !params.id ? `${loadTable.key}=$1` : null;
|
|
31
|
-
|
|
32
|
-
const limit = Math.min(maxLimit, +(query.limit || 10));
|
|
33
|
-
|
|
34
|
-
const offset = query.page ? ` offset ${(query.page - 1) * limit}` : '';
|
|
35
|
-
// id, query, filter
|
|
36
|
-
const orderColumn = query.order || loadTable.order;
|
|
37
|
-
|
|
38
|
-
const order = cols.includes(orderColumn) ? `order by ${orderColumn} ${query.desc ? 'desc' : ''}` : '';
|
|
39
|
-
const state = loadTable.filterState && query.state ? loadTable.filterState[query.state]?.sql : null;
|
|
40
|
-
const custom = loadTable.filterCustom && query.custom ? loadTable.filterCustom[query.custom]?.sql : null;
|
|
41
|
-
const search = loadTable.meta?.search && query.search ? `(${loadTable.meta?.search.split(',').map(el => `${el} ilike '%${query.search}%'`).join(' or ')})` : null;
|
|
42
|
-
|
|
43
|
-
const where = [(params.id ? ` "${pk}" = $1` : null), keyQuery, loadTable.query, fData.q, state, custom, search].filter((el) => el);
|
|
44
|
-
const q = `select ${pk ? `"${pk}" as id,` : ''} ${query.id || query.key ? '*' : cols || '*'} from ${table} t ${sqlTable} where ${where.join(' and ') || 'true'} ${offset} ${order} limit ${limit}`;
|
|
45
|
-
|
|
46
|
-
if (query.sql === '1') { return q; }
|
|
47
|
-
|
|
48
|
-
const { rows } = await pg.query(q, (params.id ? [params.id] : null) || (query.key && loadTable.key ? [query.key] : []));
|
|
49
|
-
|
|
50
|
-
const total = keyQuery || params.id ? rows.length : await pg.queryCache(`select count(*) from ${table} t where ${where.join(' and ') || 'true'}`).then((el) => el?.rows[0]?.count);
|
|
51
|
-
|
|
52
|
-
return {
|
|
53
|
-
time: Date.now() - time, total, pk, form, rows, meta, columns, filters,
|
|
54
|
-
};
|
|
55
|
-
}
|
|
1
|
+
import getTemplate from './utils/getTemplate.js';
|
|
2
|
+
import getFilterSQL from '../funcs/getFilterSQL/index.js';
|
|
3
|
+
import getMeta from '../../pg/funcs/getMeta.js';
|
|
4
|
+
|
|
5
|
+
const maxLimit = 100;
|
|
6
|
+
export default async function data(req) {
|
|
7
|
+
const time = Date.now();
|
|
8
|
+
const {
|
|
9
|
+
pg, params, query = {},
|
|
10
|
+
} = req;
|
|
11
|
+
|
|
12
|
+
const loadTable = await getTemplate('table', params.table);
|
|
13
|
+
|
|
14
|
+
if (!loadTable) { return { status: 404, message: 'not found' }; }
|
|
15
|
+
|
|
16
|
+
const {
|
|
17
|
+
table, columns, sql, filters, form, meta,
|
|
18
|
+
} = loadTable;
|
|
19
|
+
const { pk } = await getMeta(table);
|
|
20
|
+
|
|
21
|
+
const cols = columns.map((el) => el.name || el).join(',');
|
|
22
|
+
const sqlTable = sql?.filter?.((el) => !el?.disabled && el?.sql?.replace).map((el, i) => ` left join lateral (${el.sql}) ${el.name || `t${i}`} on 1=1 `)?.join('') || '';
|
|
23
|
+
|
|
24
|
+
const fData = query.filter ? await getFilterSQL({
|
|
25
|
+
filter: query.filter,
|
|
26
|
+
table,
|
|
27
|
+
json: 1,
|
|
28
|
+
}) : {};
|
|
29
|
+
|
|
30
|
+
const keyQuery = query.key && loadTable.key && !params.id ? `${loadTable.key}=$1` : null;
|
|
31
|
+
|
|
32
|
+
const limit = Math.min(maxLimit, +(query.limit || 10));
|
|
33
|
+
|
|
34
|
+
const offset = query.page ? ` offset ${(query.page - 1) * limit}` : '';
|
|
35
|
+
// id, query, filter
|
|
36
|
+
const orderColumn = query.order || loadTable.order;
|
|
37
|
+
|
|
38
|
+
const order = cols.includes(orderColumn) ? `order by ${orderColumn} ${query.desc ? 'desc' : ''}` : '';
|
|
39
|
+
const state = loadTable.filterState && query.state ? loadTable.filterState[query.state]?.sql : null;
|
|
40
|
+
const custom = loadTable.filterCustom && query.custom ? loadTable.filterCustom[query.custom]?.sql : null;
|
|
41
|
+
const search = loadTable.meta?.search && query.search ? `(${loadTable.meta?.search.split(',').map(el => `${el} ilike '%${query.search}%'`).join(' or ')})` : null;
|
|
42
|
+
|
|
43
|
+
const where = [(params.id ? ` "${pk}" = $1` : null), keyQuery, loadTable.query, fData.q, state, custom, search].filter((el) => el);
|
|
44
|
+
const q = `select ${pk ? `"${pk}" as id,` : ''} ${query.id || query.key ? '*' : cols || '*'} from ${table} t ${sqlTable} where ${where.join(' and ') || 'true'} ${offset} ${order} limit ${limit}`;
|
|
45
|
+
|
|
46
|
+
if (query.sql === '1') { return q; }
|
|
47
|
+
|
|
48
|
+
const { rows } = await pg.query(q, (params.id ? [params.id] : null) || (query.key && loadTable.key ? [query.key] : []));
|
|
49
|
+
|
|
50
|
+
const total = keyQuery || params.id ? rows.length : await pg.queryCache(`select count(*) from ${table} t where ${where.join(' and ') || 'true'}`).then((el) => el?.rows[0]?.count);
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
time: Date.now() - time, total, pk, form, rows, meta, columns, filters,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import getTemplate from './utils/getTemplate.js';
|
|
2
|
-
import getSelect from './utils/getSelect.js';
|
|
3
|
-
|
|
4
|
-
export default async function filter(req) {
|
|
5
|
-
const time = Date.now();
|
|
6
|
-
const {
|
|
7
|
-
params,
|
|
8
|
-
} = req;
|
|
9
|
-
const loadTable = await getTemplate('table', params.table);
|
|
10
|
-
if (!loadTable) { return { status: 404, message: 'not found' }; }
|
|
11
|
-
|
|
12
|
-
const filters = loadTable?.filters || loadTable?.filterList || [];
|
|
13
|
-
await Promise.all(filters.filter((el) => el.data).map(async (el) => {
|
|
14
|
-
const cls = await getSelect(el.data);
|
|
15
|
-
Object.assign(el, { options: cls?.arr });
|
|
16
|
-
}));
|
|
17
|
-
return {
|
|
18
|
-
time: Date.now() - time,
|
|
19
|
-
list: filters,
|
|
20
|
-
custom: loadTable?.filterCustom?.map(el => ({ label: el.label })),
|
|
21
|
-
inline: loadTable?.filterInline,
|
|
22
|
-
state: loadTable?.filterState?.map(el => ({ label: el.label })),
|
|
23
|
-
};
|
|
24
|
-
}
|
|
1
|
+
import getTemplate from './utils/getTemplate.js';
|
|
2
|
+
import getSelect from './utils/getSelect.js';
|
|
3
|
+
|
|
4
|
+
export default async function filter(req) {
|
|
5
|
+
const time = Date.now();
|
|
6
|
+
const {
|
|
7
|
+
params,
|
|
8
|
+
} = req;
|
|
9
|
+
const loadTable = await getTemplate('table', params.table);
|
|
10
|
+
if (!loadTable) { return { status: 404, message: 'not found' }; }
|
|
11
|
+
|
|
12
|
+
const filters = loadTable?.filters || loadTable?.filterList || [];
|
|
13
|
+
await Promise.all(filters.filter((el) => el.data).map(async (el) => {
|
|
14
|
+
const cls = await getSelect(el.data);
|
|
15
|
+
Object.assign(el, { options: cls?.arr });
|
|
16
|
+
}));
|
|
17
|
+
return {
|
|
18
|
+
time: Date.now() - time,
|
|
19
|
+
list: filters,
|
|
20
|
+
custom: loadTable?.filterCustom?.map(el => ({ label: el.label })),
|
|
21
|
+
inline: loadTable?.filterInline,
|
|
22
|
+
state: loadTable?.filterState?.map(el => ({ label: el.label })),
|
|
23
|
+
};
|
|
24
|
+
}
|