@opengis/gis 0.1.24 → 0.1.26
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/import-file.cjs +139 -139
- package/dist/import-file.css +1 -1
- package/dist/import-file.js +12627 -11587
- package/module/gis/card/gis.maps.table/index.yml +3 -0
- package/module/gis/card/gis.metadata.table/index.yml +3 -0
- package/module/gis/card/gis.rasters.table/index.yml +3 -0
- package/module/gis/card/gis.registers.table/index.yml +3 -0
- package/module/gis/card/gis.services.table/index.yml +3 -0
- package/module/gis/table/gis.metadata.table.json +70 -70
- package/package.json +6 -5
- package/server/helpers/core/badge.js +17 -0
- package/server/helpers/core/buttonFilePreview.js +13 -0
- package/server/helpers/core/buttonHelper.js +21 -0
- package/server/helpers/core/coalesce.js +8 -0
- package/server/helpers/core/select.js +48 -0
- package/server/helpers/core/token.js +19 -0
- package/server/helpers/index.js +43 -0
- package/server/helpers/list/buttonHelper.js +21 -0
- package/server/helpers/list/descriptionList.js +46 -0
- package/server/helpers/list/tableList.js +86 -0
- package/server/helpers/list/utils/button.js +6 -0
- package/server/helpers/list/utils/buttonDel.js +13 -0
- package/server/helpers/list/utils/buttonEdit.js +15 -0
- package/server/helpers/temp/contentList.js +58 -0
- package/server/helpers/temp/ifCond.js +101 -0
- package/server/helpers/utils/button.js +6 -0
- package/server/helpers/utils/buttonAdd.js +7 -0
- package/server/helpers/utils/buttonDel.js +26 -0
- package/server/helpers/utils/buttonDownload.js +3 -0
- package/server/helpers/utils/buttonEdit.js +19 -0
- package/server/helpers/utils/buttonPreview.js +3 -0
- package/server/helpers/utils/mdToHTML.js +17 -0
- package/server/helpers/utils/paddingNumber.js +4 -0
- package/server/plugins/vite.js +12 -3
- package/server/routes/gis/index.mjs +3 -0
- package/server/routes/gis/registers/funcs/content.type.js +10 -0
- package/server/routes/gis/registers/funcs/get.info.js +89 -0
- package/server/routes/gis/registers/gis.export.js +149 -0
|
@@ -1,71 +1,71 @@
|
|
|
1
|
-
{
|
|
2
|
-
"table": "gis.metadata",
|
|
3
|
-
"key": "metadata_id",
|
|
4
|
-
"form": "gis.metadata.form",
|
|
5
|
-
"meta": {
|
|
6
|
-
"title": "name",
|
|
7
|
-
"search": "name"
|
|
8
|
-
},
|
|
9
|
-
"order": "created_at desc",
|
|
10
|
-
"actions": [
|
|
11
|
-
"edit",
|
|
12
|
-
"del",
|
|
13
|
-
"add"
|
|
14
|
-
],
|
|
15
|
-
"columns": [
|
|
16
|
-
{
|
|
17
|
-
"ua": "Назва метаданих",
|
|
18
|
-
"name": "name",
|
|
19
|
-
"meta": "title",
|
|
20
|
-
"format": "text"
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
"ua": "Ресурс",
|
|
24
|
-
"name": "layer_id",
|
|
25
|
-
"data": "service_id",
|
|
26
|
-
"format": "select"
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"ua": "Суб'єкт, що є власником ресурсу",
|
|
30
|
-
"name": "contact_id",
|
|
31
|
-
"data": "account_id",
|
|
32
|
-
"format": "select"
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
"ua": "Код КАТОТТГ",
|
|
36
|
-
"name": "katottg",
|
|
37
|
-
"format": "text"
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
"ua": "Тематична категорія ресурсу",
|
|
41
|
-
"name": "topic_category",
|
|
42
|
-
"data": "topic_category",
|
|
43
|
-
"format": "select"
|
|
44
|
-
}
|
|
45
|
-
],
|
|
46
|
-
"filterList": [
|
|
47
|
-
{
|
|
48
|
-
"ua": "Ресурс",
|
|
49
|
-
"name": "layer_id",
|
|
50
|
-
"type": "Autocomplete",
|
|
51
|
-
"data": "service_id"
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
"ua": "Назва метаданих",
|
|
55
|
-
"name": "name",
|
|
56
|
-
"type": "Text"
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
"ua": "Суб'єкт, що є власником ресурсу",
|
|
60
|
-
"name": "contact_id",
|
|
61
|
-
"type": "Autocomplete",
|
|
62
|
-
"data": "service_id"
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
"ua": "Тематична категорія ресурсу",
|
|
66
|
-
"name": "topic_category",
|
|
67
|
-
"type": "Autocomplete",
|
|
68
|
-
"data": "topic_category"
|
|
69
|
-
}
|
|
70
|
-
]
|
|
1
|
+
{
|
|
2
|
+
"table": "gis.metadata",
|
|
3
|
+
"key": "metadata_id",
|
|
4
|
+
"form": "gis.metadata.form",
|
|
5
|
+
"meta": {
|
|
6
|
+
"title": "name",
|
|
7
|
+
"search": "name"
|
|
8
|
+
},
|
|
9
|
+
"order": "created_at desc",
|
|
10
|
+
"actions": [
|
|
11
|
+
"edit",
|
|
12
|
+
"del",
|
|
13
|
+
"add"
|
|
14
|
+
],
|
|
15
|
+
"columns": [
|
|
16
|
+
{
|
|
17
|
+
"ua": "Назва метаданих",
|
|
18
|
+
"name": "name",
|
|
19
|
+
"meta": "title",
|
|
20
|
+
"format": "text"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"ua": "Ресурс",
|
|
24
|
+
"name": "layer_id",
|
|
25
|
+
"data": "service_id",
|
|
26
|
+
"format": "select"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"ua": "Суб'єкт, що є власником ресурсу",
|
|
30
|
+
"name": "contact_id",
|
|
31
|
+
"data": "account_id",
|
|
32
|
+
"format": "select"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"ua": "Код КАТОТТГ",
|
|
36
|
+
"name": "katottg",
|
|
37
|
+
"format": "text"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"ua": "Тематична категорія ресурсу",
|
|
41
|
+
"name": "topic_category",
|
|
42
|
+
"data": "topic_category",
|
|
43
|
+
"format": "select"
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
"filterList": [
|
|
47
|
+
{
|
|
48
|
+
"ua": "Ресурс",
|
|
49
|
+
"name": "layer_id",
|
|
50
|
+
"type": "Autocomplete",
|
|
51
|
+
"data": "service_id"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"ua": "Назва метаданих",
|
|
55
|
+
"name": "name",
|
|
56
|
+
"type": "Text"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"ua": "Суб'єкт, що є власником ресурсу",
|
|
60
|
+
"name": "contact_id",
|
|
61
|
+
"type": "Autocomplete",
|
|
62
|
+
"data": "service_id"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"ua": "Тематична категорія ресурсу",
|
|
66
|
+
"name": "topic_category",
|
|
67
|
+
"type": "Autocomplete",
|
|
68
|
+
"data": "topic_category"
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
71
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengis/gis",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.26",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "Softpro",
|
|
6
6
|
"main": "dist/import-file.js",
|
|
@@ -30,8 +30,10 @@
|
|
|
30
30
|
"@grpc/grpc-js": "1.13.4",
|
|
31
31
|
"@grpc/proto-loader": "0.7.15",
|
|
32
32
|
"@mapbox/sphericalmercator": "1.2.0",
|
|
33
|
-
"@opengis/fastify-
|
|
34
|
-
"@opengis/
|
|
33
|
+
"@opengis/fastify-file": "1.1.2",
|
|
34
|
+
"@opengis/fastify-table": "1.4.14",
|
|
35
|
+
"@opengis/fastify-auth": "1.1.0",
|
|
36
|
+
"@opengis/v3-core": "^0.3.196",
|
|
35
37
|
"@opengis/v3-filter": "0.1.18",
|
|
36
38
|
"@turf/turf": "7.2.0",
|
|
37
39
|
"axios": "1.9.0",
|
|
@@ -45,7 +47,6 @@
|
|
|
45
47
|
"monaco-editor": "^0.52.2",
|
|
46
48
|
"vue": "^3.5.13",
|
|
47
49
|
"vue-router": "4.5.1",
|
|
48
|
-
"vue3-smooth-dnd": "0.0.6",
|
|
49
50
|
"yaml": "^2.8.0"
|
|
50
51
|
},
|
|
51
52
|
"devDependencies": {
|
|
@@ -56,4 +57,4 @@
|
|
|
56
57
|
"sass-embedded": "1.86.3",
|
|
57
58
|
"vite": "^6.3.5"
|
|
58
59
|
}
|
|
59
|
-
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { getSelect } from "@opengis/fastify-table/utils.js";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export default async function badge(id, options) {
|
|
6
|
+
if (!id?.toString) return '-';
|
|
7
|
+
const data = options.hash?.data;
|
|
8
|
+
if (!data) return id;
|
|
9
|
+
const classifier = await getSelect(data);
|
|
10
|
+
if (!classifier?.arr) return id;
|
|
11
|
+
|
|
12
|
+
const item = classifier?.arr.find(el => el.id?.toString?.() === id.toString());
|
|
13
|
+
if (!item) return id;
|
|
14
|
+
return `<span style='color:${item.color || '#14b8a6'};border-color:${item.color || '#14b8a6'}; overflow:hidden;
|
|
15
|
+
text-overflow:ellipsis; white-space:nowrap;' class="block w-fit py-1.5 px-3 rounded-full text-xs font-medium border border-teal-500 text-teal-500 max-w-[220px] text-nowrap ">${item.text}</span>`
|
|
16
|
+
|
|
17
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
import buttonPreview from '../utils/buttonPreview.js';
|
|
3
|
+
import buttonDownload from '../utils/buttonDownload.js';
|
|
4
|
+
|
|
5
|
+
export default function buttonFilePreviewHelper(data, options = {}) {
|
|
6
|
+
const { hash } = options;
|
|
7
|
+
if (data && typeof data !== 'string') return 'wrong input data type';
|
|
8
|
+
if (!data) return '';
|
|
9
|
+
|
|
10
|
+
const preview = buttonPreview(data);
|
|
11
|
+
const download = buttonDownload(data);
|
|
12
|
+
return `<div class='flex gap-x-2'>${hash?.action === 'download' ? '' : preview}${hash?.action === 'preview' ? '' : download}</div>`;
|
|
13
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import buttonAdd from "../utils/buttonAdd.js";
|
|
2
|
+
import buttonDel from "../utils/buttonDel.js";
|
|
3
|
+
import buttonEdit from "../utils/buttonEdit.js";
|
|
4
|
+
import button from "../utils/button.js";
|
|
5
|
+
export default function buttonHelper(data, opt) {
|
|
6
|
+
const { hash } = opt;
|
|
7
|
+
|
|
8
|
+
// console.log(params)
|
|
9
|
+
|
|
10
|
+
if (!hash.token) return "token empty";
|
|
11
|
+
if (hash.add) {
|
|
12
|
+
return buttonAdd(hash.token, hash.title);
|
|
13
|
+
}
|
|
14
|
+
if (hash.del) {
|
|
15
|
+
return buttonDel(hash.token, hash.title, hash.icon);
|
|
16
|
+
}
|
|
17
|
+
if (hash.edit) {
|
|
18
|
+
return buttonEdit(hash.token, hash.title, hash.icon);
|
|
19
|
+
}
|
|
20
|
+
return button(hash.token, hash.title);
|
|
21
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { getPG, getSelect } from "@opengis/fastify-table/utils.js";
|
|
2
|
+
const pg = getPG();
|
|
3
|
+
|
|
4
|
+
export default async function select(ids, options) {
|
|
5
|
+
if (!ids || (Array.isArray(ids) && ids.length === 0) || ids === '') {
|
|
6
|
+
return '';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const data = options.hash?.data;
|
|
10
|
+
if (!data && data !== false && data !== 0) return '';
|
|
11
|
+
try {
|
|
12
|
+
const idsArray = Array.isArray(ids) ? ids : [ids];
|
|
13
|
+
|
|
14
|
+
const classifier = await getSelect(data);
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
if (!classifier) return `Не знайдено класифікатор ${data}`;
|
|
19
|
+
|
|
20
|
+
const arr = classifier.arr || []
|
|
21
|
+
if (classifier.sql && typeof classifier.sql === 'string') {
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
const metaQuery = `SELECT * FROM (${classifier.sql})q LIMIT 0`;
|
|
26
|
+
const meta = await pg.query(metaQuery);
|
|
27
|
+
const idColumn = meta.fields[0].name;
|
|
28
|
+
const textColumn = meta.fields[1].name;
|
|
29
|
+
|
|
30
|
+
const q = `SELECT "${idColumn}" AS id, "${textColumn}" AS text FROM (${classifier.sql}) q WHERE "${idColumn}"::text = ANY($1::text[])`;
|
|
31
|
+
const values = [idsArray.map(id => String(id))];
|
|
32
|
+
|
|
33
|
+
const { rows } = await pg.query(q, values);
|
|
34
|
+
Object.assign(arr, rows);
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
if (!arr.length) return idsArray;
|
|
38
|
+
|
|
39
|
+
const results = idsArray.map(id => {
|
|
40
|
+
const result = arr.find(el => String(el.id) == String(id));
|
|
41
|
+
return result ? result.text : '';
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return results.filter(Boolean).join(', ');
|
|
45
|
+
} catch (err) {
|
|
46
|
+
return `Сталася помилка.<!-- err: ${err.toString()} -->`;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { setToken } from "@opengis/fastify-table/utils.js";
|
|
2
|
+
|
|
3
|
+
export default function token(params) {
|
|
4
|
+
|
|
5
|
+
const { data, hash } = params;
|
|
6
|
+
|
|
7
|
+
if (!data?.root?.user?.uid && !hash.uid) return '-';
|
|
8
|
+
if (!hash || typeof hash !== 'object') return '-';
|
|
9
|
+
|
|
10
|
+
// const id = hash?.edit ? hash?.id : data?.root?.id;
|
|
11
|
+
// console.log(hash)
|
|
12
|
+
const [token] = setToken({
|
|
13
|
+
ids: [JSON.stringify(hash)],
|
|
14
|
+
|
|
15
|
+
uid: data?.root?.user?.uid || hash.uid,
|
|
16
|
+
array: 1,
|
|
17
|
+
});
|
|
18
|
+
return token;
|
|
19
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
|
|
2
|
+
import { handlebars, handlebarsSync } from "@opengis/fastify-table/utils.js";
|
|
3
|
+
|
|
4
|
+
import token from "./core/token.js";
|
|
5
|
+
import descriptionList from "./list/descriptionList.js";
|
|
6
|
+
import tableList from "./list/tableList.js";
|
|
7
|
+
import buttonHelper from "./core/buttonHelper.js";
|
|
8
|
+
import buttonFilePreview from "./core/buttonFilePreview.js";
|
|
9
|
+
import select from "./core/select.js";
|
|
10
|
+
import badge from "./core/badge.js";
|
|
11
|
+
import coalesce from "./core/coalesce.js";
|
|
12
|
+
import mdToHTML from "./utils/mdToHTML.js";
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
import ifCond from "./temp/ifCond.js";
|
|
16
|
+
import contentList from "./temp/contentList.js";
|
|
17
|
+
import paddingNumber from './utils/paddingNumber.js';
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
export default async function route() {
|
|
22
|
+
|
|
23
|
+
handlebars.registerHelper('token', token);
|
|
24
|
+
handlebars.registerHelper('mdToHTML', mdToHTML);
|
|
25
|
+
handlebars.registerHelper('descriptionList', descriptionList);
|
|
26
|
+
handlebars.registerHelper('tableList', tableList);
|
|
27
|
+
handlebars.registerHelper('button', buttonHelper);
|
|
28
|
+
handlebars.registerHelper('buttonFilePreview', buttonFilePreview);
|
|
29
|
+
handlebarsSync.registerHelper('buttonFilePreview', buttonFilePreview);
|
|
30
|
+
handlebars.registerHelper('select', select);
|
|
31
|
+
handlebars.registerHelper('badge', badge);
|
|
32
|
+
handlebars.registerHelper('contentList', contentList);
|
|
33
|
+
handlebarsSync.registerHelper('ifCond', ifCond);
|
|
34
|
+
handlebarsSync.registerHelper('button', buttonHelper);
|
|
35
|
+
handlebars.registerHelper('ifCond', ifCond);
|
|
36
|
+
handlebars.registerHelper('empty', () => { });
|
|
37
|
+
handlebarsSync.registerHelper('empty', () => { });
|
|
38
|
+
handlebars.registerHelper('coalesce', coalesce);
|
|
39
|
+
handlebarsSync.registerHelper('coalesce', coalesce);
|
|
40
|
+
|
|
41
|
+
handlebarsSync.registerHelper('paddingNumber', paddingNumber);
|
|
42
|
+
handlebars.registerHelper('paddingNumber', paddingNumber);
|
|
43
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import buttonAdd from "../utils/buttonAdd.js";
|
|
2
|
+
import buttonDel from "../utils/buttonDel.js";
|
|
3
|
+
import buttonEdit from "../utils/buttonEdit.js";
|
|
4
|
+
import button from "../utils/button.js";
|
|
5
|
+
export default function buttonHelper(data, opt) {
|
|
6
|
+
const { hash } = opt;
|
|
7
|
+
|
|
8
|
+
// console.log(params)
|
|
9
|
+
|
|
10
|
+
if (!hash.token) return "token empty";
|
|
11
|
+
if (hash.add) {
|
|
12
|
+
return buttonAdd(hash.token, hash.title);
|
|
13
|
+
}
|
|
14
|
+
if (hash.del) {
|
|
15
|
+
return buttonDel(hash.token, hash.title);
|
|
16
|
+
}
|
|
17
|
+
if (hash.edit) {
|
|
18
|
+
return buttonEdit(hash.token, hash.title);
|
|
19
|
+
}
|
|
20
|
+
return button(hash.token, hash.title);
|
|
21
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { handlebars } from '@opengis/fastify-table/utils.js'
|
|
2
|
+
|
|
3
|
+
async function format(d, key, data) {
|
|
4
|
+
|
|
5
|
+
if (!key?.includes) return '';
|
|
6
|
+
if (d === true) return 'Так';
|
|
7
|
+
if (d === false) return 'Ні';
|
|
8
|
+
|
|
9
|
+
if (key.includes('{{')) {
|
|
10
|
+
return await handlebars.compile(key)(data);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return d;
|
|
14
|
+
}
|
|
15
|
+
export default async function descriptionList(data, opt) {
|
|
16
|
+
const { hash } = opt;
|
|
17
|
+
|
|
18
|
+
// no data
|
|
19
|
+
if (hash.nodata && !data) {
|
|
20
|
+
const noDataText = typeof hash.nodata == 'string' ? hash.nodata : '<div class="bg-gray-200 text-center p-6 rounded-xl"><h3 class="text-lg font-semibold">Інформація відсутня</h3></div>';
|
|
21
|
+
return noDataText
|
|
22
|
+
}
|
|
23
|
+
if (!hash.columns) return 'columns empty'
|
|
24
|
+
const keys = hash.columns.split(hash.divider || ',').map(el => hash.comma ? el.trim().replace(new RegExp(hash.comma || '#', 'g'), ',') : el.trim());
|
|
25
|
+
|
|
26
|
+
const result = [];
|
|
27
|
+
|
|
28
|
+
for (let i = 0; i < keys.length; i += 2) {
|
|
29
|
+
const name = keys[i];
|
|
30
|
+
const nameHBS = name.includes('{{') ? await handlebars.compile(name)({ ...data, hash }) : false;
|
|
31
|
+
|
|
32
|
+
if (!nameHBS && name.includes('{{')) continue;
|
|
33
|
+
|
|
34
|
+
const key = keys[i + 1];
|
|
35
|
+
|
|
36
|
+
const d1 = await format(data[key], key, data) || '-';
|
|
37
|
+
|
|
38
|
+
result.push(`<div class="grid grid-cols-1 gap-1 py-3 sm:grid-cols-3 sm:gap-4 even:bg-gray-50 text-[12px]">
|
|
39
|
+
<dt class="text-gray-900">${nameHBS || name}</dt>
|
|
40
|
+
<dd class="text-gray-700 sm:col-span-2">${d1}</dd>
|
|
41
|
+
</div>
|
|
42
|
+
`);
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
return '<dl class=" divide-y divide-gray-100 py-[5px] w-full">' + result.join('') + '</dl>';
|
|
46
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { setToken, handlebars } from '@opengis/fastify-table/utils.js'
|
|
2
|
+
|
|
3
|
+
import buttonEdit from './utils/buttonEdit.js';
|
|
4
|
+
import buttonDel from './utils/buttonDel.js';
|
|
5
|
+
|
|
6
|
+
function format(d, key, data, hash) {
|
|
7
|
+
if (!key?.includes) return '';
|
|
8
|
+
if (d === true) return 'Так';
|
|
9
|
+
if (d === false) return 'Ні';
|
|
10
|
+
if (key === 'actions') {
|
|
11
|
+
return `<div class="flex items-center gap-2">${(hash.form ? buttonEdit(d, 'Редагувати') : '') + buttonDel(d)}</div>`
|
|
12
|
+
}
|
|
13
|
+
if (key.startsWith('{{')) {
|
|
14
|
+
return handlebars.compile(key)(data);
|
|
15
|
+
} else if (key.startsWith('{{') && key.includes(' ') && !(key.match(/\{\{([^\s]+)/)?.[1] in handlebars.helpers)) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
if (!d) return '-';
|
|
19
|
+
return d;
|
|
20
|
+
}
|
|
21
|
+
export default async function tableList(data, opt) {
|
|
22
|
+
|
|
23
|
+
const { hash } = opt;
|
|
24
|
+
// no data
|
|
25
|
+
// const time = Date.now();
|
|
26
|
+
if (hash.nodata && !data?.length) {
|
|
27
|
+
const noDataText = typeof hash.nodata == 'string' ? hash.nodata : '<div class="bg-gray-200 text-center p-6 rounded-xl"><h3 class="text-lg font-semibold">Інформація відсутня</h3></div>';
|
|
28
|
+
return noDataText
|
|
29
|
+
}
|
|
30
|
+
if (!hash.columns) return 'columns empty'
|
|
31
|
+
const keys = hash.columns.split(hash.divider || ',').map(el => hash.comma ? el.trim().replace(new RegExp(hash.comma, 'g'), ',') : el.trim()).concat(hash.uid && hash.table && hash.id && !hash.noactions ? ['Дії', 'actions'] : []);
|
|
32
|
+
|
|
33
|
+
const result = [];
|
|
34
|
+
result.push('<thead class="text-left font-medium text-gray-700"> <tr>');
|
|
35
|
+
|
|
36
|
+
// thead
|
|
37
|
+
const skip = {}
|
|
38
|
+
for (let i = 0; i < keys.length; i += 2) {
|
|
39
|
+
const name = keys[i];
|
|
40
|
+
|
|
41
|
+
// check hbs
|
|
42
|
+
if (name.includes('{{')) {
|
|
43
|
+
console.log(hash)
|
|
44
|
+
}
|
|
45
|
+
const nameHBS = name.includes('{{') ? await handlebars.compile(name)({ ...data, hash }) : false;
|
|
46
|
+
// console.log(name, data, nameHBS)
|
|
47
|
+
skip[name] = name.includes('{{') && !nameHBS;
|
|
48
|
+
if (skip[name]) continue;
|
|
49
|
+
|
|
50
|
+
const isActionsColumn = hash.noactions && i === keys.length - 2;
|
|
51
|
+
result.push(`<th class="py-2 min-w-[200px] ${isActionsColumn ? 'last:min-w-[60px] last:max-w-[60px] last:bg-white last:sticky last:right-0' : ''}">
|
|
52
|
+
${nameHBS || name}
|
|
53
|
+
</th>`)
|
|
54
|
+
}
|
|
55
|
+
result.push('</tr></thead><tbody class="divide-y divide-gray-200">');
|
|
56
|
+
|
|
57
|
+
// body
|
|
58
|
+
for (let k = 0; k < data.length; k += 1) {
|
|
59
|
+
const row = data[k];
|
|
60
|
+
result.push('<tr class="bg-white odd:bg-gray-50 ">');
|
|
61
|
+
const obj = { form: hash.form, table: hash.table, id: row[hash.id] }
|
|
62
|
+
const token = hash.table ? setToken({ ids: [JSON.stringify(obj)], uid: hash.uid, array: 1 })[0] : null;
|
|
63
|
+
for (let i = 0; i < keys.length; i += 2) {
|
|
64
|
+
|
|
65
|
+
const name = keys[i];
|
|
66
|
+
const key = keys[i + 1];
|
|
67
|
+
if (!key) continue;
|
|
68
|
+
if (skip[name]) continue;
|
|
69
|
+
|
|
70
|
+
const tokenData = key == 'actions' ? token : null;
|
|
71
|
+
const d1 = key.includes('{{') ? await handlebars.compile(key)({ ...row, token, hash }) || '-' : null
|
|
72
|
+
const isActionsColumn = hash.noactions && i === keys.length - 2;
|
|
73
|
+
result.push(`<td class="py-2 pr-5 ${isActionsColumn ? 'last:sticky last:right-0' : ''}">
|
|
74
|
+
${d1 || format(tokenData || row[key], key, row, hash)}
|
|
75
|
+
</td>`);
|
|
76
|
+
|
|
77
|
+
}
|
|
78
|
+
// action token
|
|
79
|
+
|
|
80
|
+
result.push('</tr>');
|
|
81
|
+
}
|
|
82
|
+
result.push('</tbody>');
|
|
83
|
+
|
|
84
|
+
// console.log(Date.now() - time)
|
|
85
|
+
return '<table class="min-w-full relative divide-y-2 divide-gray-200 bg-white min-w-full overflow-auto divide-y-2 divide-gray-200 bg-white text-[12px] text-gray-600">' + result.join('') + '</table>';
|
|
86
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export default function button(token, title) {
|
|
4
|
+
return `<button onclick="window.v3plugin.$form({ token: '${token}' })"
|
|
5
|
+
class="inline-flex items-center px-2 py-1 text-sm font-medium text-white duration-300 bg-blue-600 border border-transparent rounded-lg gap-x-2 hover:bg-blue-700 hover:text-white">${title || 'Додати'}</button>`;
|
|
6
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// export default function button(token, title) {
|
|
2
|
+
// return `<button onclick="window.v3plugin.$api({ api: '/api/table/${token}', method:'delete',confirm: { title:'Підтвердити операцію', text: 'Ви впевнені що хочете вилучити запис?', cancel: 'Скасувати', confirm : 'Виконати'} })"
|
|
3
|
+
// class="inline-flex items-center px-2 py-1 text-sm font-medium text-white duration-300 bg-red-600 border border-transparent rounded-lg gap-x-2 hover:bg-red-700 hover:text-white">${title || 'Вилучити'}</button>`;
|
|
4
|
+
// }
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const newColor = 'red'
|
|
8
|
+
export default function button(token, title) {
|
|
9
|
+
return `<button onclick="window.v3plugin.$api({ api: '/api/table/${token}', method:'delete',confirm: { title:'Підтвердити операцію', text: 'Ви впевнені що хочете вилучити запис?', cancel: 'Скасувати', confirm : 'Виконати'} })"
|
|
10
|
+
class="group px-2 py-1 inline-flex border-solid justify-center items-center gap-2 rounded-md font-semibold focus:outline-none text-sm transition-all border border-transparent hover:text-white ring-offset-white bg-${newColor}-100 text-${newColor}-100 hover:bg-${newColor}-500 focus:ring-${newColor}-500">
|
|
11
|
+
<svg class="group-hover:fill-white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" width="13" height="13" fill="#ef4444"><path d="M135.2 17.7L128 32 32 32C14.3 32 0 46.3 0 64S14.3 96 32 96l384 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-96 0-7.2-14.3C307.4 6.8 296.3 0 284.2 0L163.8 0c-12.1 0-23.2 6.8-28.6 17.7zM416 128L32 128 53.2 467c1.6 25.3 22.6 45 47.9 45l245.8 0c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>
|
|
12
|
+
</button>`;
|
|
13
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
// export default function button(token, title) {
|
|
4
|
+
// return `<button onclick="window.v3plugin.$form({ token: '${token}' })"
|
|
5
|
+
// class="inline-flex items-center px-2 py-1 text-sm font-medium text-white duration-300 bg-blue-600 border border-transparent rounded-lg gap-x-2 hover:bg-blue-700 hover:text-white">${title || 'Редагувати'}</button>`;
|
|
6
|
+
// }
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
const newColor = 'blue'
|
|
10
|
+
export default function button(token, title) {
|
|
11
|
+
return `<button onclick="window.v3plugin.$form({ token: '${token}' })"
|
|
12
|
+
class="group px-2 py-1 inline-flex border-solid justify-center items-center gap-2 rounded-md font-semibold focus:outline-none text-sm transition-all border border-transparent hover:text-white ring-offset-white bg-${newColor}-100 text-${newColor}-100 hover:bg-${newColor}-500 focus:ring-${newColor}-500">
|
|
13
|
+
<svg class="group-hover:fill-white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="13" height="13" fill="#3b82f6"><path d="M471.6 21.7c-21.9-21.9-57.3-21.9-79.2 0L362.3 51.7l97.9 97.9 30.1-30.1c21.9-21.9 21.9-57.3 0-79.2L471.6 21.7zm-299.2 220c-6.1 6.1-10.8 13.6-13.5 21.9l-29.6 88.8c-2.9 8.6-.6 18.1 5.8 24.6s15.9 8.7 24.6 5.8l88.8-29.6c8.2-2.7 15.7-7.4 21.9-13.5L437.7 172.3 339.7 74.3 172.4 241.7zM96 64C43 64 0 107 0 160L0 416c0 53 43 96 96 96l256 0c53 0 96-43 96-96l0-96c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 96c0 17.7-14.3 32-32 32L96 448c-17.7 0-32-14.3-32-32l0-256c0-17.7 14.3-32 32-32l96 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L96 64z"/></svg>
|
|
14
|
+
</button>`;
|
|
15
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import { getPG, handlebars } from '@opengis/fastify-table/utils.js';
|
|
4
|
+
|
|
5
|
+
const maxLimit = 100;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Відображення даних з таблиці або запиту до БД на сторінці. За запитом отримуємо масив json із рядків бази даних.
|
|
9
|
+
* Є можливість застосування синтаксису sql у змінній query для формування запиту до БД.
|
|
10
|
+
*
|
|
11
|
+
* @summary Відображення контенту на сторінці. Є можливість застосування синтаксису sql у змінній query.
|
|
12
|
+
* @priority 5
|
|
13
|
+
* @type helper
|
|
14
|
+
* @alias contentList
|
|
15
|
+
* @example
|
|
16
|
+
* {{#contentList table="help.doc_function" query="type='api'" sql1=1 limit=1}}{{#each rows}}{{{JSON 2 this}}}{{/each}}{{/contentList}}
|
|
17
|
+
* @example
|
|
18
|
+
* {{#contentList table="help.doc_function" sql1=1 query="name like '%form%'" limit=1}}{{#each rows}}{{{JSON 2 this}}}{{/each}}{{/contentList}}
|
|
19
|
+
* @example
|
|
20
|
+
* {{#contentList table="help.article" sql=1 query="module='CORE'" limit=1}}{{#each rows}}{{{JSON 2 this}}}{{/each}}{{/contentList}}
|
|
21
|
+
* @param {String} table Таблиця в базі або конфіг таблиця
|
|
22
|
+
* @param {String} query Запит до бази
|
|
23
|
+
* @param {Number} limit Кількість рядків на сторінці
|
|
24
|
+
* @param {String} sql Вивід sql запиту
|
|
25
|
+
* @returns {String} Returns HTML
|
|
26
|
+
*/
|
|
27
|
+
export default async function contentList(options) {
|
|
28
|
+
const { table, limit, query, order, sql, debug } = options.hash;
|
|
29
|
+
if (!table) { return 'Table undefined'; }
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
const pg = getPG();
|
|
33
|
+
|
|
34
|
+
const hasBrackets = table.trim().startsWith('(') && table.trim().endsWith(')');
|
|
35
|
+
|
|
36
|
+
const where = `where ${query ? query : '1=1'}`;
|
|
37
|
+
const _limit = limit !== undefined && limit !== null ? Math.min(maxLimit, +limit) : 15;
|
|
38
|
+
const _order = order ? `order by ${order}` : '';
|
|
39
|
+
|
|
40
|
+
const SQL = `select *,${pg.pk[table] || '1'}::text from ${hasBrackets ? table + ' t' : table} ${where} ${_order} limit ${_limit}`;
|
|
41
|
+
const compiledSQL = SQL.includes('{{') ? await handlebars.compile(SQL)({ ...options.data.root, hash: options.hash, opt: options.hash }) : SQL;
|
|
42
|
+
|
|
43
|
+
if (sql) {
|
|
44
|
+
return compiledSQL.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"')
|
|
45
|
+
.replaceAll("'", ''');
|
|
46
|
+
}
|
|
47
|
+
const { rows } = await pg.query(compiledSQL);
|
|
48
|
+
const data = { rows, total: rows.length, ...options.data?.root };
|
|
49
|
+
|
|
50
|
+
if (debug) {
|
|
51
|
+
return JSON.stringify(data, null, 2);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return options.fn(data);
|
|
55
|
+
} catch (err) {
|
|
56
|
+
return `Сталася помилка, зверніться до відділу підтримки.<!-- err: ${err.toString()} -->`;
|
|
57
|
+
}
|
|
58
|
+
};
|