@opengis/cms 0.0.62 → 0.0.63

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.
Files changed (124) hide show
  1. package/README.md +131 -131
  2. package/dist/{ArticlesPage-CFjE_cw_.js → ArticlesPage-BjYzvTWM.js} +3 -3
  3. package/dist/{CollectionsBreadcrumb-BCxeRikP.js → CollectionsBreadcrumb-HePNJb-d.js} +1 -1
  4. package/dist/CollectionsBreadcrumb.vue_vue_type_script_setup_true_lang-BJh-tjam.js +53 -0
  5. package/dist/{Dashboard-C1eGscNd.js → Dashboard-CXkg_pk8.js} +132 -132
  6. package/dist/{EditCollectionPage-C4uNmBJf.js → EditCollectionPage-BGZCMcQS.js} +3 -3
  7. package/dist/{MenuAddPage-D-p3gFgm.js → MenuAddPage-QTnwCoGh.js} +1 -1
  8. package/dist/{MenuBody-rN5j4YBu.js → MenuBody-Bi0ONVZf.js} +2 -2
  9. package/dist/{MenuItemPage-BoJw885D.js → MenuItemPage-B7Y9KFyb.js} +3 -3
  10. package/dist/{MenuList-DFEBS0NB.js → MenuList-BLIpeqSd.js} +53 -53
  11. package/dist/{MenuPage-BCZB_S8j.js → MenuPage-3W6jZ15H.js} +1 -1
  12. package/dist/{MenuWrapper-AZ_8s-zd.js → MenuWrapper-OrOv6sOb.js} +1 -1
  13. package/dist/{MonacoEditor-Db-3Jc3E.js → MonacoEditor-ByPT8pnv.js} +1 -1
  14. package/dist/MonacoEditor.vue_vue_type_script_setup_true_lang-C8cip9Ci.js +84 -0
  15. package/dist/{UniversalTable-CzqPG-tY.js → UniversalTable-GBd_pStq.js} +80 -80
  16. package/dist/{UniversalTablePagination-4gL47A7I.js → UniversalTablePagination-Dw2hc0nc.js} +46 -46
  17. package/dist/{contentForm-CcFbUeal.js → contentForm-NmskI6Ye.js} +2 -2
  18. package/dist/index.js +5 -5
  19. package/dist/{vs-builder-monaco-B3Jj0V31.js → vs-builder-monaco-Cw-f19gc.js} +1 -1
  20. package/dist/{vs-builder-preview-DL3RYMp7.js → vs-builder-preview-l5KhqlrF.js} +1 -1
  21. package/dist/{vs-form-reference-list-Dtv8fJJU.js → vs-form-reference-list-hZufPxfE.js} +696 -353
  22. package/input-types.json +9 -9
  23. package/locales/en.json +823 -815
  24. package/locales/uk.json +821 -813
  25. package/module/cms/cls/content.status.json +17 -17
  26. package/module/cms/cls/user_type.json +9 -9
  27. package/module/cms/form/admin.users.form.json +77 -77
  28. package/module/cms/select/cms.page_type.sql +1 -1
  29. package/module/cms/select/news_tag_id.sql +11 -11
  30. package/module/cms/table/admin.users.table.json +53 -53
  31. package/module/cms/table/collection.default.table.json +96 -96
  32. package/module/cms/table/single.default.table.json +116 -116
  33. package/package.json +69 -69
  34. package/plugin.js +43 -43
  35. package/server/app.js +35 -35
  36. package/server/config.js +4 -4
  37. package/server/functions/getContent.js +45 -45
  38. package/server/functions/getDraftKey.js +22 -22
  39. package/server/functions/getSearchData.js +31 -31
  40. package/server/functions/getTags.js +30 -30
  41. package/server/functions/getUser.js +27 -27
  42. package/server/functions/utils/mock.reply.js +55 -55
  43. package/server/index.js +22 -22
  44. package/server/migrations/fixes.sql +132 -132
  45. package/server/migrations/site.sql +596 -596
  46. package/server/plugins/adminHook.js +78 -78
  47. package/server/plugins/hook.js +59 -59
  48. package/server/plugins/vite.js +75 -75
  49. package/server/routes/category/controllers/cms.category.delete.js +21 -21
  50. package/server/routes/category/controllers/cms.category.get.js +17 -17
  51. package/server/routes/category/controllers/cms.category.list.js +16 -16
  52. package/server/routes/category/controllers/cms.category.post.js +21 -21
  53. package/server/routes/category/controllers/cms.category.put.js +23 -23
  54. package/server/routes/category/index.mjs +22 -22
  55. package/server/routes/cms/controllers/cmsStat.js +55 -55
  56. package/server/routes/cms/controllers/cmsSuggest.js +57 -57
  57. package/server/routes/cms/controllers/deleteContent.js +113 -113
  58. package/server/routes/cms/controllers/downloadMedia.js +84 -84
  59. package/server/routes/cms/controllers/getContent.js +113 -113
  60. package/server/routes/cms/controllers/getContentBySlug.js +93 -93
  61. package/server/routes/cms/controllers/getPermissions.js +15 -15
  62. package/server/routes/cms/controllers/insertContent.js +226 -226
  63. package/server/routes/cms/controllers/listMedia.js +155 -155
  64. package/server/routes/cms/controllers/properties.get.js +18 -18
  65. package/server/routes/cms/controllers/properties.post.js +99 -99
  66. package/server/routes/cms/controllers/searchContent.js +214 -214
  67. package/server/routes/cms/controllers/setPermissions.js +49 -49
  68. package/server/routes/cms/controllers/translate.js +89 -89
  69. package/server/routes/cms/controllers/updateContent.js +231 -231
  70. package/server/routes/cms/functions/getSettings.js +48 -48
  71. package/server/routes/cms/index.mjs +112 -112
  72. package/server/routes/cms/utils/additionalData.js +35 -35
  73. package/server/routes/cms/utils/getCollection.js +89 -89
  74. package/server/routes/cms/utils/getSingle.js +188 -188
  75. package/server/routes/cms/utils/inputTypes.js +5 -5
  76. package/server/routes/cms/utils/insertContentLocalization.js +104 -104
  77. package/server/routes/cms/utils/requestTranslation.js +135 -135
  78. package/server/routes/cms/utils/updateLocalization.js +42 -42
  79. package/server/routes/cmsSpace/controllers/deleteSpace.js +26 -26
  80. package/server/routes/cmsSpace/controllers/getSpaces.js +28 -28
  81. package/server/routes/cmsSpace/controllers/insertSpace.js +22 -22
  82. package/server/routes/cmsSpace/controllers/updateSpace.js +24 -24
  83. package/server/routes/cmsSpace/index.mjs +20 -20
  84. package/server/routes/contentType/controllers/addContentType.js +160 -160
  85. package/server/routes/contentType/controllers/contentTypeList.js +47 -47
  86. package/server/routes/contentType/controllers/delContentType.js +75 -75
  87. package/server/routes/contentType/controllers/editContentType.js +70 -70
  88. package/server/routes/contentType/controllers/getContentType.js +57 -57
  89. package/server/routes/contentType/index.mjs +35 -35
  90. package/server/routes/contentType/utils/updateContents.js +44 -44
  91. package/server/routes/contentType/utils/updateCustomContentTable.js +53 -53
  92. package/server/routes/feedback/controllers/email.list.js +24 -24
  93. package/server/routes/feedback/controllers/feedback.js +48 -48
  94. package/server/routes/feedback/controllers/feedback.list.js +37 -37
  95. package/server/routes/feedback/controllers/news.subscriptions.js +44 -44
  96. package/server/routes/feedback/index.mjs +71 -71
  97. package/server/routes/logs/controllers/export.user.logs.js +77 -77
  98. package/server/routes/logs/controllers/user.logs.js +44 -44
  99. package/server/routes/logs/index.mjs +9 -9
  100. package/server/routes/menu/controllers/addMenu.js +37 -37
  101. package/server/routes/menu/controllers/delMenu.js +31 -31
  102. package/server/routes/menu/controllers/editMenu.js +41 -41
  103. package/server/routes/menu/controllers/getMenu.js +24 -24
  104. package/server/routes/menu/functions/getMenu.js +50 -50
  105. package/server/routes/menu/index.mjs +13 -13
  106. package/server/routes/migration/controllers/collectionToCustom.js +137 -137
  107. package/server/routes/migration/index.mjs +8 -8
  108. package/server/routes/root.mjs +8 -8
  109. package/server/routes/tags/controllers/add.tags.js +24 -24
  110. package/server/routes/tags/controllers/del.tags.js +19 -19
  111. package/server/routes/tags/controllers/edit.tags.js +25 -25
  112. package/server/routes/tags/controllers/get.tags.js +15 -15
  113. package/server/routes/tags/index.mjs +14 -14
  114. package/server/templates/cls/cms.category_type.json +9 -9
  115. package/server/templates/cls/cms.content_review_status.json +9 -9
  116. package/server/templates/cls/cms.content_status.json +9 -9
  117. package/server/templates/cls/cms.content_type.json +9 -9
  118. package/server/templates/cls/cms.lang.json +9 -9
  119. package/server/templates/page/login.html +126 -126
  120. package/server/templates/select/core.user_mentioned.sql +1 -1
  121. package/utils.d.ts +52 -52
  122. package/utils.js +8 -8
  123. package/dist/CollectionsBreadcrumb.vue_vue_type_script_setup_true_lang-umRzB5mY.js +0 -53
  124. package/dist/MonacoEditor.vue_vue_type_script_setup_true_lang-B1DrxmQX.js +0 -84
