@opengis/admin 0.2.122 → 0.2.123
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/{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;
         |