@opengis/fastify-table 1.0.19 → 1.0.21

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/Changelog.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # fastify-table
2
2
 
3
+ ## 1.0.21 - 03.05.2024
4
+
5
+ - fix widget db structure
6
+
7
+ ## 1.0.20 - 03.05.2024
8
+
9
+ - fix filter separator
10
+
3
11
  ## 1.0.19 - 02.05.2024
4
12
 
5
13
  - widget plugin
@@ -0,0 +1,12 @@
1
+ import { existsSync } from 'fs';
2
+ import { readFile, writeFile } from 'fs/promises';
3
+
4
+ export default async function deleteItem({ params = {} }) {
5
+ const { id } = params;
6
+ if (!id) return { error: 'not enough params', status: 400 };
7
+ if (!existsSync('dblist.json')) return { data: [] };
8
+ const data = JSON.parse(await readFile('dblist.json') || '[]');
9
+
10
+ await writeFile('dblist.json', JSON.stringify(data.filter((el) => el.id !== id)));
11
+ return { data };
12
+ }
@@ -0,0 +1,17 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { existsSync } from 'fs';
3
+ import { readFile, writeFile } from 'fs/promises';
4
+
5
+ import checkItem from './utils/checkItem.js';
6
+
7
+ export default async function insertItem({ body = {} }) {
8
+ const check = checkItem(body.data);
9
+ if (check?.error) return check;
10
+
11
+ Object.assign(body.data, { id: randomUUID() });
12
+ const data = existsSync('dblist.json') ? JSON.parse(await readFile('dblist.json') || '[]') : [];
13
+ data.push(body.data);
14
+
15
+ await writeFile('dblist.json', JSON.stringify(data));
16
+ return { data };
17
+ }
@@ -0,0 +1,7 @@
1
+ import { existsSync } from 'fs';
2
+ import { readFile } from 'fs/promises';
3
+
4
+ export default async function readItemList() {
5
+ const data = existsSync('dblist.json') ? JSON.parse(await readFile('dblist.json') || '[]') : [];
6
+ return { data };
7
+ }
@@ -0,0 +1,22 @@
1
+ import { existsSync } from 'fs';
2
+ import { readFile, writeFile } from 'fs/promises';
3
+
4
+ import checkItem from './utils/checkItem.js';
5
+
6
+ export default async function updateItem({ body = {}, params = {} }) {
7
+ const { id } = params;
8
+ if (!id) return { error: 'not enough params', status: 400 };
9
+
10
+ if (!existsSync('dblist.json')) {
11
+ return { error: 'nothing to update: 1', status: 400 };
12
+ }
13
+
14
+ const check = checkItem(body.data);
15
+ if (check?.error) return check;
16
+
17
+ const data = JSON.parse(await readFile('dblist.json') || '[]');
18
+ data.filter((el) => el.id === id)?.forEach((el) => Object.assign(el, body.data));
19
+
20
+ await writeFile('dblist.json', JSON.stringify(data));
21
+ return { data };
22
+ }
@@ -0,0 +1,9 @@
1
+ export default function validateItem(item) {
2
+ if (!item || typeof item !== 'object' || Array.isArray(item)) {
3
+ return { error: 'param data is invalid: 1', status: 400 };
4
+ }
5
+ if (!item.options?.database || Object.keys(item).filter((key) => !['key', 'name', 'options'].includes(key) || (typeof item[key] !== 'string' && key !== 'options')).length) {
6
+ return { error: 'param data is invalid: 2', status: 400 };
7
+ }
8
+ return null;
9
+ }
@@ -0,0 +1,40 @@
1
+ import createItem from './controllers/insertItem.js';
2
+ import readItemList from './controllers/readItems.js';
3
+ import updateItem from './controllers/updateItem.js';
4
+ import deleteItem from './controllers/deleteItem.js';
5
+
6
+ export default async function plugin(fastify, config = {}) {
7
+ const prefix = config.prefix || '/api';
8
+ fastify.route({
9
+ method: 'POST',
10
+ url: `${prefix}/list`,
11
+ config: {
12
+ policy: [],
13
+ },
14
+ handler: createItem,
15
+ });
16
+ fastify.route({
17
+ method: 'GET',
18
+ url: `${prefix}/list`,
19
+ config: {
20
+ policy: [],
21
+ },
22
+ handler: readItemList,
23
+ });
24
+ fastify.route({
25
+ method: 'PUT',
26
+ url: `${prefix}/list/:id`,
27
+ config: {
28
+ policy: [],
29
+ },
30
+ handler: updateItem,
31
+ });
32
+ fastify.route({
33
+ method: 'DELETE',
34
+ url: `${prefix}/list/:id`,
35
+ config: {
36
+ policy: [],
37
+ },
38
+ handler: deleteItem,
39
+ });
40
+ }
package/index.js CHANGED
@@ -10,6 +10,7 @@ import notificationPlugin from './notification/index.js';
10
10
  import widgetPlugin from './widget/index.js';