@@ -1,189 +1,189 @@
1
- import path from 'node:path';
2
-
3
- import { pgClients, metaFormat, getFilterSQL, getFilter, getMeta } from '@opengis/fastify-table/utils.js';
4
-
5
- import inputTypes from '../utils/inputTypes.js';
6
- import additionalData from "./additionalData.js";
7
-
8
- export default async function getSingle({
9
- contentId: contentId1, contentTypeId, id: id1, limit: queryLimit, maxLimit, search, filter, locale, statusQuery, user, sql, page, defaultColumns = [], fields, defaultFields = [], defaultFilters = [],
10
- }, pg = pgClients.client) {
11
- const id = id1 || (contentId1 === 'pages' ? undefined : contentId1) || '';
12
- const contentId = id1 ? contentId1 : "pages";
13
-
14
- // new ? 1 : 2
15
- const customColumns = contentTypeId === (id || contentId)
16
- ? await pg.query(
17
- `SELECT columns FROM site.content_types WHERE content_type_id=$1`, [id || contentId]
18
- ).then(el => el.rows?.[0]?.columns || [])
19
- : await pg.query(`
20
- SELECT columns FROM site.content_types WHERE content_type_id in (select content_type_id from site.contents where content_id=$1) limit 1
21
- `, [id || contentId]).then(el => el.rows?.[0]?.columns || []);
22
-
23
- const contentQuery = contentId === 'pages' || !id
24
- ? `(type = 'single' or content_type_id = 'pages')`
25
- : 'content_type_id=(select content_type_id from site.contents where content_id=$2)';
26
-
27
- const columns = defaultColumns.concat(customColumns.filter(col => defaultColumns.findIndex(el => el.name === col.name) === -1));
28
-
29
- columns.filter(el => el.defaultColumn).forEach(col => {
30
- const { name, localization } = customColumns.find(item => item.name === col.name) || {};
31
- if (name) {
32
- Object.assign(col, { localization });
33
- }
34
- });
35
-
36
- const limit = Math.min(maxLimit, +(queryLimit || 20));
37
- const offset = page && page > 0 && !id ? (page - 1) * limit : 0;
38
-
39
- const fData = filter
40
- ? await getFilterSQL({
41
- pg,
42
- table: 'site.contents',
43
- filter,
44
- search,
45
- filterList: defaultFilters,
46
- query: `
47
- content_type_id IN (
48
- SELECT content_type_id
49
- FROM site.content_types
50
- WHERE ${contentQuery || 'true'}
51
- )
52
- `,
53
- })
54
- : {
55
- optimizedSQL: 'SELECT * FROM site.contents WHERE true',
56
- };
57
-
58
- const localeQuery = locale && locale !== 'uk' && pg.pk?.['site.contents'] ? `${pg.pk?.['site.contents']} in ( select object_id from site.localization where REVERSE( split_part( REVERSE(field_key), ':', 1) ) = '${locale.replace(/'/g, "''")}' )` : undefined;
59
-
60
- const columnList = await getMeta({
61
- pg,
62
- table: 'site.contents',
63
- }).then(el => el.columns?.map?.(col => col.name) || []);
64
- const existingFields = fields && contentId === 'pages' || !id ? defaultFields.concat((fields || '').split(',')).filter(colName => columnList.includes(colName)).concat(['content_id AS id']).join(',') : '';
65
- const extraKeys = fields ? fields.split(',').filter(key => !defaultFields.includes(key)) : [];
66
- const cols = existingFields.length ? existingFields.concat(extraKeys?.length ? `,"extraKeys"` : []) : `content_id AS id,
67
- content_id,
68
- created_by,
69
- title,
70
- slug,
71
- meta,
72
- published_by,
73
- published_at,
74
- status,
75
- content_type_id,
76
- /* content_type_id AS type, */
77
- main_image
78
- ${contentId === 'pages' || !id ? `,"extraKeys"` : ''}`;
79
-
80
- const q = `
81
- SELECT ${cols} FROM (${fData.optimizedSQL}) a
82
- ${extraKeys || id ? `LEFT JOIN LATERAL (
83
- SELECT json_agg(row_to_json(q)) AS "extraKeys"
84
- FROM (
85
- SELECT field_key, field_type, field_value, field_value_object
86
- FROM site.content_data
87
- WHERE content_id = a.content_id
88
- ) q
89
- ) b ON true` : ''}
90
-
91
- LEFT JOIN LATERAL (
92
- SELECT type FROM site.content_types WHERE content_type_id=a.content_type_id LIMIT 1
93
- )c ON true
94
-
95
- WHERE $1=$1 and $2=$2
96
- and ${statusQuery || 'true'}
97
- and ${localeQuery || '1=1'}
98
- and ${contentQuery || 'true'}
99
- and ${id ? `$2 in (slug, content_id)` : 'true'}
100
- and content_id<>'pages'
101
- order by case when status='archived' then true else false end, published_at desc nulls last
102
- LIMIT ${limit} OFFSET ${id ? 0 : offset}
103
- `;
104
-
105
- if (sql && user?.user_type?.includes?.('admin')) {
106
- return q; // Expose raw SQL for debugging
107
- }
108
-
109
- const { total = 0, filtered = 0 } = await pg.query(`
110
- SELECT COUNT(*)::int as total,
111
- count(*) FILTER(WHERE ${fData.q || "true"})::int as filtered
112
- FROM site.contents
113
- WHERE content_type_id IN (
114
- SELECT content_type_id
115
- FROM site.content_types
116
- WHERE ${localeQuery || '1=1'}
117
- and $1=$1 and $2=$2 and ${contentQuery || 'true'}
118
- )
119
- and ${statusQuery || 'true'}
120
- and content_id<>'pages'
121
- `, [contentId, id]).then(el => el.rows?.[0] || {});
122
-
123
- const { rows = [] } = await pg.query(q, [contentId, id || '']);
124
-
125
- const locales = await pg.query(`select array_agg(distinct REVERSE(split_part(REVERSE(field_key), ':', 1))) from site.localization
126
- where object_id in (select content_id from site.contents
127
- where content_type_id IN (
128
- SELECT content_type_id FROM site.content_types where $1=$1 and $2=$2 and ${contentQuery || 'true'}
129
- )
130
- and ${statusQuery || 'true'}
131
- )`, [contentId, id]
132
- ).then(el => el.rows?.[0]?.array_agg || []);
133
-
134
- // Flatten extra fields into main object
135
- const rows1 = rows.map(row => ({
136
- ...row,
137
- ...Object.fromEntries(
138
- row.extraKeys?.filter(k => extraKeys?.length ? extraKeys.includes(k.field_key) : true)?.map(k =>
139
- [k.field_key, inputTypes[k.field_type] === 'json' || k.field_key === 'meta'
140
- ? k.field_value_object
141
- : k.field_value]
142
- ) || []
143
- ),
144
- extraKeys: undefined,
145
- }));
146
-
147
- // Apply localization and tags etc.
148
- await additionalData(pg, rows1, locale, contentId === 'pages' || !id ? [existingFields, extraKeys].filter(Boolean).join(',') : null);
149
-
150
- // Apply metadata formatting
151
- await metaFormat({
152
- rows: rows1,
153
- cls: {
154
- created_by: 'core.user_mentioned',
155
- // content_type_id: 'cms.type_id',
156
- // type: 'cms.type_id',
157
- },
158
- sufix: false,
159
- }, pg);
160
-
161
- const { list: filters = [] } = await getFilter({
162
- pg, table: 'single.default.table', user, filter: `content_type_id in (select content_type_id from site.content_types where type='single' or content_type_id='pages')`
163
- }) || {};
164
-
165
- const finalColumns = !id
166
- ? columns?.map?.(col => Object.assign(col, { type: col.name === 'published_at' ? 'date' : col.type }))?.filter?.(el => !el.hidden)
167
- : columns?.filter?.(el => !el.hidden);
168
-
169
- rows1.filter(row => row.single_sections?.length).forEach(row => {
170
- row.single_sections.filter(section => section.documents?.length).forEach(section => {
171
- section.documents.filter(doc => doc.file).forEach(doc => Object.assign(doc, { file_name: path.basename(doc.file) }));
172
- });
173
- });
174
-
175
- // temporary solution, before front makes changes to call by id, not type
176
- rows1.forEach(row => Object.assign(row, { content_type_id: !row.content_type_id || row.content_type_id === 'pages' ? row.content_id : row.content_type_id }));
177
-
178
- return {
179
- locales,
180
- type: 'single',
181
- total,
182
- filtered,
183
- count: rows1.length,
184
- pk: 'id',
185
- rows: rows1,
186
- columns: finalColumns,
187
- filters,
188
- };
1
+ import path from 'node:path';
2
+
3
+ import { pgClients, metaFormat, getFilterSQL, getFilter, getMeta } from '@opengis/fastify-table/utils.js';
4
+
5
+ import inputTypes from '../utils/inputTypes.js';
6
+ import additionalData from "./additionalData.js";
7
+
8
+ export default async function getSingle({
9
+ contentId: contentId1, contentTypeId, id: id1, limit: queryLimit, maxLimit, search, filter, locale, statusQuery, user, sql, page, defaultColumns = [], fields, defaultFields = [], defaultFilters = [],
10
+ }, pg = pgClients.client) {
11
+ const id = id1 || (contentId1 === 'pages' ? undefined : contentId1) || '';
12
+ const contentId = id1 ? contentId1 : "pages";
13
+
14
+ // new ? 1 : 2
15
+ const customColumns = contentTypeId === (id || contentId)
16
+ ? await pg.query(
17
+ `SELECT columns FROM site.content_types WHERE content_type_id=$1`, [id || contentId]
18
+ ).then(el => el.rows?.[0]?.columns || [])
19
+ : await pg.query(`
20
+ SELECT columns FROM site.content_types WHERE content_type_id in (select content_type_id from site.contents where content_id=$1) limit 1
21
+ `, [id || contentId]).then(el => el.rows?.[0]?.columns || []);
22
+
23
+ const contentQuery = contentId === 'pages' || !id
24
+ ? `(type = 'single' or content_type_id = 'pages')`
25
+ : 'content_type_id=(select content_type_id from site.contents where content_id=$2)';
26
+
27
+ const columns = defaultColumns.concat(customColumns.filter(col => defaultColumns.findIndex(el => el.name === col.name) === -1));
28
+
29
+ columns.filter(el => el.defaultColumn).forEach(col => {
30
+ const { name, localization } = customColumns.find(item => item.name === col.name) || {};
31
+ if (name) {
32
+ Object.assign(col, { localization });
33
+ }
34
+ });
35
+
36
+ const limit = Math.min(maxLimit, +(queryLimit || 20));
37
+ const offset = page && page > 0 && !id ? (page - 1) * limit : 0;
38
+
39
+ const fData = filter
40
+ ? await getFilterSQL({
41
+ pg,
42
+ table: 'site.contents',
43
+ filter,
44
+ search,
45
+ filterList: defaultFilters,
46
+ query: `
47
+ content_type_id IN (
48
+ SELECT content_type_id
49
+ FROM site.content_types
50
+ WHERE ${contentQuery || 'true'}
51
+ )
52
+ `,
53
+ })
54
+ : {
55
+ optimizedSQL: 'SELECT * FROM site.contents WHERE true',
56
+ };
57
+
58
+ const localeQuery = locale && locale !== 'uk' && pg.pk?.['site.contents'] ? `${pg.pk?.['site.contents']} in ( select object_id from site.localization where REVERSE( split_part( REVERSE(field_key), ':', 1) ) = '${locale.replace(/'/g, "''")}' )` : undefined;
59
+
60
+ const columnList = await getMeta({
61
+ pg,
62
+ table: 'site.contents',
63
+ }).then(el => el.columns?.map?.(col => col.name) || []);
64
+ const existingFields = fields && contentId === 'pages' || !id ? defaultFields.concat((fields || '').split(',')).filter(colName => columnList.includes(colName)).concat(['content_id AS id']).join(',') : '';
65
+ const extraKeys = fields ? fields.split(',').filter(key => !defaultFields.includes(key)) : [];
66
+ const cols = existingFields.length ? existingFields.concat(extraKeys?.length ? `,"extraKeys"` : []) : `content_id AS id,
67
+ content_id,
68
+ created_by,
69
+ title,
70
+ slug,
71
+ meta,
72
+ published_by,
73
+ published_at,
74
+ status,
75
+ content_type_id,
76
+ /* content_type_id AS type, */
77
+ main_image
78
+ ${contentId === 'pages' || !id ? `,"extraKeys"` : ''}`;
79
+
80
+ const q = `
81
+ SELECT ${cols} FROM (${fData.optimizedSQL}) a
82
+ ${extraKeys || id ? `LEFT JOIN LATERAL (
83
+ SELECT json_agg(row_to_json(q)) AS "extraKeys"
84
+ FROM (
85
+ SELECT field_key, field_type, field_value, field_value_object
86
+ FROM site.content_data
87
+ WHERE content_id = a.content_id
88
+ ) q
89
+ ) b ON true` : ''}
90
+
91
+ LEFT JOIN LATERAL (
92
+ SELECT type FROM site.content_types WHERE content_type_id=a.content_type_id LIMIT 1
93
+ )c ON true
94
+
95
+ WHERE $1=$1 and $2=$2
96
+ and ${statusQuery || 'true'}
97
+ and ${localeQuery || '1=1'}
98
+ and ${contentQuery || 'true'}
99
+ and ${id ? `$2 in (slug, content_id)` : 'true'}
100
+ and content_id<>'pages'
101
+ order by case when status='archived' then true else false end, published_at desc nulls last
102
+ LIMIT ${limit} OFFSET ${id ? 0 : offset}
103
+ `;
104
+
105
+ if (sql && user?.user_type?.includes?.('admin')) {
106
+ return q; // Expose raw SQL for debugging
107
+ }
108
+
109
+ const { total = 0, filtered = 0 } = await pg.query(`
110
+ SELECT COUNT(*)::int as total,
111
+ count(*) FILTER(WHERE ${fData.q || "true"})::int as filtered
112
+ FROM site.contents
113
+ WHERE content_type_id IN (
114
+ SELECT content_type_id
115
+ FROM site.content_types
116
+ WHERE ${localeQuery || '1=1'}
117
+ and $1=$1 and $2=$2 and ${contentQuery || 'true'}
118
+ )
119
+ and ${statusQuery || 'true'}
120
+ and content_id<>'pages'
121
+ `, [contentId, id]).then(el => el.rows?.[0] || {});
122
+
123
+ const { rows = [] } = await pg.query(q, [contentId, id || '']);
124
+
125
+ const locales = await pg.query(`select array_agg(distinct REVERSE(split_part(REVERSE(field_key), ':', 1))) from site.localization
126
+ where object_id in (select content_id from site.contents
127
+ where content_type_id IN (
128
+ SELECT content_type_id FROM site.content_types where $1=$1 and $2=$2 and ${contentQuery || 'true'}
129
+ )
130
+ and ${statusQuery || 'true'}
131
+ )`, [contentId, id]
132
+ ).then(el => el.rows?.[0]?.array_agg || []);
133
+
134
+ // Flatten extra fields into main object
135
+ const rows1 = rows.map(row => ({
136
+ ...row,
137
+ ...Object.fromEntries(
138
+ row.extraKeys?.filter(k => extraKeys?.length ? extraKeys.includes(k.field_key) : true)?.map(k =>
139
+ [k.field_key, inputTypes[k.field_type] === 'json' || k.field_key === 'meta'
140
+ ? k.field_value_object
141
+ : k.field_value]
142
+ ) || []
143
+ ),
144
+ extraKeys: undefined,
145
+ }));
146
+
147
+ // Apply localization and tags etc.
148
+ await additionalData(pg, rows1, locale, contentId === 'pages' || !id ? [existingFields, extraKeys].filter(Boolean).join(',') : null);
149
+
150
+ // Apply metadata formatting
151
+ await metaFormat({
152
+ rows: rows1,
153
+ cls: {
154
+ created_by: 'core.user_mentioned',
155
+ // content_type_id: 'cms.type_id',
156
+ // type: 'cms.type_id',
157
+ },
158
+ sufix: false,
159
+ }, pg);
160
+
161
+ const { list: filters = [] } = await getFilter({
162
+ pg, table: 'single.default.table', user, filter: `content_type_id in (select content_type_id from site.content_types where type='single' or content_type_id='pages')`
163
+ }) || {};
164
+
165
+ const finalColumns = !id
166
+ ? columns?.map?.(col => Object.assign(col, { type: col.name === 'published_at' ? 'date' : col.type }))?.filter?.(el => !el.hidden)
167
+ : columns?.filter?.(el => !el.hidden);
168
+
169
+ rows1.filter(row => row.single_sections?.length).forEach(row => {
170
+ row.single_sections.filter(section => section.documents?.length).forEach(section => {
171
+ section.documents.filter(doc => doc.file).forEach(doc => Object.assign(doc, { file_name: path.basename(doc.file) }));
172
+ });
173
+ });
174
+
175
+ // temporary solution, before front makes changes to call by id, not type
176
+ rows1.forEach(row => Object.assign(row, { content_type_id: !row.content_type_id || row.content_type_id === 'pages' ? row.content_id : row.content_type_id }));
177
+
178
+ return {
179
+ locales,
180
+ type: 'single',
181
+ total,
182
+ filtered,
183
+ count: rows1.length,
184
+ pk: 'id',
185
+ rows: rows1,
186
+ columns: finalColumns,
187
+ filters,
188
+ };
189
189
  }
@@ -1,6 +1,6 @@
1
- import path from 'node:path';
2
- import { existsSync, readFileSync } from 'node:fs';
3
-
4
- const inputTypes = ['input-types.json', path.join('node_modules/@opengis/cms', 'input-types.json')].filter(filepath => existsSync(filepath)).reduce((acc, curr) => ({ ...acc, ...JSON.parse(readFileSync(curr) || '{}') }), {});
5
-
1
+ import path from 'node:path';
2
+ import { existsSync, readFileSync } from 'node:fs';
3
+
4
+ const inputTypes = ['input-types.json', path.join('node_modules/@opengis/cms', 'input-types.json')].filter(filepath => existsSync(filepath)).reduce((acc, curr) => ({ ...acc, ...JSON.parse(readFileSync(curr) || '{}') }), {});
5
+
6
6
  export default inputTypes
@@ -1,105 +1,105 @@
1
- import { dataInsert, pgClients } from "@opengis/fastify-table/utils.js";
2
-
3
- import requestTranslation from "./requestTranslation.js";
4
-
5
- export default async function insertContentLocalization({ send = () => { }, table, id, from, to, nocache, skip, schemaKeys, user }, pg = pgClients.client) {
6
- if (!to) {
7
- const resp = { error: 'not enough query params: to', code: 400 };
8
- send(resp.error + ': ' + id);
9
- return resp;
10
- }
11
-
12
- const row = await pg.query(`select * ${table ? '' : ',content_id as id'} from ${table ? `data."${table}"` : 'site.contents'} where $1 in (id,slug)`, [id]).then(el => el.rows?.[0]);
13
-
14
- if (!row) {
15
- const resp = { error: 'content not found', code: 404 };
16
- send(resp.error + ': ' + id);
17
- return resp;
18
- }
19
-
20
- const targetLocalization = await pg.query('select json_object_agg(split_part(field_key,\':\',1),field_value) from site.localization where object_id=$1 and field_key is not null and split_part(field_key,\':\',2)=$2', [row.id, to])
21
- .then(el => el.rows?.[0]?.json_object_agg);
22
-
23
- const localizationExists = await pg.query('select 1 from site.localization where object_id=$1 and field_key is not null and split_part(field_key,\':\',2)=$2', [row.id, to])
24
- .then(el => el.rowCount);
25
-
26
- if (localizationExists && !nocache && !skip) {
27
- const resp = { error: 'target localization already exists', code: 400 };
28
- send(resp.error + ': ' + id);
29
- return resp;
30
- }
31
-
32
- const localization = await pg.query('select json_object_agg(split_part(field_key,\':\',2),field_value) from site.localization where object_id=$1 and field_key is not null and split_part(field_key,\':\',2)=$2', [row.id, from])
33
- .then(el => el.rows?.[0]?.json_object_agg || {});
34
-
35
- if (!row) {
36
- const resp = { error: 'content not found', code: 404 };
37
- send(resp.error + ': ' + id);
38
- return resp;
39
- }
40
-
41
- const obj = { ...row, ...localization };
42
-
43
- const entries = Object.entries(obj).filter(([key, value]) => value && schemaKeys.includes(key) && (typeof value === 'string' || (Array.isArray(value) && value?.[0] && typeof value?.[0] === 'object' && Object.keys(value).length)));
44
- // do not overwrite old localization by default
45
- const filteredEntries = skip && targetLocalization ? entries.filter(([key]) => !Object.keys(targetLocalization).includes(key)) : entries;
46
-
47
- if (skip && targetLocalization && !filteredEntries.length) {
48
- const resp = { error: 'nothing to localize after skipping of fields with existing localization', code: 400 };
49
- send(resp.error + ': ' + id);
50
- return resp;
51
- }
52
-
53
- const skipped = schemaKeys.filter(key => !filteredEntries.map(([el]) => el).includes(key));
54
-
55
- const { result, error, code = 200 } = await requestTranslation(filteredEntries, from, to);
56
-
57
- if (error && code) {
58
- send(error + ': ' + id);
59
- return { error, code };
60
- }
61
-
62
- const arr = Object.keys(result).reduce((acc, curr) => {
63
- acc.push({
64
- field_key: curr,
65
- field_value: result[curr],
66
- object_id: id,
67
- });
68
- return acc;
69
- }, []);
70
-
71
- const client = await pg.connect();
72
-
73
- try {
74
- await client.query('begin');
75
-
76
- if (nocache) {
77
- const deleted = await client.query('delete from site.localization where object_id=$1 and split_part(field_key,\':\',2)=$2', [id, to]).then(el => el.rowCount || 0);
78
- send(`deleted existing localizations: ${deleted}, ${id}`);
79
- console.log('deleted existing localizations: ', deleted, id);
80
- }
81
-
82
- if (skip) {
83
- const deleted = await client.query('delete from site.localization where object_id=$1 and not split_part(field_key,\':\',1)<>any($2)', [id, Object.keys(targetLocalization)]).then(el => el.rowCount || 0);
84
- send(`deleted existing localizations1: ${deleted}, ${id}`);
85
- console.log('deleted existing localizations1: ', deleted, id);
86
- }
87
-
88
- await Promise.all(arr.map(async row => dataInsert({
89
- pg: client,
90
- table: 'site.localization',
91
- data: row,
92
- uid: user?.uid,
93
- })));
94
- await client.query('commit');
95
-
96
- send(`translation success: ${table}/${id}`);
97
- return { table, id: row.id, keys: schemaKeys, skipped, to };
98
- } catch (err) {
99
- await client.query('rollback');
100
- send(`translation error: ${err.toString()} (${id})`);
101
- return { error: err.toString(), code: 500 };
102
- } finally {
103
- client.release();
104
- }
1
+ import { dataInsert, pgClients } from "@opengis/fastify-table/utils.js";
2
+
3
+ import requestTranslation from "./requestTranslation.js";
4
+
5
+ export default async function insertContentLocalization({ send = () => { }, table, id, from, to, nocache, skip, schemaKeys, user }, pg = pgClients.client) {
6
+ if (!to) {
7
+ const resp = { error: 'not enough query params: to', code: 400 };
8
+ send(resp.error + ': ' + id);
9
+ return resp;
10
+ }
11
+
12
+ const row = await pg.query(`select * ${table ? '' : ',content_id as id'} from ${table ? `data."${table}"` : 'site.contents'} where $1 in (id,slug)`, [id]).then(el => el.rows?.[0]);
13
+
14
+ if (!row) {
15
+ const resp = { error: 'content not found', code: 404 };
16
+ send(resp.error + ': ' + id);
17
+ return resp;
18
+ }
19
+
20
+ const targetLocalization = await pg.query('select json_object_agg(split_part(field_key,\':\',1),field_value) from site.localization where object_id=$1 and field_key is not null and split_part(field_key,\':\',2)=$2', [row.id, to])
21
+ .then(el => el.rows?.[0]?.json_object_agg);
22
+
23
+ const localizationExists = await pg.query('select 1 from site.localization where object_id=$1 and field_key is not null and split_part(field_key,\':\',2)=$2', [row.id, to])
24
+ .then(el => el.rowCount);
25
+
26
+ if (localizationExists && !nocache && !skip) {
27
+ const resp = { error: 'target localization already exists', code: 400 };
28
+ send(resp.error + ': ' + id);
29
+ return resp;
30
+ }
31
+
32
+ const localization = await pg.query('select json_object_agg(split_part(field_key,\':\',2),field_value) from site.localization where object_id=$1 and field_key is not null and split_part(field_key,\':\',2)=$2', [row.id, from])
33
+ .then(el => el.rows?.[0]?.json_object_agg || {});
34
+
35
+ if (!row) {
36
+ const resp = { error: 'content not found', code: 404 };
37
+ send(resp.error + ': ' + id);
38
+ return resp;
39
+ }
40
+
41
+ const obj = { ...row, ...localization };
42
+
43
+ const entries = Object.entries(obj).filter(([key, value]) => value && schemaKeys.includes(key) && (typeof value === 'string' || (Array.isArray(value) && value?.[0] && typeof value?.[0] === 'object' && Object.keys(value).length)));
44
+ // do not overwrite old localization by default
45
+ const filteredEntries = skip && targetLocalization ? entries.filter(([key]) => !Object.keys(targetLocalization).includes(key)) : entries;
46
+
47
+ if (skip && targetLocalization && !filteredEntries.length) {
48
+ const resp = { error: 'nothing to localize after skipping of fields with existing localization', code: 400 };
49
+ send(resp.error + ': ' + id);
50
+ return resp;
51
+ }
52
+
53
+ const skipped = schemaKeys.filter(key => !filteredEntries.map(([el]) => el).includes(key));
54
+
55
+ const { result, error, code = 200 } = await requestTranslation(filteredEntries, from, to);
56
+
57
+ if (error && code) {
58
+ send(error + ': ' + id);
59
+ return { error, code };
60
+ }
61
+
62
+ const arr = Object.keys(result).reduce((acc, curr) => {
63
+ acc.push({
64
+ field_key: curr,
65
+ field_value: result[curr],
66
+ object_id: id,
67
+ });
68
+ return acc;
69
+ }, []);
70
+
71
+ const client = await pg.connect();
72
+
73
+ try {
74
+ await client.query('begin');
75
+
76
+ if (nocache) {
77
+ const deleted = await client.query('delete from site.localization where object_id=$1 and split_part(field_key,\':\',2)=$2', [id, to]).then(el => el.rowCount || 0);
78
+ send(`deleted existing localizations: ${deleted}, ${id}`);
79
+ console.log('deleted existing localizations: ', deleted, id);
80
+ }
81
+
82
+ if (skip) {
83
+ const deleted = await client.query('delete from site.localization where object_id=$1 and not split_part(field_key,\':\',1)<>any($2)', [id, Object.keys(targetLocalization)]).then(el => el.rowCount || 0);
84
+ send(`deleted existing localizations1: ${deleted}, ${id}`);
85
+ console.log('deleted existing localizations1: ', deleted, id);
86
+ }
87
+
88
+ await Promise.all(arr.map(async row => dataInsert({
89
+ pg: client,
90
+ table: 'site.localization',
91
+ data: row,
92
+ uid: user?.uid,
93
+ })));
94
+ await client.query('commit');
95
+
96
+ send(`translation success: ${table}/${id}`);
97
+ return { table, id: row.id, keys: schemaKeys, skipped, to };
98
+ } catch (err) {
99
+ await client.query('rollback');
100
+ send(`translation error: ${err.toString()} (${id})`);
101
+ return { error: err.toString(), code: 500 };
102
+ } finally {
103
+ client.release();
104
+ }
105
105
  }