@opengis/admin 0.2.122 → 0.2.123
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/{add-page-D9BweG1f.js → add-page-CNaov3n_.js} +1 -1
- package/dist/{admin-interface-Bq8kf59d.js → admin-interface-Bfl5z6ck.js} +582 -732
- package/dist/{admin-view-pmWjnncn.js → admin-view-DYePX_Un.js} +1 -1
- package/dist/admin.js +2 -2
- package/dist/admin.umd.cjs +50 -50
- package/dist/{card-view-DNKItKZ_.js → card-view-OkM8SWMi.js} +1 -1
- package/dist/{edit-page-DmanLFQC.js → edit-page-BXf-hnHj.js} +1 -1
- package/dist/{import-file-B3hz_TTe.js → import-file-Cds3w-U5.js} +15024 -14822
- package/dist/{profile-page-CnXrMOV_.js → profile-page-B7ofAYKr.js} +1 -1
- package/dist/style.css +1 -1
- package/module/settings/menu.json +21 -13
- package/package.json +3 -3
- package/server/plugins/hook.js +13 -1
- package/server/routes/menu/controllers/getMenu.js +9 -3
- package/server/routes/print/controllers/printTemplate.add.js +37 -0
- package/server/routes/print/controllers/printTemplate.delete.js +29 -0
- package/server/routes/print/controllers/printTemplate.edit.js +42 -0
- package/server/routes/print/controllers/printTemplate.js +24 -79
- package/server/routes/print/controllers/printTemplateList.js +20 -0
- package/server/routes/print/controllers/printTemplatePreview.js +81 -0
- package/server/routes/print/index.mjs +14 -2
- package/server/routes/properties/controllers/admin.properties.post.js +2 -2
- package/server/routes/properties/index.mjs +1 -1
- package/server/routes/report/controllers/data.js +76 -0
- package/server/routes/report/controllers/list.js +18 -0
- package/server/routes/report/index.mjs +7 -0
- package/server/routes/report/utils/formatValue.js +179 -0
- package/server/routes/report/utils/getFilterQuery.js +67 -0
@@ -0,0 +1,179 @@
|
|
1
|
+
const dateTypeList = ['date', 'timestamp', 'timestamp without time zone', 'timestamp with time zone'];
|
2
|
+
const numberTypeList = ['float8', 'int4', 'int8', 'numeric', 'double precision', 'integer'];
|
3
|
+
const isValidDate = (dateStr) => {
|
4
|
+
const [dd, mm, yyyy] = dateStr.split('.');
|
5
|
+
return new Date(mm + '/' + dd + '/' + yyyy).toString() !== 'Invalid Date';
|
6
|
+
};
|
7
|
+
|
8
|
+
function dt(y, m, d) {
|
9
|
+
return new Date(Date.UTC(y, m, d)).toISOString().slice(0, 10);
|
10
|
+
}
|
11
|
+
const dp = {
|
12
|
+
d: new Date().getDate(),
|
13
|
+
w: new Date().getDate() - (new Date().getDay() || 7) + 1,
|
14
|
+
m: new Date().getMonth(),
|
15
|
+
q: (new Date().getMonth() / 4).toFixed() * 3,
|
16
|
+
y: new Date().getFullYear(),
|
17
|
+
};
|
18
|
+
|
19
|
+
function formatDateISOString(date) {
|
20
|
+
if (!date?.includes('.')) return date;
|
21
|
+
const [day, month, year] = date.split('.');
|
22
|
+
return `${year}-${month}-${day}`;
|
23
|
+
}
|
24
|
+
|
25
|
+
function formatValue({
|
26
|
+
pg, filter = {}, name, value, operator = '=', dataTypeID, uid = 1, optimize,
|
27
|
+
}) {
|
28
|
+
const { data, sql, extra } = filter;
|
29
|
+
const pk = false;
|
30
|
+
|
31
|
+
if (!dataTypeID && !extra) return {};
|
32
|
+
const fieldType = extra ? pg.pgType?.[{ Date: 1114 }[filter?.type] || 25] : pg.pgType?.[dataTypeID];
|
33
|
+
if (!name || !value || !fieldType) return {};
|
34
|
+
const filterType = filter.type?.toLowerCase();
|
35
|
+
|
36
|
+
// current day, week, month, year etc.
|
37
|
+
if (dateTypeList.includes(fieldType) && !value?.includes('_') && ['cd', 'cw', 'cm', 'cq', 'cy'].includes(value)) {
|
38
|
+
const query = {
|
39
|
+
cd: `${name}::date = '${dt(dp.y, dp.m, dp.d)}'::date`,
|
40
|
+
cw: `${name}::date >= '${dt(dp.y, dp.m, dp.w)}'::date and ${name} <= '${dt(dp.y, dp.m, dp.w + 6)}'::date`,
|
41
|
+
cm: `${name}::date >= '${dt(dp.y, dp.m, 1)}'::date and ${name} <= '${dt(dp.y, dp.m + 1, 0)}'::date`,
|
42
|
+
cq: `${name}::date >= '${dt(dp.y, dp.q, 1)}'::date and ${name} <= '${dt(dp.y, dp.q + 3, 0)}'::date`,
|
43
|
+
cy: `${name}::date >= '${dt(dp.y, 0, 1)}'::date and ${name}::date <= '${dt(dp.y, 11, 31)}'::date`,
|
44
|
+
}[value];
|
45
|
+
return { op: '=', query, extra };
|
46
|
+
}
|
47
|
+
|
48
|
+
// date range
|
49
|
+
if (dateTypeList.includes(fieldType) && value?.includes('_')) {
|
50
|
+
const [min, max] = value.split('_');
|
51
|
+
const query = `${name} >= '${min}'::date and ${name} <= '${max}'::date`;
|
52
|
+
return { op: 'between', query, extra };
|
53
|
+
}
|
54
|
+
|
55
|
+
// v3 filter date range, example - "01.01.2024-31.12.2024"
|
56
|
+
if (dateTypeList.includes(fieldType) && value?.includes('.') && value?.indexOf('-') === 10 && value?.length === 21) {
|
57
|
+
const [startDate, endDate] = value.split('-');
|
58
|
+
const min = formatDateISOString(startDate);
|
59
|
+
const max = formatDateISOString(endDate);
|
60
|
+
|
61
|
+
if (!isValidDate(startDate) || !isValidDate(endDate)) {
|
62
|
+
return { op: 'between', query: 'false', extra };
|
63
|
+
}
|
64
|
+
const query = extra && pk
|
65
|
+
? `${pk} in (select object_id from crm.extra_data where property_key='${name}' and value_date::date >= '${min}'::date and value_date::date <= '${max}'::date)`
|
66
|
+
: `${name}::date >= '${min}'::date and ${name}::date <= '${max}'::date`;
|
67
|
+
return { op: 'between', query, extra };
|
68
|
+
}
|
69
|
+
|
70
|
+
// my rows
|
71
|
+
if (value === 'me' && uid && fieldType === 'text') {
|
72
|
+
return { op: '=', query: extra ? `uid = '${uid}'` : `${name}::text = '${uid}'`, extra };
|
73
|
+
}
|
74
|
+
|
75
|
+
const formatType = {
|
76
|
+
float8: 'numeric',
|
77
|
+
int4: 'numeric',
|
78
|
+
int8: 'numeric',
|
79
|
+
varchar: 'text',
|
80
|
+
bool: 'boolean',
|
81
|
+
geometry: 'geom',
|
82
|
+
}[fieldType] || 'text';
|
83
|
+
|
84
|
+
if (optimize && optimize.name !== optimize.pk) {
|
85
|
+
const val = filterType === 'text' ? `ilike '%${value}%'` : `= any('{${value}}')`;
|
86
|
+
return {
|
87
|
+
op: '~',
|
88
|
+
query: fieldType?.includes('[]')
|
89
|
+
? `${optimize.pk} && (select array_agg(${optimize.pk}) from ${optimize.table} where ${name} ${val} )`
|
90
|
+
: `${optimize.pk} in (select ${optimize.pk} from ${optimize.table} where ${name} ${val} )`,
|
91
|
+
extra,
|
92
|
+
};
|
93
|
+
}
|
94
|
+
|
95
|
+
if (fieldType?.includes('[]')) {
|
96
|
+
return { op: 'in', query: `'{${value}}'::text[] && ${name}::text[]`, extra };
|
97
|
+
}
|
98
|
+
|
99
|
+
// multiple items of 1 param
|
100
|
+
if (value?.indexOf(',') !== -1) {
|
101
|
+
const values = value.split(',').filter((el) => el !== 'null');
|
102
|
+
if (extra && pk) {
|
103
|
+
const query = value?.indexOf('null') !== -1
|
104
|
+
? `${pk} in (select object_id from crm.extra_data where property_key='${name}' and ( value_text is null or value_text in (${values?.map((el) => `'"${el}"'`).join(',')}) ) )`
|
105
|
+
: `${pk} in (select object_id from crm.extra_data where property_key='${name}' and value_text in (${values?.map((el) => `'"${el}"'`).join(',')}) )`;
|
106
|
+
return { op: 'in', query, extra };
|
107
|
+
}
|
108
|
+
const query = value?.indexOf('null') !== -1
|
109
|
+
? `( ${name} is null or ${name}::text in (${values?.map((el) => `'${el}'`).join(',')}) )`
|
110
|
+
: `${name}::text in (${value.split(',')?.map((el) => `'${el}'`).join(',')})`;
|
111
|
+
return { op: 'in', query, extra };
|
112
|
+
}
|
113
|
+
|
114
|
+
// v3 filter number range, example - "100_500"
|
115
|
+
if (numberTypeList.includes(fieldType) && value?.indexOf('_') !== -1) {
|
116
|
+
const [min, max] = value.split('_');
|
117
|
+
const query = (max === 'max' ? `${name} > ${min}` : null) || (min === 'min' ? `${name} <= ${max}` : null) || `${name} between ${min} and ${max}`;
|
118
|
+
return { op: 'between', query, extra };
|
119
|
+
}
|
120
|
+
|
121
|
+
// number range
|
122
|
+
if (numberTypeList.includes(fieldType) && value?.indexOf('-') !== -1) {
|
123
|
+
const [min, max] = value.split('-');
|
124
|
+
if (min === 'min' && max === 'max') return {};
|
125
|
+
const query = (max === 'max' ? `${name} > ${min}` : null) || (min === 'min' ? `${name} < ${max}` : null) || `${name} between ${min} and ${max}`;
|
126
|
+
return { op: 'between', query, extra };
|
127
|
+
}
|
128
|
+
|
129
|
+
if (['<', '>'].includes(operator)) {
|
130
|
+
const query = `${name} ${operator} '${value}'::${formatType}`;
|
131
|
+
return { op: operator, query, extra };
|
132
|
+
}
|
133
|
+
|
134
|
+
if (operator === '=' && filterType !== 'text' && !filter?.data) {
|
135
|
+
const query = {
|
136
|
+
null: `${name} is null`,
|
137
|
+
notnull: `${name} is not null`,
|
138
|
+
}[value] || `${name}::${formatType}='${value}'::${formatType}`;
|
139
|
+
return { op: '=', query, extra };
|
140
|
+
}
|
141
|
+
|
142
|
+
if (['~', '='].includes(operator)) {
|
143
|
+
const operator1 = (filterType === 'text' && (filter?.id || filter?.name) && operator === '=' ? '~' : operator);
|
144
|
+
const matchNull = { null: 'is null', notnull: 'is not null' }[value];
|
145
|
+
const match = matchNull || ((operator1 === '=' || filterType === 'autocomplete') ? `='${value}'` : `ilike '%${value}%'`);
|
146
|
+
if (extra && pk) {
|
147
|
+
const query = data && sql
|
148
|
+
? `${pk} in (select object_id from crm.extra_data where property_key='${name}' and value_text in ( ( with q(id,name) as (${sql}) select id from q where ${filterType === 'autocomplete' ? 'id' : 'name'} ${match})))`
|
149
|
+
: `${pk} in (select object_id from crm.extra_data where property_key='${name}' and value_text ${match})`;
|
150
|
+
return { op: 'ilike', query, extra };
|
151
|
+
}
|
152
|
+
|
153
|
+
const query = filter?.data && filter?.sql
|
154
|
+
? `${filter?.name || filter?.id} in ( ( with q(id,name) as (${filter?.sql}) select id from q where ${filterType === 'autocomplete' ? 'id' : 'name'}::text ${match}) )` // filter with cls
|
155
|
+
: `${name}::text ${match}`; // simple filter
|
156
|
+
// console.log(query);
|
157
|
+
return { op: 'ilike', query };
|
158
|
+
}
|
159
|
+
|
160
|
+
// json
|
161
|
+
if (name.includes('.')) {
|
162
|
+
const [col, prop] = name.split('.');
|
163
|
+
const query = ` ${col}->>'${prop}' in ('${value.join("','")}')`;
|
164
|
+
return { op: 'in', query, extra };
|
165
|
+
}
|
166
|
+
|
167
|
+
// geometry
|
168
|
+
if (['geometry'].includes(fieldType)) {
|
169
|
+
const bbox = value[0].split('_');
|
170
|
+
|
171
|
+
if (bbox?.length === 4) {
|
172
|
+
const query = ` ${name} && 'box(${bbox[0]} ${bbox[1]},${bbox[2]} ${bbox[3]})'::box2d `;
|
173
|
+
return { op: '&&', query, extra };
|
174
|
+
}
|
175
|
+
}
|
176
|
+
return {};
|
177
|
+
}
|
178
|
+
|
179
|
+
export default formatValue;
|
@@ -0,0 +1,67 @@
|
|
1
|
+
/* eslint-disable no-continue */
|
2
|
+
|
3
|
+
/**
|
4
|
+
* @param {Number} opt.json - (1|0) 1 - Результат - Object, 0 - String
|
5
|
+
* @param {String} opt.query - запит до таблиці
|
6
|
+
* @param {String} opt.hash - інформація з хешу по запиту
|
7
|
+
*/
|
8
|
+
|
9
|
+
import formatValue from './formatValue.js';
|
10
|
+
|
11
|
+
function getFilterQuery({ pg, filter: filterStr, fields, filterList }) {
|
12
|
+
if (!filterStr) return null; // filter list API
|
13
|
+
|
14
|
+
const mainOperators = ['=', '~', '>', '<'];
|
15
|
+
|
16
|
+
const filterQueryArray = decodeURIComponent(filterStr?.replace(/%/g, '%25').replace(/%/g, '\\%')?.replace(/(^,)|(,$)/g, '')).replace(/'/g, '').split(/[;|]/);
|
17
|
+
|
18
|
+
const resultList = [];
|
19
|
+
|
20
|
+
for (let i = 0; i < filterQueryArray.length; i += 1) {
|
21
|
+
const item = filterQueryArray[i];
|
22
|
+
const operator = mainOperators?.find((el) => item.indexOf(el) !== -1) || '=';
|
23
|
+
const [name] = item.split(operator);
|
24
|
+
|
25
|
+
// skip already added filter
|
26
|
+
if (resultList.find((el) => el.name === name)) {
|
27
|
+
continue;
|
28
|
+
}
|
29
|
+
|
30
|
+
// filter
|
31
|
+
const filter = filterList?.find((el) => [el.id, el.name].includes(name)) || { type: 'text' };
|
32
|
+
|
33
|
+
// find all value
|
34
|
+
const value = filterQueryArray.filter((el) => el.startsWith(name)).map((el) => el.substring(name.length + 1)).join(',');
|
35
|
+
|
36
|
+
if (filter?.query) {
|
37
|
+
resultList.push({
|
38
|
+
name, value, query: filter?.query, operator: '=', filterType: filter.type, type: 'text',
|
39
|
+
});
|
40
|
+
continue;
|
41
|
+
}
|
42
|
+
|
43
|
+
// find field and skip not exists
|
44
|
+
const { dataTypeID } = fields?.find((el) => el.name === name) || {};
|
45
|
+
|
46
|
+
// format query
|
47
|
+
const {
|
48
|
+
op, query, filterType, fieldType,
|
49
|
+
} = formatValue({
|
50
|
+
pg,
|
51
|
+
filter,
|
52
|
+
name,
|
53
|
+
value,
|
54
|
+
operator,
|
55
|
+
dataTypeID,
|
56
|
+
}) || {};
|
57
|
+
if (!query) continue;
|
58
|
+
|
59
|
+
resultList.push({
|
60
|
+
name, value, query, operator: op, filterType, type: fieldType,
|
61
|
+
});
|
62
|
+
}
|
63
|
+
|
64
|
+
return resultList;
|
65
|
+
}
|
66
|
+
|
67
|
+
export default getFilterQuery;
|