11
11
  import crudPlugin from './crud/index.js';
12
12
  import policyPlugin from './policy/index.js';
13
+ import dbListPlugin from './dblist/index.js';
13
14
 
14
15
  async function plugin(fastify, opt) {
15
16
  // console.log(opt);
@@ -31,6 +32,7 @@ async function plugin(fastify, opt) {
31
32
  crudPlugin(fastify, opt);
32
33
  notificationPlugin(fastify, opt);
33
34
  widgetPlugin(fastify, opt);
35
+ dbListPlugin(fastify, opt);
34
36
  }
35
37
  export default fp(plugin);
36
38
  // export { rclient };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/fastify-table",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "type": "module",
5
5
  "description": "core-plugins",
6
6
  "main": "index.js",
@@ -24,10 +24,12 @@ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS file_id text NOT NULL DEFAULT admi
24
24
  ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS upload_name text;
25
25
  ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS object_id text;
26
26
  ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS file_type text;
27
+ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS file_status numeric;
27
28
  ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS doc_type text;
28
29
  ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS title text;
29
30
  ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS size numeric;
30
31
  ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS ext text;
32
+ ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS tags text[];
31
33
  ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS file_path text;
32
34
  ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS ismain boolean default false;
33
35
  ALTER TABLE crm.file ADD COLUMN IF NOT EXISTS isverified boolean default false;
@@ -3,6 +3,8 @@ ALTER TABLE log.table_change DROP CONSTRAINT IF EXISTS log_table_change_pkey;
3
3
  ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS table_change_id text NOT NULL DEFAULT admin.next_id();
4
4
 
5
5
  ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS table_name text;
6
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS object_id text;
7
+ ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS change_type text;
6
8
  ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS change_key text;
7
9
  ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS change_date date;
8
10
  ALTER TABLE log.table_change ADD COLUMN IF NOT EXISTS json_old json;
@@ -24,7 +24,7 @@ export default async function data(req) {
24
24
 
25
25
  const fData = query.filter ? await getFilterSQL({
26
26
  filter: query.filter,
27
- table,
27
+ table: params.table,
28
28
  json: 1,
29
29
  }) : {};
30
30
 
@@ -1,41 +1,41 @@
1
- import getTemplate from './utils/getTemplate.js';
2
- import getMeta from '../../pg/funcs/getMeta.js';
3
- import metaFormat from '../funcs/metaFormat/index.js';
4
-
5
- const maxLimit = 100;
6
-
7
- export default async function data({
8
- pg, query = {},
9
- }) {
10
- const time = Date.now();
11
-
12
- const loadTable = await getTemplate('table', query.table);
13
-
14
- if (!loadTable) { return { message: 'not found', status: 404 }; }
15
-
16
- const { table, columns, meta } = loadTable;
17
- const { pk } = await getMeta(table);
18
-
19
- const cols = columns.map((el) => el.name || el).join(',');
20
- const [orderColumn, orderDir] = (query.order || loadTable.order || '').split('-');
21
- const order = cols.includes(orderColumn) && orderColumn?.length ? `order by ${orderColumn} ${query.desc || orderDir === 'desc' ? 'desc' : ''}` : '';
22
-
23
- const limit = Math.min(maxLimit, +(query.limit || 10));
24
- const offset = query.page && query.page > 0 ? ` offset ${(query.page - 1) * limit}` : '';
25
-
26
- const search = meta?.search && query.key ? `(${meta?.search.concat(meta?.title ? `,${meta?.title}` : '').split(',').map(el => `${el} ilike '%${query.key}%'`).join(' or ')})` : null;
27
-
28
- const where = [loadTable.query, search].filter((el) => el);
29
- const q = `select ${pk ? `"${pk}" as id,` : ''} * from ${table} t where ${where.join(' and ') || 'true'} ${order} ${offset} limit ${limit}`;
30
-
31
- if (query.sql === '1') return q;
32
-
33
- const { rows } = await pg.query(q);
34
-
35
- const total = await pg.queryCache(`select count(*) from ${table} t where ${where.join(' and ') || 'true'}`).then((el) => el?.rows[0]?.count);
36
-
37
- await metaFormat({ rows, table: query.table });
38
- return {
39
- time: Date.now() - time, total, count: rows.length, rows,
40
- };
41
- }
1
+ import getTemplate from './utils/getTemplate.js';
2
+ import getMeta from '../../pg/funcs/getMeta.js';
3
+ import metaFormat from '../funcs/metaFormat/index.js';
4
+
5
+ const maxLimit = 100;
6
+
7
+ export default async function data({
8
+ pg, query = {},
9
+ }) {
10
+ const time = Date.now();
11
+
12
+ const loadTable = await getTemplate('table', query.table);
13
+
14
+ if (!loadTable) { return { message: 'not found', status: 404 }; }
15
+
16
+ const { table, columns, meta } = loadTable;
17
+ const { pk } = await getMeta(table);
18
+
19
+ const cols = columns.map((el) => el.name || el).join(',');
20
+ const [orderColumn, orderDir] = (query.order || loadTable.order || '').split('-');
21
+ const order = cols.includes(orderColumn) && orderColumn?.length ? `order by ${orderColumn} ${query.desc || orderDir === 'desc' ? 'desc' : ''}` : '';
22
+
23
+ const limit = Math.min(maxLimit, +(query.limit || 10));
24
+ const offset = query.page && query.page > 0 ? ` offset ${(query.page - 1) * limit}` : '';
25
+
26
+ const search = meta?.search && query.key ? `(${meta?.search.concat(meta?.title ? `,${meta?.title}` : '').split(',').map(el => `${el} ilike '%${query.key}%'`).join(' or ')})` : null;
27
+
28
+ const where = [loadTable.query, search].filter((el) => el);
29
+ const q = `select ${pk ? `"${pk}" as id,` : ''} * from ${table} t where ${where.join(' and ') || 'true'} ${order} ${offset} limit ${limit}`;
30
+
31
+ if (query.sql === '1') return q;
32
+
33
+ const { rows } = await pg.query(q);
34
+
35
+ const total = await pg.queryCache(`select count(*) from ${table} t where ${where.join(' and ') || 'true'}`).then((el) => el?.rows[0]?.count);
36
+
37
+ await metaFormat({ rows, table: query.table });
38
+ return {
39
+ time: Date.now() - time, total, count: rows.length, rows,
40
+ };
41
+ }
@@ -42,7 +42,7 @@ async function getFilterSQL({
42
42
  filter,
43
43
  tableSQL,
44
44
  fields,
45
- filterList: body?.filter_list || filterList,
45
+ filterList: filterList || (body?.filter_list || []).concat(body.filterInline || []).concat(body.filterCustom || []).concat(body.filterState || []).concat(body.filterList || []),
46
46
  pg,
47
47
  config,
48
48
  });
@@ -19,7 +19,7 @@ function getQuery({
19
19
 
20
20
  const filterQueryArray = config.v3?.filter
21
21
  ? decodeURI(filterStr?.replace(/(^,)|(,$)/g, '')).replace(/'/g, '').split(/[;|]/)
22
- : decodeURI(filterStr?.replace(/(^,)|(,$)/g, '')?.replace(/,null/g, '')).replace(/'/g, '').split(/[;|,]/);
22
+ : decodeURI(filterStr?.replace(/(^,)|(,$)/g, '')?.replace(/,null/g, '')).replace(/'/g, '').split(/[;|]/);
23
23
 
24
24
  const resultList = [];
25
25
 
@@ -45,7 +45,7 @@ function getQuery({
45
45
  const type = pg.pgType?.[dataTypeID];
46
46
 
47
47
  // filter
48
- const filter = filterList?.find((el) => el.name === name) || { type: 'text' };
48
+ const filter = filterList?.find((el) => el.id === name) || { type: 'text' };
49
49
  const filterType = filter.type?.toLowerCase();
50
50
  // format query
51
51
 
@@ -0,0 +1,47 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert';
3
+
4
+ import build from '../../helper.js';
5
+ import config from '../config.js';
6
+
7
+ const prefix = config.prefix || '/api';
8
+
9
+ test('api dblist', async (t) => {
10
+ const app = await build(t);
11
+ await t.test('GET /list', async () => {
12
+ const res = await app.inject({
13
+ method: 'GET',
14
+ url: `${prefix}/list`,
15
+ });
16
+ const rep = JSON.parse(res?.body);
17
+ assert.ok(rep.data);
18
+ });
19
+ let id;
20
+ await t.test('POST /list', async () => {
21
+ const res = await app.inject({
22
+ method: 'POST',
23
+ url: `${prefix}/list`,
24
+ body: { data: { key: 'testDB', name: 'testTitle', options: { database: 'mbk_kr_prod' } } },
25
+ });
26
+ const rep = JSON.parse(res?.body);
27
+ id = rep.data?.find((el) => el.key === 'testDB')?.id;
28
+ assert.ok(id);
29
+ });
30
+ await t.test('PUT /list/:id', async () => {
31
+ const res = await app.inject({
32
+ method: 'PUT',
33
+ url: `${prefix}/list/${id}`,
34
+ body: { data: { key: 'testDB1', name: 'testTitle1', options: { host: '192.168.3.160', database: 'mbk_kr_prod', port: 5434 } } },
35
+ });
36
+ const rep = JSON.parse(res?.body);
37
+ assert.ok(rep.data);
38
+ });
39
+ await t.test('DELETE /list/:id', async () => {
40
+ const res = await app.inject({
41
+ method: 'DELETE',
42
+ url: `${prefix}/list/${id}`,
43
+ });
44
+ const rep = JSON.parse(res?.body);
45
+ assert.ok(rep.data);
46
+ });
47
+ });
@@ -1,16 +1,16 @@
1
1
  import { test } from 'node:test';
2
2
  import assert from 'node:assert';
3
3
 
4
- import build from '../../helper.js';
4
+ import build from '../helper.js';
5
5
  import config from '../config.js';
6
6
 
7
7
  const session = { passport: { user: { uid: config.testUser?.uid || '1' } } };
8
8
 
9
- import widgetGet from '../../widget/controllers/widget.get.js';
10
- import widgetSet from '../../widget/controllers/widget.set.js';
11
- import widgetDel from '../../widget/controllers/widget.del.js';
9
+ import widgetGet from '../widget/controllers/widget.get.js';
10
+ import widgetSet from '../widget/controllers/widget.set.js';
11
+ import widgetDel from '../widget/controllers/widget.del.js';
12
12
 
13
- import pgClients from '../../pg/pgClients.js';
13
+ import pgClients from '../pg/pgClients.js';
14
14
 
15
15
  test('api && funcs notification', async (t) => {
16
16
  const app = await build(t);
@@ -0,0 +1,76 @@
1
+ import { readdir } from 'fs/promises';
2
+ import { existsSync, readFileSync } from 'fs';
3
+
4
+ // import getTemplate from '../../../table/controllers/utils/getTemplate.js';
5
+ import getSelect from '../../../table/controllers/utils/getSelect.js';
6
+
7
+ const dbData = {};
8
+
9
+ // from config??
10
+ const allTemplates = { table: {} };
11
+
12
+ const historyQ = `select nspname||'.'||relname as table_name, json_agg(json_build_object('name',attname, 'title',coalesce(col_description(attrelid, attnum),attname))) as columns
13
+ from pg_attribute a
14
+ left join pg_catalog.pg_attrdef d ON (a.attrelid, a.attnum) = (d.adrelid, d.adnum)
15
+ JOIN pg_class AS i
16
+ ON i.oid = a.attrelid
17
+ JOIN pg_namespace AS NS ON i.relnamespace = NS.OID
18
+ where a.attnum > 0
19
+ and not a.attisdropped
20
+ group by nspname||'.'||relname`;
21
+
22
+ export default async function historyFormat(rows, table, pg) {
23
+ if (!rows?.[0]?.changes) return rows; // old structure
24
+ // on startup
25
+ if (!allTemplates.table.length) {
26
+ const templateDir = './server/templates/table';
27
+ const templates = existsSync(templateDir) ? await readdir(templateDir) : [];
28
+ templates.forEach((template) => {
29
+ const body = JSON.parse(readFileSync(`${templateDir}/${template}`) || '{}');
30
+ Object.assign(allTemplates.table, { [template]: body });
31
+ });
32
+ }
33
+
34
+ const progrid = Object.keys(allTemplates.table).find((key) => key.replace('.json', '') === table);
35
+ if (!progrid) return rows;
36
+ // const body = await getTemplate('table', progrid);
37
+ const body = allTemplates.table[progrid];
38
+ const tableName = body?.table || table;
39
+ if (!tableName) return rows;
40
+
41
+ // get DB column description
42
+ if (!dbData?.[body.table]?.length) {
43
+ const { rows: rows1 } = await pg.query(historyQ);
44
+ rows1.forEach((row) => {
45
+ dbData[row.table_name] = row.columns;
46
+ });
47
+ }
48
+
49
+ // rewrite!!!
50
+ await Promise.all(rows?.map(async (op) => {
51
+ op.changes?.map(async (el) => {
52
+ const col = body.colModel.filter((col1) => col1.name === el.attr)[0] || dbData[body?.table]?.find((col1) => col1.name === el.attr);
53
+ if (el.attr === 'geom') {
54
+ el.title = 'Геометрія';
55
+ }
56
+ el.title = col?.ua || col?.title || el.attr;
57
+ if (!col) return;
58
+ el.type = col.type;
59
+ el.format = col.format;
60
+ const select = col.data || col.option || col.select;
61
+
62
+ // getSelect not equals to node
63
+ if (select && false) {
64
+ el.select = select;
65
+ const cls = await getSelect(select, {
66
+ val: [el.old, el.new],
67
+ });
68
+
69
+ el.oldf = cls[0] || el.old;
70
+ el.newf = cls[1] || el.new;
71
+ }
72
+ });
73
+ }));
74
+
75
+ return rows;
76
+ }
@@ -29,8 +29,6 @@ export default async function widgetDel({
29
29
  const sql = {
30
30
  comment: 'delete from crm.comment where object_id=$1 and uid=$2 and comment_id=$3',
31
31
  checklist: 'delete from crm.checklist where object_id=$1 and uid=$2 and checklist_id=$3 ',
32
- link: 'delete from crm.link where object_id=$1 and uid=$2 and link_id=$3 ',
33
- time: 'delete from crm.elapsed_time where object_id=$1 and uid=$2 and elapsed_time_id=$3 ',
34
32
  };
35
33
  try {
36
34
  const { rows, rowCount } = await pg.query(sql[type], [objectid, user.uid, id]);
@@ -1,61 +1,6 @@
1
- import getTemplate from '../../table/controllers/utils/getTemplate.js';
2
- import getSelect from '../../table/controllers/utils/getSelect.js';
3
1
  import getToken from '../../crud/funcs/getToken.js';
4
2
  import getMeta from '../../pg/funcs/getMeta.js';
5
- // import setToken from '../../crud/funcs/setToken.js';
6
-
7
- const historyQ = `select nspname||'.'||relname as table_name, json_agg(json_build_object('name',attname, 'title',coalesce(col_description(attrelid, attnum),attname))) as columns
8
- from pg_attribute a
9
- left join pg_catalog.pg_attrdef d ON (a.attrelid, a.attnum) = (d.adrelid, d.adnum)
10
- JOIN pg_class AS i
11
- ON i.oid = a.attrelid
12
- JOIN pg_namespace AS NS ON i.relnamespace = NS.OID
13
- where a.attnum > 0
14
- and not a.attisdropped
15
- group by nspname||'.'||relname`;
16
-
17
- const dbData = {};
18
-
19
- async function historyFormat(rows, progrid, pg) {
20
- if (!progrid) return rows;
21
- const body = await getTemplate('table', progrid);
22
- const tableName = body?.model || body?.table || progrid;
23
-
24
- // get DB column description
25
- if (!dbData?.[tableName]?.length) {
26
- const { rows: rows1 } = await pg.query(historyQ);
27
- rows1.forEach((row) => {
28
- dbData[row.table_name] = row.columns;
29
- });
30
- }
31
-
32
- await Promise.all(rows?.map(async (op) => {
33
- op.changes?.map(async (el) => {
34
- const col = body.colModel.filter((col1) => col1.name === el.attr)[0] || dbData[tableName]?.find((col1) => col1.name === el.attr);
35
- if (el.attr === 'geom') {
36
- el.title = 'Геометрія';
37
- }
38
- el.title = col?.ua || col?.title || el.attr;
39
- if (!col) return;
40
- el.type = col.type;
41
- el.format = col.format;
42
- const select = col.data || col.option || col.select;
43
-
44
- // getSelect not equals to node
45
- if (select && false) {
46
- el.select = select;
47
- const cls = await getSelect(select, {
48
- val: [el.old, el.new],
49
- });
50
-
51
- el.oldf = cls[0] || el.old;
52
- el.newf = cls[1] || el.new;
53
- }
54
- });
55
- }));
56
-
57
- return rows;
58
- }
3
+ import historyFormat from './utils/historyFormat.js';
59
4
 
60
5
  /**
61
6
  * Дістає CRM для widget
@@ -73,36 +18,24 @@ export default async function widgetGet({
73
18
 
74
19
  const objectid = param ? JSON.parse(param)?.id : params.objectid;
75
20
 
76
- if (!['comment', 'history', 'file', 'checklist', 'link', 'time'].includes(params.type)) return { error: 'param type not valid', status: 400 };
21
+ if (!['comment', 'history', 'file', 'checklist'].includes(params.type)) return { error: 'param type not valid', status: 400 };
77
22
  if (!objectid) return { error: 'id required', status: 400 };
78
23
 
79
24
  const sql = {
80
25
  comment: `select body,c.cdate, comment_id,object_id,c.uid, coalesce(user_name,' ')||' '||coalesce(sur_name,'') as username,avatar
81
- from crm.comment c left join admin.users u on u.uid=c.uid where object_id=$1 order by cdate desc`,
26
+ from crm.comment c left join admin.users u on u.uid=c.uid where object_id=$1 order by cdate desc`,
82
27
 
83
- history1: `select _column attr, c.cdate,_old "old",_new "new", c.uid, coalesce(user_name,' ')||' '||coalesce(sur_name,'') as username,
84
- avatar,pk_id from log.table_row_log c left join admin.users u on u.uid=c.uid where pk_id=$1 and _type='UPDATE' order by cdate desc limit 100`,
85
-
86
- history: `SELECT operation_id, _type, c.uid, c.cdate, json_agg(json_build_object('attr',_column,'old', _old,'new', _new)) as changes, pk_id,
87
- (select coalesce(user_name,' ')||' '||coalesce(sur_name,'') as username from admin.users u where u.uid=c.uid) username from log.table_row_log c
88
-
89
- where pk_id=$1 and _type='UPDATE'
90
- group by operation_id,_type,c.uid,c.cdate,c.pk_id
91
- order by cdate desc limit 100`,
28
+ history: `SELECT object_id, table_name, change_key, change_date, json_old, json_new, date_old,
29
+ date_new, number_old, number_new, bool_old, bool_new, text_old,
30
+ text_new, uid, cdate FROM log.table_change where object_id=$1 order by cdate desc, change_key limit 100`,
92
31
 
93
32
  checklist: `SELECT checklist_id, title, is_done, done_date, c.uid, c.cdate, coalesce(user_name,' ')||' '||coalesce(sur_name,'') as username,
94
- avatar FROM crm.checklist c left join admin.users u on u.uid=c.uid where object_id=$1 order by cdate desc`,
95
-
96
- link: `SELECT link_id, link, title, meta FROM crm.link
97
- where object_id=$1 order by cdate desc`,
33
+ avatar FROM crm.checklist c left join admin.users u on u.uid=c.uid where object_id=$1 order by cdate desc`,
98
34
 
99
- time: `SELECT elapsed_time_id, time, description from crm.elapsed_time
100
- where object_id=$1 order by cdate desc `,
101
-
102
- file: `SELECT file_id, file_path, uploaded_name, ext, size, c.uid, c.cdate, file_type, c.main,
103
- coalesce(user_name,' ')||' '||coalesce(sur_name,'') as username, verif,
104
- avatar, c.author,publicate,doc_date,describe, cls_type
105
- FROM admin.doc_file c left join admin.users u on u.uid=c.uid where object_id=$1 and file_status<>3 order by cdate desc`,
35
+ file: `SELECT file_id, file_path, uploaded_name, ext, size, c.uid, c.cdate, file_type, c.ismain,
36
+ coalesce(user_name,' ')||' '||coalesce(sur_name,'') as username, isverified,
37
+ avatar, c.uid as author, file_status FROM crm.file c left join admin.users u on u.uid=c.uid
38
+ where object_id=$1 and file_status<>3 order by cdate desc`,
106
39
 
107
40
  };
108
41
  try {
@@ -112,26 +45,22 @@ export default async function widgetGet({
112
45
  time.push(Date.now());
113
46
 
114
47
  /* Object info */
115
- const { tableName } = await pg.one(`select _table as "tableName",pk_id from log.table_row_log c
116
- where pk_id = $1 /*and _type ='INSERT'*/ limit 1`, [objectid]);
48
+ const { tableName } = await pg.one('select table_name as "tableName" from log.table_change where object_id=$1 limit 1', [objectid]);
117
49
  const { pk } = await getMeta({ table: tableName });
118
- const q = `select coalesce(b.user_name,'')||coalesce(' '||b.sur_name,'') as author, a.cdate, a.editor_date
119
- from ${tableName} a left join admin.users b on a.uid=b.uid where a.${pk}=$1 limit 1`;
50
+
51
+ const q = `select coalesce(b.user_name,'')||coalesce(' '||b.sur_name,'') as author, a.cdate, a.editor_date from ${tableName} a left join admin.users b on a.uid=b.uid where a.${pk}=$1 limit 1`;
120
52
  const data = pk ? await pg.one(q, [objectid]) : {};
53
+
121
54
  if (query.debug && user?.user_type === 'admin') {
122
55
  return {
123
56
  sql, type: params.type, q, id: objectid, data,
124
57
  };
125
58
  }
126
59
 
127
- const progrid = null; /* tableName ? table || Object.keys(db.progrid)
128
- .filter((el) => db.progrid[el]?.model === tableName || db.progrid[el]?.includes?.(`"${tableName}"`))[0] : null; */
129
-
130
60
  time.push(Date.now());
131
61
  return {
132
- progrid,
133
62
  time: { data: time[1] - time[0], format: time[2] - time[1] },
134
- rows: params.type === 'history' ? await historyFormat(rows, progrid, pg) : rows,
63
+ rows: params.type === 'history' ? await historyFormat(rows, tableName, pg) : rows,
135
64
  user: { uid: user?.uid, name: user?.user_name },
136
65
  data: { author: data?.author, cdate: data?.cdate, edate: data?.editor_date },
137
66
  objectid: params.objectid,
@@ -3,14 +3,10 @@ import getMeta from '../../pg/funcs/getMeta.js';
3
3
 
4
4
  const tableList = {
5
5
  comment: 'crm.comment',
6
- link: 'crm.link',
7
- time: 'crm.elapsed_time',
8
6
  checklist: 'crm.checklist',
9
7
  };
10
8
  const pkList = {
11
9
  comment: 'comment_id',
12
- link: 'link_id',
13
- time: 'elapsed_time_id',
14
10
  checklist: 'checklist_id',
15
11
  };
16
12
 
@@ -19,7 +15,7 @@ export default async function widgetSet({
19
15
  }) {
20
16
  const { user = {} } = session.passport || {};
21
17
  const { type, id, objectid } = params;
22
- if (!['comment', 'checklist', 'link', 'time'].includes(type)) return { error: 'param type not valid', status: 400 };
18
+ if (!['comment', 'checklist'].includes(type)) return { error: 'param type not valid', status: 400 };
23
19
  if (!objectid) return { error: 'id required', status: 400 };
24
20
 
25
21
  const table = tableList[type];