@opengis/cms 0.0.50 → 0.0.52
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/{ArticlesPage-Cuit_90w.js → ArticlesPage-Cddv2qte.js} +5 -5
- package/dist/{BuilderPage-B79YHrmr.js → BuilderPage-BgcBJcw7.js} +139 -139
- package/dist/{CollectionsBreadcrumb.vue_vue_type_script_setup_true_lang-B6irHMzL.js → CollectionsBreadcrumb.vue_vue_type_script_setup_true_lang-C-k8QGA-.js} +19 -19
- package/dist/{CollectionsPage-JfmrHNR_.js → CollectionsPage-d5MLIIAG.js} +3 -3
- package/dist/{CreateForm-BMOBeP4G.js → CreateForm-B0srHu5e.js} +2 -2
- package/dist/{EditCollectionPage-B4p_iA6h.js → EditCollectionPage-NUVatLkY.js} +65 -59
- package/dist/{EmptyData-DaZt_nAm.js → EmptyData-BSW20VKP.js} +5 -5
- package/dist/{MenuAddPage-CmU4kAUM.js → MenuAddPage-Cn3JN04F.js} +3 -3
- package/dist/{MenuItemPage-UV8JlJvT.js → MenuItemPage-B0Th9EOe.js} +60 -60
- package/dist/{MenuPage-c4TPJgIN.js → MenuPage-DQpD3IXx.js} +4 -4
- package/dist/MonacoEditor.vue_vue_type_script_setup_true_lang-CTKNG0qR.js +84 -0
- package/dist/{UniversalTable.vue_vue_type_script_setup_true_lang-DR4PQwqR.js → UniversalTable.vue_vue_type_script_setup_true_lang-DW6O-xoY.js} +78 -78
- package/dist/{UniversalTablePagination.vue_vue_type_script_setup_true_lang-C8P9DCeX.js → UniversalTablePagination.vue_vue_type_script_setup_true_lang-DBIPBmpm.js} +46 -46
- package/dist/contentForm-C4Jp-FbQ.js +586 -0
- package/dist/{getField-C7EZs-YQ.js → getField-CKcz_b0t.js} +960 -933
- package/dist/index.js +10 -10
- package/dist/style.css +1 -1
- package/dist/{vuedraggable-CoAPPFYd.js → vuedraggable-mqqAYsch.js} +107 -107
- package/locales/en.json +6 -1
- package/locales/uk.json +4 -1
- package/package.json +68 -68
- package/server/functions/getContent.js +6 -15
- package/server/functions/getSearchData.js +3 -13
- package/server/functions/utils/mock.reply.js +56 -0
- package/server/routes/cms/controllers/listMedia.js +30 -3
- package/server/routes/cms/controllers/searchContent.js +12 -5
- package/server/routes/cms/utils/additionalData.js +1 -1
- package/dist/MonacoEditor.vue_vue_type_script_setup_true_lang-C8cip9Ci.js +0 -84
- package/dist/contentForm-S5mXr5B7.js +0 -553
package/locales/en.json
CHANGED
|
@@ -126,7 +126,10 @@
|
|
|
126
126
|
"dragToBuild": "Drag and drop content blocks here to build your collection structure",
|
|
127
127
|
"collectionCreated": "Collection created successfully",
|
|
128
128
|
"collectionCreationFailed": "Error creating collection",
|
|
129
|
-
"pinPublication": "Pin Publication"
|
|
129
|
+
"pinPublication": "Pin Publication",
|
|
130
|
+
"enLocalization": "EN localization",
|
|
131
|
+
"translateContentSuccess": "Content translated successfully",
|
|
132
|
+
"translateContentError": "Error translating content"
|
|
130
133
|
},
|
|
131
134
|
"articles": {
|
|
132
135
|
"title": "Articles",
|
|
@@ -478,6 +481,8 @@
|
|
|
478
481
|
"configure": "Configure",
|
|
479
482
|
"successTitle": "Success",
|
|
480
483
|
"successMessage": "Settings saved successfully",
|
|
484
|
+
"translateContentSuccess": "Content translated successfully",
|
|
485
|
+
"translateContentError": "Error translating content",
|
|
481
486
|
"errorTitle": "Error",
|
|
482
487
|
"errorMessage": "Error saving settings",
|
|
483
488
|
"generateNewKey": "Generate New Key",
|
package/locales/uk.json
CHANGED
|
@@ -126,7 +126,10 @@
|
|
|
126
126
|
"dragToBuild": "Перетягніть блоки контенту сюди, щоб створити структуру колекції",
|
|
127
127
|
"collectionCreated": "Колекція успішно створена",
|
|
128
128
|
"collectionCreationFailed": "Помилка при створенні колекції",
|
|
129
|
-
"pinPublication": "Закріпити публікацію"
|
|
129
|
+
"pinPublication": "Закріпити публікацію",
|
|
130
|
+
"enLocalization": "EN локалізація",
|
|
131
|
+
"translateContentSuccess": "Контент успішно перекладений",
|
|
132
|
+
"translateContentError": "Помилка при перекладі контенту"
|
|
130
133
|
},
|
|
131
134
|
"articles": {
|
|
132
135
|
"title": "Сторінки",
|
package/package.json
CHANGED
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@opengis/cms",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "cms",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"author": "Softpro",
|
|
7
|
-
"main": "./dist/index.js",
|
|
8
|
-
"license": "EULA",
|
|
9
|
-
"files": [
|
|
10
|
-
"module",
|
|
11
|
-
"locales",
|
|
12
|
-
"dist",
|
|
13
|
-
"server",
|
|
14
|
-
"plugin.js",
|
|
15
|
-
"utils.js",
|
|
16
|
-
"utils.d.ts",
|
|
17
|
-
"input-types.json"
|
|
18
|
-
],
|
|
19
|
-
"scripts": {
|
|
20
|
-
"patch": "npm version patch && git push && npm publish",
|
|
21
|
-
"test": "node --test test/**/*.test.js",
|
|
22
|
-
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
|
23
|
-
"dev": "NODE_ENV=dev bun --env-file=.env.ip server ",
|
|
24
|
-
"admin": "vite admin",
|
|
25
|
-
"build": "vite build && vite build admin",
|
|
26
|
-
"build:lib": "vite build",
|
|
27
|
-
"proxy": "vite dev admin",
|
|
28
|
-
"start": "bun --env-file=.env.ip server",
|
|
29
|
-
"prod": "NODE_ENV=production bun --env-file=.env.ip server ",
|
|
30
|
-
"ip": "bun --env-file=.env.ip server",
|
|
31
|
-
"demo": "node --env-file=.env.demo --env-file=.env server",
|
|
32
|
-
"i18n:sync": "node i18n-sync.cjs",
|
|
33
|
-
"prepublishOnly": "bun build:lib",
|
|
34
|
-
"softpro": "bun --env-file=.env.softpro server",
|
|
35
|
-
"softpro1": "NODE_ENV=production bun --env-file=.env.prod-softpro.local server"
|
|
36
|
-
},
|
|
37
|
-
"dependencies": {},
|
|
38
|
-
"resolutions": {
|
|
39
|
-
"rollup": "4.30.0"
|
|
40
|
-
},
|
|
41
|
-
"devDependencies": {
|
|
42
|
-
"@fastify/compress": "^8.1.0",
|
|
43
|
-
"@opengis/core": "^0.0.30",
|
|
44
|
-
"@opengis/fastify-table": "^2.0.
|
|
45
|
-
"@opengis/filter": "^0.1.31",
|
|
46
|
-
"@opengis/form": "^0.0.109",
|
|
47
|
-
"@opengis/richtext": "0.0.
|
|
48
|
-
"@vueuse/head": "2.0.0",
|
|
49
|
-
"js-yaml": "^4.1.0",
|
|
50
|
-
"lucide-vue-next": "0.344.0",
|
|
51
|
-
"vite": "5.1.4",
|
|
52
|
-
"vue": "^3.5.17",
|
|
53
|
-
"vue-i18n": "11.1.5",
|
|
54
|
-
"vue-router": "4.4.3",
|
|
55
|
-
"vuedraggable": "4.1.0",
|
|
56
|
-
"@tailwindcss/typography": "0.5.10",
|
|
57
|
-
"@tsconfig/node22": "^22.0.2",
|
|
58
|
-
"@vitejs/plugin-vue": "5.0.4",
|
|
59
|
-
"autoprefixer": "10.4.18",
|
|
60
|
-
"eslint": "8.49.0",
|
|
61
|
-
"postcss": "8.4.35",
|
|
62
|
-
"sass": "^1.92.1",
|
|
63
|
-
"tailwindcss": "3.4.1",
|
|
64
|
-
"typescript": "~5.8.0",
|
|
65
|
-
"vitest": "3.2.4",
|
|
66
|
-
"vue-tsc": "^2.2.10"
|
|
67
|
-
}
|
|
68
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@opengis/cms",
|
|
3
|
+
"version": "0.0.52",
|
|
4
|
+
"description": "cms",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"author": "Softpro",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"license": "EULA",
|
|
9
|
+
"files": [
|
|
10
|
+
"module",
|
|
11
|
+
"locales",
|
|
12
|
+
"dist",
|
|
13
|
+
"server",
|
|
14
|
+
"plugin.js",
|
|
15
|
+
"utils.js",
|
|
16
|
+
"utils.d.ts",
|
|
17
|
+
"input-types.json"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"patch": "npm version patch && git push && npm publish",
|
|
21
|
+
"test": "node --test test/**/*.test.js",
|
|
22
|
+
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
|
23
|
+
"dev": "NODE_ENV=dev bun --env-file=.env.ip server ",
|
|
24
|
+
"admin": "vite admin",
|
|
25
|
+
"build": "vite build && vite build admin",
|
|
26
|
+
"build:lib": "vite build",
|
|
27
|
+
"proxy": "vite dev admin",
|
|
28
|
+
"start": "bun --env-file=.env.ip server",
|
|
29
|
+
"prod": "NODE_ENV=production bun --env-file=.env.ip server ",
|
|
30
|
+
"ip": "bun --env-file=.env.ip server",
|
|
31
|
+
"demo": "node --env-file=.env.demo --env-file=.env server",
|
|
32
|
+
"i18n:sync": "node i18n-sync.cjs",
|
|
33
|
+
"prepublishOnly": "bun build:lib",
|
|
34
|
+
"softpro": "bun --env-file=.env.softpro server",
|
|
35
|
+
"softpro1": "NODE_ENV=production bun --env-file=.env.prod-softpro.local server"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {},
|
|
38
|
+
"resolutions": {
|
|
39
|
+
"rollup": "4.30.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@fastify/compress": "^8.1.0",
|
|
43
|
+
"@opengis/core": "^0.0.30",
|
|
44
|
+
"@opengis/fastify-table": "^2.0.143",
|
|
45
|
+
"@opengis/filter": "^0.1.31",
|
|
46
|
+
"@opengis/form": "^0.0.109",
|
|
47
|
+
"@opengis/richtext": "0.0.45",
|
|
48
|
+
"@vueuse/head": "2.0.0",
|
|
49
|
+
"js-yaml": "^4.1.0",
|
|
50
|
+
"lucide-vue-next": "0.344.0",
|
|
51
|
+
"vite": "5.1.4",
|
|
52
|
+
"vue": "^3.5.17",
|
|
53
|
+
"vue-i18n": "11.1.5",
|
|
54
|
+
"vue-router": "4.4.3",
|
|
55
|
+
"vuedraggable": "4.1.0",
|
|
56
|
+
"@tailwindcss/typography": "0.5.10",
|
|
57
|
+
"@tsconfig/node22": "^22.0.2",
|
|
58
|
+
"@vitejs/plugin-vue": "5.0.4",
|
|
59
|
+
"autoprefixer": "10.4.18",
|
|
60
|
+
"eslint": "8.49.0",
|
|
61
|
+
"postcss": "8.4.35",
|
|
62
|
+
"sass": "^1.92.1",
|
|
63
|
+
"tailwindcss": "3.4.1",
|
|
64
|
+
"typescript": "~5.8.0",
|
|
65
|
+
"vitest": "3.2.4",
|
|
66
|
+
"vue-tsc": "^2.2.10"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -1,25 +1,14 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
|
|
3
3
|
import { config, getRedis, pgClients } from '@opengis/fastify-table/utils.js';
|
|
4
|
-
|
|
4
|
+
import { createMockReply } from './utils/mock.reply.js';
|
|
5
5
|
import getContent from '../routes/cms/controllers/getContent.js';
|
|
6
6
|
|
|
7
7
|
const pg = pgClients.client;
|
|
8
8
|
const rclient = getRedis();
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
status: (statusCode) => {
|
|
13
|
-
Object.assign(mockReply.response, { status: statusCode });
|
|
14
|
-
return mockReply;
|
|
15
|
-
},
|
|
16
|
-
send: (result) => {
|
|
17
|
-
Object.assign(mockReply.response, typeof result === 'object' ? result : { message: result });
|
|
18
|
-
return { ...mockReply.response };
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export default async function getContentBySlug({ slug, filter, tags, state, locale, contextQuery, collection = 'pages', ttl = 3600, fields, limit = 12, page = 1 } = {}) {
|
|
10
|
+
|
|
11
|
+
export default async function getContentBySlug({ slug, filter, tags, state, locale, contextQuery, collection = 'pages', ttl = 3600, fields, limit = 12, page = 1, order, desc } = {}) {
|
|
23
12
|
if (!slug) {
|
|
24
13
|
// return { error: 'not enough params: slug', code: 400 };
|
|
25
14
|
}
|
|
@@ -43,7 +32,9 @@ export default async function getContentBySlug({ slug, filter, tags, state, loca
|
|
|
43
32
|
return { cache: true, ...cacheData };
|
|
44
33
|
}
|
|
45
34
|
|
|
46
|
-
const req = { pg: pgClients.client, params: { type: collection, id: slug }, query: { filter, tags, state, contextQuery, locale, fields, limit, page } };
|
|
35
|
+
const req = { pg: pgClients.client, params: { type: collection, id: slug }, query: { filter, tags, state, contextQuery, locale, fields, limit, page, order, desc } };
|
|
36
|
+
|
|
37
|
+
const mockReply = createMockReply();
|
|
47
38
|
const result = await getContent(req, mockReply, true);
|
|
48
39
|
|
|
49
40
|
if (ttl) {
|
|
@@ -1,29 +1,18 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
|
|
3
3
|
import { config, getRedis, pgClients } from '@opengis/fastify-table/utils.js';
|
|
4
|
+
import { createMockReply } from './utils/mock.reply.js';
|
|
4
5
|
|
|
5
6
|
import searchContent from '../routes/cms/controllers/searchContent.js';
|
|
6
7
|
|
|
7
8
|
const pg = pgClients.client;
|
|
8
9
|
const rclient = getRedis();
|
|
9
10
|
|
|
10
|
-
const mockReply = {
|
|
11
|
-
response: {},
|
|
12
|
-
status: (statusCode) => {
|
|
13
|
-
Object.assign(mockReply.response, { status: statusCode });
|
|
14
|
-
return mockReply;
|
|
15
|
-
},
|
|
16
|
-
send: (result) => {
|
|
17
|
-
Object.assign(mockReply.response, typeof result === 'object' ? result : { message: result });
|
|
18
|
-
return { ...mockReply.response };
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
|
|
22
11
|
export default async function getSearchData({ page = 1, limit = 12, ttl = 3600, search, locale, tags, filter, contentType, asc } = {}) {
|
|
23
12
|
// check if any crud operations performed, if not - return cached response
|
|
24
13
|
const crudInc = await rclient.get(`pg:site.contents:crud`) || 0;
|
|
25
14
|
|
|
26
|
-
const cacheKey = createHash('md5').update([config.pg?.database, 'cms:search', crudInc, page, limit,
|
|
15
|
+
const cacheKey = createHash('md5').update([config.pg?.database, 'cms:search', crudInc, page, limit, search, locale, tags, filter, contentType, asc].join(':')).digest('hex');
|
|
27
16
|
const cacheData = ttl === 0 ? null : JSON.parse(await rclient.get(cacheKey));
|
|
28
17
|
|
|
29
18
|
// return from cache
|
|
@@ -31,6 +20,7 @@ export default async function getSearchData({ page = 1, limit = 12, ttl = 3600,
|
|
|
31
20
|
return { cache: true, ...cacheData };
|
|
32
21
|
}
|
|
33
22
|
|
|
23
|
+
const mockReply = createMockReply();
|
|
34
24
|
const result = await searchContent({ pg, query: { search, locale, page, limit, tags, filter, contentType } }, mockReply);
|
|
35
25
|
|
|
36
26
|
if (ttl) {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @template T
|
|
3
|
+
* @typedef {Object} MockReplyResponse
|
|
4
|
+
* @property {number} [status] - HTTP статус-код
|
|
5
|
+
* @property {T} [data] - Дані відповіді (якщо передано об'єкт)
|
|
6
|
+
* @property {string} [message] - Повідомлення (якщо передано рядок)
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Створює ізольований mock-об'єкт reply для тестування Fastify-хендлерів.
|
|
11
|
+
* Імітує методи `status()` та `send()`.
|
|
12
|
+
*
|
|
13
|
+
* @template T
|
|
14
|
+
* @returns {{
|
|
15
|
+
* status: (statusCode: number) => any,
|
|
16
|
+
* send: (result: T | string) => MockReplyResponse<T>
|
|
17
|
+
* }}
|
|
18
|
+
*/
|
|
19
|
+
export function createMockReply() {
|
|
20
|
+
/** @type {MockReplyResponse<any>} */
|
|
21
|
+
|
|
22
|
+
let response = {};
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
/**
|
|
26
|
+
* Встановлює HTTP статус-код.
|
|
27
|
+
* Повертає той самий reply для чейнінгу.
|
|
28
|
+
*
|
|
29
|
+
* @param {number} statusCode
|
|
30
|
+
* @returns {any}
|
|
31
|
+
*/
|
|
32
|
+
status(statusCode) {
|
|
33
|
+
response.status = statusCode;
|
|
34
|
+
return this;
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Імітує Fastify reply.send().
|
|
39
|
+
* Якщо передано об'єкт — він додається як data.
|
|
40
|
+
* Якщо передано рядок — додається як message.
|
|
41
|
+
*
|
|
42
|
+
* @param {T | string} result
|
|
43
|
+
* @returns {MockReplyResponse<T>}
|
|
44
|
+
*/
|
|
45
|
+
send(result) {
|
|
46
|
+
response = {
|
|
47
|
+
...response,
|
|
48
|
+
...(typeof result === 'object'
|
|
49
|
+
? { data: result }
|
|
50
|
+
: { message: result }),
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return response;
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -23,7 +23,7 @@ const rootDir = path.resolve(getFolder(config, 'local'));
|
|
|
23
23
|
const dir = '/files';
|
|
24
24
|
|
|
25
25
|
const filesizeCache = {};
|
|
26
|
-
const
|
|
26
|
+
const fileMtimeCache = {};
|
|
27
27
|
|
|
28
28
|
mkdirSync(path.join(rootDir, dir), { recursive: true });
|
|
29
29
|
|
|
@@ -89,8 +89,33 @@ export default async function listMedia(req, reply) {
|
|
|
89
89
|
const filepath = media ? media.url : ('/files/' + (el.path.split('/files/')[1] ? el.path.split('/files/')[1] + '/' : '') + el.name);
|
|
90
90
|
|
|
91
91
|
if (!filesizeCache[filepath]) {
|
|
92
|
-
const { size } = await stat(path.join(rootDir, filepath));
|
|
92
|
+
const { mtime, size } = await stat(path.join(rootDir, filepath));
|
|
93
93
|
Object.assign(filesizeCache, { [filepath]: size });
|
|
94
|
+
mtime.setHours(0, 0, 0, 0); // strip hours from timestamp, leave only date
|
|
95
|
+
Object.assign(fileMtimeCache, { [filepath]: mtime });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
const [, from, to] = q ? (q.match(/between\s+'(\d{4}-\d{2}-\d{2})'::date\s+and\s+'(\d{4}-\d{2}-\d{2})'::date/i) || []) : [];
|
|
100
|
+
|
|
101
|
+
// skip entirely if invalid dates passed to query.filter
|
|
102
|
+
if ((from && new Date(from).toString() === 'Invalid Date') || (to && new Date(to).toString() === 'Invalid Date')) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// skip if file modification date does not match filter value
|
|
107
|
+
if (fileMtimeCache[filepath] && from && to && (new Date(from) > fileMtimeCache[filepath] || new Date(to) < fileMtimeCache[filepath])) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const dt = q && !q.includes('between') ? query.filter.match(/\d{4}-\d{2}-\d{2}/)?.[0] : null;
|
|
112
|
+
const date = dt ? new Date(dt) : null;
|
|
113
|
+
// skip timezone offset
|
|
114
|
+
if (date) { date.setHours(0, 0, 0, 0); }
|
|
115
|
+
|
|
116
|
+
// filter by exact date
|
|
117
|
+
if (fileMtimeCache[filepath] && date && (new Date(date).getTime() !== fileMtimeCache[filepath].getTime())) {
|
|
118
|
+
return null;
|
|
94
119
|
}
|
|
95
120
|
|
|
96
121
|
const mime = getMimeType(el.name) || '';
|
|
@@ -116,10 +141,12 @@ export default async function listMedia(req, reply) {
|
|
|
116
141
|
url: filepath,
|
|
117
142
|
mime,
|
|
118
143
|
preview,
|
|
144
|
+
updated_at: fileMtimeCache[filepath].toISOString(),
|
|
119
145
|
}
|
|
120
146
|
}));
|
|
121
147
|
|
|
122
|
-
|
|
148
|
+
// filter empty items, such as filtered out by query.filter=updated_at (not from db, but from fs.stat)
|
|
149
|
+
Object.assign(result, { data: subdirs.concat(files.filter(Boolean)) });
|
|
123
150
|
return result;
|
|
124
151
|
|
|
125
152
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { pgClients, getFilterSQL } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
import additionalData from '../utils/additionalData.js';
|
|
2
4
|
|
|
3
5
|
const filterList = [
|
|
4
6
|
{
|
|
@@ -55,11 +57,12 @@ export default async function searchContent({
|
|
|
55
57
|
const limit = Math.min(query.limit || 16, maxLimit);
|
|
56
58
|
const offset = (page - 1) * limit;
|
|
57
59
|
|
|
58
|
-
const { q } = filter ? await getFilterSQL({
|
|
60
|
+
const { q } = filter || search ? await getFilterSQL({
|
|
59
61
|
pg,
|
|
60
62
|
table: 'site.contents',
|
|
61
63
|
filter,
|
|
62
64
|
search,
|
|
65
|
+
searchColumn: 'a.slug,a.title',
|
|
63
66
|
query: `status='published'`,
|
|
64
67
|
filterList,
|
|
65
68
|
}) : { q: `status='published'` };
|
|
@@ -91,11 +94,11 @@ export default async function searchContent({
|
|
|
91
94
|
const collections = contents.filter(el => el.content_type === 'collection' && el.table_name);
|
|
92
95
|
|
|
93
96
|
// const totals = await pg.query(`select json_object_agg(oid::regclass, reltuples) from pg_class`).then(el => el.rows?.[0]?.json_object_agg || {});
|
|
94
|
-
const allSingles = await pg.query(`select count(*)::int from site.contents where content_type_id in (select content_type_id from site.content_types where type = 'single'
|
|
97
|
+
const allSingles = await pg.query(`select count(*)::int from site.contents where content_type_id in (select content_type_id from site.content_types where type = 'single') and status='published'`).then(el => el.rows?.[0]?.count || 0);
|
|
95
98
|
const allCollectionTables = await pg.query(`select array_agg(table_name) from site.content_types where type = 'collection' and table_name is not null`).then(el => el.rows?.[0]?.array_agg || []);
|
|
96
99
|
|
|
97
100
|
const allCollections = await Promise.all(allCollectionTables.map(async tablename => {
|
|
98
|
-
const total = pg.queryCache ? await pg.queryCache(`select count(*)::int from data."${tablename}"`, { table: `data.${tablename}` }).then(el => el.rows?.[0]?.count || 0) : 0;
|
|
101
|
+
const total = pg.queryCache ? await pg.queryCache(`select count(*)::int from data."${tablename}" where status='published'`, { table: `data.${tablename}` }).then(el => el.rows?.[0]?.count || 0) : 0;
|
|
99
102
|
return total;
|
|
100
103
|
})).then(el => el.reduce((acc, curr) => acc + (curr || 0), 0) || 0);
|
|
101
104
|
|
|
@@ -121,10 +124,12 @@ export default async function searchContent({
|
|
|
121
124
|
}[!!asc];
|
|
122
125
|
|
|
123
126
|
const { optimizedSQL = `SELECT * FROM data."${table}" where status='published' ORDER BY ${order}` } =
|
|
124
|
-
filter ? await getFilterSQL({
|
|
127
|
+
filter || search ? await getFilterSQL({
|
|
125
128
|
pg,
|
|
126
129
|
table: `data."${table}"`,
|
|
127
130
|
filter,
|
|
131
|
+
search,
|
|
132
|
+
searchColumn: 'slug,title',
|
|
128
133
|
query: `status='published'`,
|
|
129
134
|
filterList: collectionFilters,
|
|
130
135
|
order: 'published_at DESC NULLS LAST'
|
|
@@ -141,6 +146,8 @@ export default async function searchContent({
|
|
|
141
146
|
return { rows: [], /*total: total // totals[`data.${table}`] || totals[`data."${table}"`] || 0*/ };
|
|
142
147
|
});
|
|
143
148
|
|
|
149
|
+
// await additionalData(pg, items, locale);
|
|
150
|
+
|
|
144
151
|
return {
|
|
145
152
|
rows: items.map(el => ({
|
|
146
153
|
...row,
|
|
@@ -22,7 +22,7 @@ export default async function additionalData(pg, rows, locale, fields = '*') {
|
|
|
22
22
|
const localization = localizations.find(el => el.object_id === row.id);
|
|
23
23
|
const localizationKeys = Object.keys(localization?.json_object_agg || {}).filter(key => row[key.split(':').shift()]);
|
|
24
24
|
const localizationObj1 = Object.entries(localization?.json_object_agg || {}).filter(([key]) => rows.length > 1 ? true : localizationKeys.includes(key)).reduce((acc, curr) => ({ ...acc, [curr[0]]: typeof curr[1] === 'string' && curr[1].startsWith('[') && curr[1].endsWith(']') ? JSON.parse(curr[1]) : curr[1] }), {});
|
|
25
|
-
const localizationObj = fields?.length ? Object.fromEntries(Object.entries(localizationObj1).filter(([key]) => fields.split(',').includes(key.split(':').shift()))) : localizationObj1;
|
|
25
|
+
const localizationObj = fields?.length && fields !== '*' ? Object.fromEntries(Object.entries(localizationObj1).filter(([key]) => fields.split(',').includes(key.split(':').shift()))) : localizationObj1;
|
|
26
26
|
if (locale && locale !== 'uk') {
|
|
27
27
|
Object.assign(row, Object.keys(localizationObj).reduce((acc, curr) => ({ ...acc, [curr.replace(`:${locale}`, '')]: localizationObj[curr] }), {}));
|
|
28
28
|
} else if (!locale) {
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { defineComponent as s, mergeModels as m, useModel as c, ref as f, onMounted as h, watch as d, onBeforeUnmount as p, openBlock as g, createElementBlock as v, normalizeStyle as w } from "vue";
|
|
2
|
-
async function M() {
|
|
3
|
-
if (window.monaco)
|
|
4
|
-
return window.monaco;
|
|
5
|
-
const i = "https://cdn.jsdelivr.net/npm/monaco-editor@0.45.0/min";
|
|
6
|
-
return window.require || (window.require = { paths: { vs: `${i}/vs` } }, await new Promise((t, l) => {
|
|
7
|
-
const n = document.createElement("script");
|
|
8
|
-
n.src = `${i}/vs/loader.min.js`, n.onload = () => t(), n.onerror = l, document.head.appendChild(n);
|
|
9
|
-
})), new Promise((t) => {
|
|
10
|
-
window.require(["vs/editor/editor.main"], () => t(window.monaco));
|
|
11
|
-
});
|
|
12
|
-
}
|
|
13
|
-
const C = /* @__PURE__ */ s({
|
|
14
|
-
__name: "MonacoEditor",
|
|
15
|
-
props: /* @__PURE__ */ m({
|
|
16
|
-
language: { default: "javascript" },
|
|
17
|
-
theme: { default: "vs-dark" },
|
|
18
|
-
width: { default: "100%" },
|
|
19
|
-
height: { default: "100%" },
|
|
20
|
-
options: { default: () => ({
|
|
21
|
-
minimap: { enabled: !1 }
|
|
22
|
-
}) }
|
|
23
|
-
}, {
|
|
24
|
-
modelValue: {
|
|
25
|
-
required: !0
|
|
26
|
-
},
|
|
27
|
-
modelModifiers: {}
|
|
28
|
-
}),
|
|
29
|
-
emits: ["update:modelValue"],
|
|
30
|
-
setup(i) {
|
|
31
|
-
const t = i, l = c(i, "modelValue"), n = f(null);
|
|
32
|
-
let o = null, r = null;
|
|
33
|
-
return h(async () => {
|
|
34
|
-
var e;
|
|
35
|
-
if (n.value)
|
|
36
|
-
try {
|
|
37
|
-
r = await M();
|
|
38
|
-
const a = ((e = l.value) == null ? void 0 : e.replace(/\\n/g, `
|
|
39
|
-
`)) || "";
|
|
40
|
-
o = r.editor.create(n.value, {
|
|
41
|
-
value: a,
|
|
42
|
-
language: t.language,
|
|
43
|
-
theme: t.theme,
|
|
44
|
-
automaticLayout: !0,
|
|
45
|
-
...t.options
|
|
46
|
-
}), o.onDidChangeModelContent(() => {
|
|
47
|
-
const u = (o == null ? void 0 : o.getValue()) || "";
|
|
48
|
-
l.value = u;
|
|
49
|
-
});
|
|
50
|
-
} catch (a) {
|
|
51
|
-
console.error("Failed to load Monaco Editor:", a);
|
|
52
|
-
}
|
|
53
|
-
}), d(
|
|
54
|
-
() => l.value,
|
|
55
|
-
(e) => {
|
|
56
|
-
if (o) {
|
|
57
|
-
const a = (e == null ? void 0 : e.replace(/\\n/g, `
|
|
58
|
-
`)) || "";
|
|
59
|
-
a !== o.getValue() && o.setValue(a);
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
{ immediate: !0 }
|
|
63
|
-
), d(
|
|
64
|
-
() => t.language,
|
|
65
|
-
(e) => {
|
|
66
|
-
o && e && r && r.editor.setModelLanguage(o.getModel(), e);
|
|
67
|
-
}
|
|
68
|
-
), d(
|
|
69
|
-
() => t.theme,
|
|
70
|
-
(e) => {
|
|
71
|
-
o && e && r && r.editor.setTheme(e);
|
|
72
|
-
}
|
|
73
|
-
), p(() => {
|
|
74
|
-
o && (o.dispose(), o = null);
|
|
75
|
-
}), (e, a) => (g(), v("div", {
|
|
76
|
-
ref_key: "editorContainer",
|
|
77
|
-
ref: n,
|
|
78
|
-
style: w({ width: e.width, height: e.height })
|
|
79
|
-
}, null, 4));
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
export {
|
|
83
|
-
C as _
|
|
84
|
-
};
|