@opengis/admin 0.3.105 → 0.3.107

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.
@@ -1,5 +1,5 @@
1
1
  import { resolveComponent as e, openBlock as r, createBlock as t } from "vue";
2
- import { _ as c } from "./import-file-Bs86FUW3.js";
2
+ import { _ as c } from "./import-file-DIAYCDNH.js";
3
3
  const n = {};
4
4
  function s(_, p, a, i, f, m) {
5
5
  const o = e("router-view");
@@ -1,4 +1,4 @@
1
- import { _ as $, s as k, u as V, g as d } from "./import-file-Bs86FUW3.js";
1
+ import { _ as $, s as k, u as V, g as d } from "./import-file-DIAYCDNH.js";
2
2
  import { resolveComponent as j, openBlock as p, createElementBlock as g, createElementVNode as m, normalizeClass as b, createCommentVNode as x, normalizeStyle as y, createBlock as E } from "vue";
3
3
  const O = {
4
4
  data() {
@@ -3705,27 +3705,27 @@ const Z4 = [
3705
3705
  {
3706
3706
  name: "edit",
3707
3707
  path: "/edit",
3708
- component: () => import("./edit-page-DVyHgdP0.js")
3708
+ component: () => import("./edit-page-DGjs4jeh.js")
3709
3709
  },
3710
3710
  {
3711
3711
  name: "add",
3712
3712
  path: "/add",
3713
- component: () => import("./add-page-BtME1JJf.js")
3713
+ component: () => import("./add-page-DELwNBs9.js")
3714
3714
  },
3715
3715
  {
3716
3716
  path: "/profile",
3717
3717
  name: "profile",
3718
- component: () => import("./profile-page-DHRxyJA_.js")
3718
+ component: () => import("./profile-page-CaQqFoqe.js")
3719
3719
  },
3720
3720
  {
3721
3721
  name: "card-view",
3722
3722
  path: "/card",
3723
- component: () => import("./card-view-BPUveYDd.js"),
3723
+ component: () => import("./card-view-Cb3j5eXY.js"),
3724
3724
  children: [
3725
3725
  {
3726
3726
  name: "table",
3727
3727
  path: ":table",
3728
- component: () => import("./card-view-BPUveYDd.js"),
3728
+ component: () => import("./card-view-Cb3j5eXY.js"),
3729
3729
  children: [
3730
3730
  {
3731
3731
  name: "card",
@@ -3786,14 +3786,14 @@ const eB = /* @__PURE__ */ ft(X4, [["render", Q4]]), tB = (t) => {
3786
3786
  {
3787
3787
  path: "/",
3788
3788
  name: "home",
3789
- component: () => import("./admin-view-URsx4MBX.js"),
3789
+ component: () => import("./admin-view-DnD5gBsl.js"),
3790
3790
  children: [
3791
3791
  ...t,
3792
3792
  ...e,
3793
3793
  // { path: '/', redirect: '/home' },
3794
3794
  {
3795
3795
  path: "/:catchAll(.*)",
3796
- component: () => import("./admin-interface-mIo1_gE2.js")
3796
+ component: () => import("./admin-interface-ChLQ5JCd.js")
3797
3797
  }
3798
3798
  ]
3799
3799
  }
@@ -61180,7 +61180,8 @@ const Jce = /* @__PURE__ */ ft(Zce, [["render", Kce]]), Qce = async (t, e, n, i
61180
61180
  __name: "admin-info-popover",
61181
61181
  props: {
61182
61182
  table: { type: String, default: () => "" },
61183
- id: { type: String, default: () => "" }
61183
+ id: { type: String, default: () => "" },
61184
+ api: { type: String, default: () => "" }
61184
61185
  },
61185
61186
  setup(t) {
61186
61187
  var _, k;
@@ -61193,7 +61194,7 @@ const Jce = /* @__PURE__ */ ft(Zce, [["render", Kce]]), Qce = async (t, e, n, i
61193
61194
  const f = async () => {
61194
61195
  try {
61195
61196
  const { data: C } = await lt.get(
61196
- `/api/table-data/${n.table}/${n.id}`
61197
+ `${n.api}/${n.table}/${n.id}`
61197
61198
  );
61198
61199
  i.value = C;
61199
61200
  } catch {
@@ -1,4 +1,4 @@
1
- import { _ as n, g as m } from "./import-file-Bs86FUW3.js";
1
+ import { _ as n, g as m } from "./import-file-DIAYCDNH.js";
2
2
  import { u as p } from "./user-B_2kh6ic.js";
3
3
  import { resolveComponent as d, openBlock as u, createElementBlock as f, createElementVNode as o, createBlock as h, createCommentVNode as b } from "vue";
4
4
  const x = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/admin",
3
- "version": "0.3.105",
3
+ "version": "0.3.107",
4
4
  "description": "This project Softpro Admin",
5
5
  "main": "dist/admin.js",
6
6
  "type": "module",
@@ -47,7 +47,7 @@
47
47
  "@fullcalendar/timegrid": "^6.1.15",
48
48
  "@fullcalendar/vue3": "^6.1.15",
49
49
  "@opengis/fastify-auth": "1.0.86",
50
- "@opengis/fastify-file": "1.0.82",
50
+ "@opengis/fastify-file": "1.0.83",
51
51
  "@opengis/fastify-table": "^1.3.52",
52
52
  "@opengis/v3-core": "^0.3.161",
53
53
  "@opengis/v3-filter": "^0.1.3",
@@ -14,6 +14,8 @@ export default async function reportList({
14
14
  name: el[0],
15
15
  filters: item?.filters || [],
16
16
  title: item?.title || el[0],
17
+ subtitle: item?.subtitle,
18
+ category: item?.category,
17
19
  sql: user.user_type?.includes('admin') ? item?.sql : undefined,
18
20
  };
19
21
  }));
@@ -1,14 +1,26 @@
1
1
  import path from 'node:path';
2
2
 
3
- import { pgClients, getTemplate, metaFormat, handlebarsSync } from '@opengis/fastify-table/utils.js';
3
+ import { pgClients, getTemplate, metaFormat } from '@opengis/fastify-table/utils.js';
4
4
 
5
5
  import getFilterQuery from '../utils/getFilterQuery.js';
6
+ import { downloadFile, getExport, getMimeType } from '@opengis/fastify-file/utils.js';
6
7
 
7
8
  const maxLimit = 100;
8
9
 
9
- export default async function tableData({
10
- pg = pgClients.client, params = {}, query = {}, user = {},
11
- }, reply) {
10
+ const matches = {
11
+ 16: 'yes/no', // boolean
12
+ 701: 'number', // double precision
13
+ 1082: 'date', // date
14
+ 1184: 'date', // timestamp w/ time zone
15
+ 1114: 'date', // timestamp w/o time zone
16
+ 1700: 'number', // numeric
17
+ };
18
+
19
+ export default async function tableData(req, reply) {
20
+ const {
21
+ pg = pgClients.client, params = {}, query = {}, user = {}, host, unittest,
22
+ } = req;
23
+
12
24
  if (!params?.name) {
13
25
  return { message: 'not enough params: name', status: 400 };
14
26
  }
@@ -31,11 +43,12 @@ export default async function tableData({
31
43
  });
32
44
  }
33
45
 
34
- const { title, subtitle, widgets = [], kpi, sql = `select * from ${loadTemplate.table} where ${loadTemplate.query || 'true'}`, meta, filters } = loadTemplate;
46
+ const { title, subtitle, category, widgets = [], kpi, sql = `select * from ${loadTemplate.table} where ${loadTemplate.query || 'true'}`, meta, filters } = loadTemplate;
35
47
  const { date, columns: metaColumns } = meta || {};
36
48
 
37
49
  const granularity = query.granularity && date && false ? `date_trunc('${query.granularity}',${date})::date::text` : null;
38
50
  const groupby = [meta?.groupby, granularity].filter(el => el).join(',');
51
+ const [orderby, ord] = (query.order || loadTemplate.orderby || '').replace(/ /, '-').split('-');
39
52
 
40
53
  const period = query.period && date ? `${date}=${query.period}` : null;
41
54
  const filter = [query.filter, period].filter(el => el).join(';');
@@ -45,14 +58,38 @@ export default async function tableData({
45
58
 
46
59
  const { fields = [] } = await pg.query(`select * from (${sql.replace(/{{uid}}/g, user?.uid)})q limit 0`);
47
60
 
48
- const where = filter ? getFilterQuery({ pg, filter, fields, filterList: filters })?.map?.(el => el.query)?.join(' and ') : null;
61
+ const where = getFilterQuery({ pg, filter, fields, filterList: filters, searchColumns: meta.search, search: query.search });
49
62
 
50
- const q = `select ${metaColumns || '*'} from (${sql.replace(/{{uid}}/g, user?.uid)})q where ${where || '1=1'} ${groupby ? `group by ${groupby}` : ''} limit ${limit} offset ${offset}`;
63
+ const orderbyColumnExists = fields?.find?.(el => el.name === orderby);
64
+ const q = `select ${metaColumns || '*'} from (${sql.replace(/{{uid}}/g, user?.uid)})q where ${where || '1=1'} ${groupby ? `group by ${groupby}` : ''} ${orderby && orderbyColumnExists ? `order by ${orderby} ${['asc', 'desc'].includes(ord) ? ord : 'desc'} nulls last` : ''} limit ${limit} offset ${offset}`;
51
65
 
52
66
  if (query.sql && user?.user_type?.includes('admin')) {
53
67
  return q;
54
68
  }
55
69
 
70
+ if (query.export) {
71
+ const resp = await getExport({
72
+ pg,
73
+ host,
74
+ unittest,
75
+ nocache: query.nocache,
76
+ tableSql: `select ${metaColumns || '*'} from (${sql.replace(/{{uid}}/g, user?.uid)})q where ${where || '1=1'}`,
77
+ sourceName: title || 'report',
78
+ columns: fields.map(({ name }) => ({ name, title: meta?.titles?.[name] || name })),
79
+ cls: meta?.cls,
80
+ format: ['xlsx', 'csv'].find(el => (req.query.format || 'xlsx') === el) || 'xlsx',
81
+ formatAnswer: 'filepath',
82
+ }, reply);
83
+ if (resp?.filePath) {
84
+ const buffer = await downloadFile(resp.filePath, { buffer: true });
85
+ const headers = {};
86
+ headers['Content-Type'] = `attachment; filename=${getMimeType(resp.filePath)}`;
87
+ headers['Content-Disposition'] = `attachment; filename=${path.basename(resp.filePath)}`;
88
+ return reply.status(200).headers(headers).send(buffer);
89
+ }
90
+ return resp;
91
+ }
92
+
56
93
  if (kpi?.length) {
57
94
  await Promise.all(kpi.map(async (el) => {
58
95
  if (!el.sql && !el.table) {
@@ -73,8 +110,6 @@ export default async function tableData({
73
110
  sql: user?.user_type === 'admin' ? el.sql : undefined
74
111
  }));
75
112
 
76
- const types = fields.reduce((acc, curr) => ({ ...acc, [curr.name]: pg.pgType?.[curr.dataTypeID] }), {});
77
-
78
113
  const { rows = [] } = await pg.query(q).catch(err => {
79
114
  return reply.status(500).send('query error: ' + err.toString());
80
115
  });
@@ -84,14 +119,7 @@ export default async function tableData({
84
119
  const columns = fields.map(el => ({
85
120
  name: el.name,
86
121
  title: meta?.titles?.[el.name] || el.name,
87
- type: meta?.cls?.[el.name]
88
- ? 'Autocomplete'
89
- : (
90
- ['date', 'timestamp with time zone', 'timestamp without time zone'].includes(types[el.name])
91
- ? 'Date'
92
- : null
93
- ) || 'Text',
94
- format: pg.pgType?.[el.dataTypeID],
122
+ format: meta?.cls?.[el.name] ? 'select' : (matches[el.dataTypeID] || 'text'),
95
123
  data: meta?.cls?.[el.name],
96
124
  }));
97
125
 
@@ -101,6 +129,7 @@ export default async function tableData({
101
129
  data: rows,
102
130
  title,
103
131
  subtitle,
132
+ category,
104
133
  widgets,
105
134
  columns,
106
135
  };
@@ -4,6 +4,37 @@ import { pgClients, getTemplate, metaFormat } from '@opengis/fastify-table/utils
4
4
 
5
5
  const maxLimit = 100;
6
6
 
7
+ const matches = {
8
+ 16: 'yes/no', // boolean
9
+ 701: 'number', // double precision
10
+ 1082: 'date', // date
11
+ 1184: 'date', // timestamp w/ time zone
12
+ 1114: 'date', // timestamp w/o time zone
13
+ 1700: 'number', // numeric
14
+ };
15
+
16
+ function normalizeData(widget, limit = maxLimit, offset = 0) {
17
+ const groupby = typeof widget.groupby === 'string'
18
+ ? { name: widget.groupby }
19
+ : (widget.groupby?.[0] || widget.groupby);
20
+
21
+ const agg = groupby.name
22
+ ? `${widget.granularity ? `date_trunc('${widget.granularity}', ${groupby.name})` : `${groupby.name}`}`
23
+ : 'count(*)';
24
+
25
+ const xCol = widget.granularity
26
+ ? `date_trunc('${widget.granularity}', ${groupby.name})`
27
+ : groupby.name;
28
+
29
+ const sql = `select * from ${widget.table} where ${widget.query || 'true'} limit ${limit} offset ${offset}`;
30
+
31
+ const q = `select ${agg} as ${groupby.name}, ${widget.agg} as metric from (${sql}) t
32
+ ${groupby.name ? `group by ${xCol}` : ''}
33
+ ${widget.orderby || xCol ? `order by ${widget.orderby || xCol}` : ''}`;
34
+
35
+ return { groupby, agg, xCol, q };
36
+ }
37
+
7
38
  export default async function widgetData({
8
39
  pg = pgClients.client, params = {}, query = {}, user = {},
9
40
  }, reply) {
@@ -43,34 +74,15 @@ export default async function widgetData({
43
74
 
44
75
  const { cls = {}, titles = {} } = widget.meta || {};
45
76
 
77
+ const limit = Math.min(query.limit || maxLimit, maxLimit);
46
78
  const offset = query.page && query.page > 0 ? (query.page - 1) * limit : 0;
47
- const sql = widget.sql || `select * from ${widget.table} where ${widget.query || 'true'} limit ${maxLimit} offset ${offset}`;
48
79
 
49
- const groupby = typeof widget.groupby === 'string'
50
- ? { name: widget.groupby }
51
- : (widget.groupby?.[0] || widget.groupby);
80
+ const { groupby, q } = normalizeData(widget, limit, offset);
52
81
 
53
82
  if (groupby.cls) {
54
83
  Object.assign(cls, { [groupby.name]: groupby.cls });
55
84
  }
56
85
 
57
- const xCol = widget.granularity
58
- ? `date_trunc('${widget.granularity}', ${groupby.name})`
59
- : groupby.name;
60
-
61
- const q = widget.agg
62
- ? `select ${widget.agg} as metric ${groupby.name
63
- ? `${widget.granularity
64
- ? `,date_trunc('${widget.granularity}', ${groupby.name})`
65
- : `,${groupby.name}`}`
66
- : ''
67
- } as ${groupby.name} from (${sql}) t ${groupby.name
68
- ? `group by ${xCol}`
69
- : ''
70
- }
71
- ${widget.orderby || xCol ? `order by ${widget.orderby || xCol}` : ''}`
72
- : sql;
73
-
74
86
  if (query.sql) return q;
75
87
 
76
88
  const { rows = [], fields = [] } = await pg.query(q).catch(err => {
@@ -78,19 +90,10 @@ export default async function widgetData({
78
90
  }) || {};
79
91
  await metaFormat({ rows, cls, sufix: false }, pg);
80
92
 
81
- const types = fields.reduce((acc, curr) => ({ ...acc, [curr.name]: pg.pgType?.[curr.dataTypeID] }), {});
82
-
83
93
  const columns = fields.map(el => ({
84
94
  name: el.name,
85
95
  title: titles?.[el.name] || el.name,
86
- type: cls?.[el.name]
87
- ? 'Autocomplete'
88
- : (
89
- ['date', 'timestamp with time zone', 'timestamp without time zone'].includes(types[el.name])
90
- ? 'Date'
91
- : null
92
- ) || 'Text',
93
- format: pg.pgType?.[el.dataTypeID],
96
+ format: cls?.[el.name] ? 'select' : (matches[el.dataTypeID] || 'text'),
94
97
  data: cls?.[el.name],
95
98
  }));
96
99
 
@@ -1,21 +1,21 @@
1
1
  /* eslint-disable no-continue */
2
2
 
3
- /**
4
- * @param {Number} opt.json - (1|0) 1 - Результат - Object, 0 - String
5
- * @param {String} opt.query - запит до таблиці
6
- * @param {String} opt.hash - інформація з хешу по запиту
7
- */
3
+ import { pgClients } from '@opengis/fastify-table/utils.js';
8
4
 
9
5
  import formatValue from './formatValue.js';
10
6
 
11
- function getFilterQuery({ pg, filter: filterStr, fields, filterList }) {
12
- if (!filterStr) return null; // filter list API
7
+ export default function getFilterQuery({ pg = pgClients.client, filter: filterStr, fields, filterList, searchColumns, search }) {
8
+ if (!filterStr && !search) return null;
13
9
 
14
10
  const mainOperators = ['=', '~', '>', '<'];
15
11
 
16
12
  const filterQueryArray = decodeURIComponent(filterStr?.replace(/%/g, '%25').replace(/%/g, '\\%')?.replace(/(^,)|(,$)/g, '')).replace(/'/g, '').split(/[;|]/);
17
13
 
18
14
  const resultList = [];
15
+ const searchwith = searchColumns || fields?.filter?.((el) => pg.pgType?.[el.dataTypeID] === 'text')?.map?.((el) => el.name)?.join?.(',');
16
+
17
+ const sval = `ilike '%${decodeURIComponent(search?.replace(/%/g, '%25')).replace(/'/g, "''").replace(/%/g, '\\%')}%'`;
18
+ const searchQuery = search && searchwith ? ` (${searchwith.split(',')?.map((name) => `${name} ${sval}`).join(' or ')} )` : '';
19
19
 
20
20
  for (let i = 0; i < filterQueryArray.length; i += 1) {
21
21
  const item = filterQueryArray[i];
@@ -61,7 +61,8 @@ function getFilterQuery({ pg, filter: filterStr, fields, filterList }) {
61
61
  });
62
62
  }
63
63
 
64
- return resultList;
64
+ const where = [searchQuery].concat(resultList?.map?.(el => el.query) || []).filter(el => el).join(' and ');
65
+
66
+ return where;
65
67
  }
66
68
 
67
- export default getFilterQuery;