@opengis/cms 0.0.35 → 0.0.36
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/MenuAddPage-CUvJmUMq.js +112 -0
- package/dist/MenuItemPage-sG5nAbiE.js +1375 -0
- package/dist/MenuPage-jPWKpo5C.js +102 -0
- package/dist/index-7TVhDCPx.js +21173 -0
- package/dist/index.js +13 -21591
- package/dist/index.umd.cjs +86 -58
- package/package.json +1 -2
- package/server/routes/cms/controllers/deleteMedia.js +76 -76
- package/server/routes/cms/controllers/downloadMedia.js +49 -49
- package/server/routes/cms/controllers/getPermissions.js +15 -15
- package/server/routes/cms/controllers/listMedia.js +94 -94
- package/server/routes/cms/controllers/metadataMedia.js +39 -39
- package/server/routes/cms/controllers/setPermissions.js +49 -49
- package/server/routes/cms/controllers/uploadMedia.js +79 -79
- package/server/templates/select/core.user_mentioned.sql +1 -1
- package/module/cms/cls/content.status.json +0 -18
- package/module/cms/cls/user_type.json +0 -10
- package/module/cms/form/admin.users.form.json +0 -78
- package/module/cms/select/cms.page_type.sql +0 -2
- package/module/cms/select/collection.sql +0 -1
- package/module/cms/select/news_tag_id.sql +0 -12
- package/module/cms/select/tag_id.sql +0 -1
- package/module/cms/table/admin.users.table.json +0 -54
- package/module/cms/table/collection.default.table.json +0 -96
- package/module/cms/table/single.default.table.json +0 -114
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
import { logger, pgClients, dataInsert } from '@opengis/fastify-table/utils.js';
|
|
2
|
-
|
|
3
|
-
export default async function setPermissions(req, reply) {
|
|
4
|
-
const { pg = pgClients.client, params = {}, user = {}, body = {} } = req;
|
|
5
|
-
|
|
6
|
-
if (!user?.uid) {
|
|
7
|
-
return reply.status(401).send('unauthorized');
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
if (!params.id) {
|
|
11
|
-
return reply.status(400).send('not enough params: id');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const client = await pg.connect()
|
|
15
|
-
const result = {};
|
|
16
|
-
try {
|
|
17
|
-
await client.query('BEGIN');
|
|
18
|
-
|
|
19
|
-
const { rowCount = 0 } = await client.query(
|
|
20
|
-
`delete from site.permissions where user_id=$1`,
|
|
21
|
-
[params.id].filter(Boolean),
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
Object.assign(result, { deleted: rowCount });
|
|
25
|
-
|
|
26
|
-
if (Array.isArray(body.permissions) && body.permissions?.length) {
|
|
27
|
-
body.permissions.forEach((el) => {
|
|
28
|
-
Object.assign(el, { user_id: el.user_id || params.id });
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
await Promise.all(body.permissions.map(async (el) => dataInsert({
|
|
32
|
-
pg: client,
|
|
33
|
-
table: 'site.permissions',
|
|
34
|
-
data: el,
|
|
35
|
-
uid: user.uid,
|
|
36
|
-
})));
|
|
37
|
-
|
|
38
|
-
Object.assign(result, { inserted: body.permissions.length });
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
await client.query('COMMIT');
|
|
42
|
-
return reply.status(200).send(result);
|
|
43
|
-
} catch (err) {
|
|
44
|
-
await client.query('ROLLBACK');
|
|
45
|
-
logger.file('cms/permissions', { error: err.toString(), stack: err.stack });
|
|
46
|
-
return reply.status(500).send('set permissions error');
|
|
47
|
-
} finally {
|
|
48
|
-
client.release();
|
|
49
|
-
}
|
|
1
|
+
import { logger, pgClients, dataInsert } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
export default async function setPermissions(req, reply) {
|
|
4
|
+
const { pg = pgClients.client, params = {}, user = {}, body = {} } = req;
|
|
5
|
+
|
|
6
|
+
if (!user?.uid) {
|
|
7
|
+
return reply.status(401).send('unauthorized');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (!params.id) {
|
|
11
|
+
return reply.status(400).send('not enough params: id');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const client = await pg.connect()
|
|
15
|
+
const result = {};
|
|
16
|
+
try {
|
|
17
|
+
await client.query('BEGIN');
|
|
18
|
+
|
|
19
|
+
const { rowCount = 0 } = await client.query(
|
|
20
|
+
`delete from site.permissions where user_id=$1`,
|
|
21
|
+
[params.id].filter(Boolean),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
Object.assign(result, { deleted: rowCount });
|
|
25
|
+
|
|
26
|
+
if (Array.isArray(body.permissions) && body.permissions?.length) {
|
|
27
|
+
body.permissions.forEach((el) => {
|
|
28
|
+
Object.assign(el, { user_id: el.user_id || params.id });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
await Promise.all(body.permissions.map(async (el) => dataInsert({
|
|
32
|
+
pg: client,
|
|
33
|
+
table: 'site.permissions',
|
|
34
|
+
data: el,
|
|
35
|
+
uid: user.uid,
|
|
36
|
+
})));
|
|
37
|
+
|
|
38
|
+
Object.assign(result, { inserted: body.permissions.length });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
await client.query('COMMIT');
|
|
42
|
+
return reply.status(200).send(result);
|
|
43
|
+
} catch (err) {
|
|
44
|
+
await client.query('ROLLBACK');
|
|
45
|
+
logger.file('cms/permissions', { error: err.toString(), stack: err.stack });
|
|
46
|
+
return reply.status(500).send('set permissions error');
|
|
47
|
+
} finally {
|
|
48
|
+
client.release();
|
|
49
|
+
}
|
|
50
50
|
}
|
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import { mkdir } from 'node:fs/promises';
|
|
3
|
-
|
|
4
|
-
import { uploadMultiPart, config, getFolder, dataInsert, pgClients } from "@opengis/fastify-table/utils.js";
|
|
5
|
-
|
|
6
|
-
// path.resolve() converts POSIX paths from getFolder to valid Windows paths (Bun/Node fs require this on Windows)
|
|
7
|
-
const rootDir = path.resolve(getFolder(config, 'local'));
|
|
8
|
-
const dir = '/files';
|
|
9
|
-
|
|
10
|
-
export default async function uploadMedia(req, reply) {
|
|
11
|
-
const { pg = pgClients.client, user = {}, query = {} } = req;
|
|
12
|
-
|
|
13
|
-
if (!pg?.pk?.['site.media']) {
|
|
14
|
-
return reply.status(404).send('table not found');
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if (query.subdir && (typeof query.subdir !== 'string' || query.subdir.includes('..'))) {
|
|
18
|
-
return reply.status(403).send('invalid query params: subdir');
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// upload assets
|
|
22
|
-
if (req.headers['content-type']?.split?.(';')?.shift?.() === 'multipart/form-data') {
|
|
23
|
-
const file = await uploadMultiPart(req, { subdir: query.subdir || '', originalFilename: true }).catch(err => {
|
|
24
|
-
if (err.message === 'file with specified name already exists in directory') {
|
|
25
|
-
err.message = 'Файл з вказаною назвою вже існує';
|
|
26
|
-
err.statusCode = 400;
|
|
27
|
-
}
|
|
28
|
-
throw err;
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const { originalFilename: filename, filetype, mimetype } = file;
|
|
32
|
-
const relpath = path.join(dir, query.subdir || '', file.originalFilename).replace(/\\/g, '/');
|
|
33
|
-
|
|
34
|
-
const id = await dataInsert({
|
|
35
|
-
pg,
|
|
36
|
-
table: 'site.media',
|
|
37
|
-
data: {
|
|
38
|
-
filename,
|
|
39
|
-
filetype,
|
|
40
|
-
subdir: query.subdir,
|
|
41
|
-
url: relpath,
|
|
42
|
-
mime: mimetype,
|
|
43
|
-
filesize: file.size,
|
|
44
|
-
},
|
|
45
|
-
uid: user?.uid,
|
|
46
|
-
}).then(el => el?.rows?.[0]?.media_id);
|
|
47
|
-
|
|
48
|
-
return reply.status(200).send({
|
|
49
|
-
res: 'ok',
|
|
50
|
-
name: filename,
|
|
51
|
-
type: 'file',
|
|
52
|
-
mimetype,
|
|
53
|
-
result: {
|
|
54
|
-
file_id: id,
|
|
55
|
-
format: file.extension,
|
|
56
|
-
size: file.size,
|
|
57
|
-
// entity_id: resultInsert?.entity_id,
|
|
58
|
-
file_path: relpath,
|
|
59
|
-
file_name: filename,
|
|
60
|
-
dir: path.dirname(relpath).replace(/\\/g, '/'),
|
|
61
|
-
native_file_name: filename,
|
|
62
|
-
},
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (!query.subdir) {
|
|
67
|
-
return reply.status(400).send('not enough query params: subdir');
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// create directory
|
|
71
|
-
const relpath = path.join(dir, query.subdir).replace(/\\/g, '/');
|
|
72
|
-
const dirpath = path.join(rootDir, relpath);
|
|
73
|
-
await mkdir(dirpath, { recursive: true });
|
|
74
|
-
|
|
75
|
-
return reply.status(200).send({
|
|
76
|
-
relpath,
|
|
77
|
-
dirname: path.basename(query.subdir),
|
|
78
|
-
type: 'dir',
|
|
79
|
-
});
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { mkdir } from 'node:fs/promises';
|
|
3
|
+
|
|
4
|
+
import { uploadMultiPart, config, getFolder, dataInsert, pgClients } from "@opengis/fastify-table/utils.js";
|
|
5
|
+
|
|
6
|
+
// path.resolve() converts POSIX paths from getFolder to valid Windows paths (Bun/Node fs require this on Windows)
|
|
7
|
+
const rootDir = path.resolve(getFolder(config, 'local'));
|
|
8
|
+
const dir = '/files';
|
|
9
|
+
|
|
10
|
+
export default async function uploadMedia(req, reply) {
|
|
11
|
+
const { pg = pgClients.client, user = {}, query = {} } = req;
|
|
12
|
+
|
|
13
|
+
if (!pg?.pk?.['site.media']) {
|
|
14
|
+
return reply.status(404).send('table not found');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (query.subdir && (typeof query.subdir !== 'string' || query.subdir.includes('..'))) {
|
|
18
|
+
return reply.status(403).send('invalid query params: subdir');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// upload assets
|
|
22
|
+
if (req.headers['content-type']?.split?.(';')?.shift?.() === 'multipart/form-data') {
|
|
23
|
+
const file = await uploadMultiPart(req, { subdir: query.subdir || '', originalFilename: true }).catch(err => {
|
|
24
|
+
if (err.message === 'file with specified name already exists in directory') {
|
|
25
|
+
err.message = 'Файл з вказаною назвою вже існує';
|
|
26
|
+
err.statusCode = 400;
|
|
27
|
+
}
|
|
28
|
+
throw err;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const { originalFilename: filename, filetype, mimetype } = file;
|
|
32
|
+
const relpath = path.join(dir, query.subdir || '', file.originalFilename).replace(/\\/g, '/');
|
|
33
|
+
|
|
34
|
+
const id = await dataInsert({
|
|
35
|
+
pg,
|
|
36
|
+
table: 'site.media',
|
|
37
|
+
data: {
|
|
38
|
+
filename,
|
|
39
|
+
filetype,
|
|
40
|
+
subdir: query.subdir,
|
|
41
|
+
url: relpath,
|
|
42
|
+
mime: mimetype,
|
|
43
|
+
filesize: file.size,
|
|
44
|
+
},
|
|
45
|
+
uid: user?.uid,
|
|
46
|
+
}).then(el => el?.rows?.[0]?.media_id);
|
|
47
|
+
|
|
48
|
+
return reply.status(200).send({
|
|
49
|
+
res: 'ok',
|
|
50
|
+
name: filename,
|
|
51
|
+
type: 'file',
|
|
52
|
+
mimetype,
|
|
53
|
+
result: {
|
|
54
|
+
file_id: id,
|
|
55
|
+
format: file.extension,
|
|
56
|
+
size: file.size,
|
|
57
|
+
// entity_id: resultInsert?.entity_id,
|
|
58
|
+
file_path: relpath,
|
|
59
|
+
file_name: filename,
|
|
60
|
+
dir: path.dirname(relpath).replace(/\\/g, '/'),
|
|
61
|
+
native_file_name: filename,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!query.subdir) {
|
|
67
|
+
return reply.status(400).send('not enough query params: subdir');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// create directory
|
|
71
|
+
const relpath = path.join(dir, query.subdir).replace(/\\/g, '/');
|
|
72
|
+
const dirpath = path.join(rootDir, relpath);
|
|
73
|
+
await mkdir(dirpath, { recursive: true });
|
|
74
|
+
|
|
75
|
+
return reply.status(200).send({
|
|
76
|
+
relpath,
|
|
77
|
+
dirname: path.basename(query.subdir),
|
|
78
|
+
type: 'dir',
|
|
79
|
+
});
|
|
80
80
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
select uid, coalesce(sur_name,'')||coalesce(' '||user_name,'') as text, email from admin.users
|
|
1
|
+
select uid, coalesce(sur_name,'')||coalesce(' '||user_name,'') as text, email from admin.users
|
|
2
2
|
where enabled order by coalesce(sur_name,'')||coalesce(' '||user_name,'')
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"schema": {
|
|
3
|
-
"user_name": {
|
|
4
|
-
"type": "Text",
|
|
5
|
-
"rules": [
|
|
6
|
-
"required"
|
|
7
|
-
],
|
|
8
|
-
"ua": "Ім'я",
|
|
9
|
-
"i": "Вноситься ім'я користувача, що буде відображатися у системі"
|
|
10
|
-
},
|
|
11
|
-
"sur_name": {
|
|
12
|
-
"type": "Text",
|
|
13
|
-
"rules": [
|
|
14
|
-
"required"
|
|
15
|
-
],
|
|
16
|
-
"ua": "Прізвище",
|
|
17
|
-
"i": "Вноситься прізвище користувача, що буде відображатися у системі"
|
|
18
|
-
},
|
|
19
|
-
"father_name": {
|
|
20
|
-
"ua": "По-батькові",
|
|
21
|
-
"type": "Text"
|
|
22
|
-
},
|
|
23
|
-
"phone": {
|
|
24
|
-
"type": "Text",
|
|
25
|
-
"mask": "+389999999999",
|
|
26
|
-
"ua": "Телефон",
|
|
27
|
-
"i": "Вноситься телефон користувача"
|
|
28
|
-
},
|
|
29
|
-
"email": {
|
|
30
|
-
"type": "Text",
|
|
31
|
-
"ua": "E-mail",
|
|
32
|
-
"i": "Вноситься електронна адреса користувача",
|
|
33
|
-
"rules": [
|
|
34
|
-
"email"
|
|
35
|
-
]
|
|
36
|
-
},
|
|
37
|
-
"login": {
|
|
38
|
-
"type": "Text",
|
|
39
|
-
"ua": "Логін",
|
|
40
|
-
"i": "Вноситься довільний логін користувача латинськими літерами, що буде використовуватися для входу в систему",
|
|
41
|
-
"rules": [
|
|
42
|
-
"required"
|
|
43
|
-
]
|
|
44
|
-
},
|
|
45
|
-
"password": {
|
|
46
|
-
"type": "Text",
|
|
47
|
-
"ua": "Пароль",
|
|
48
|
-
"rules": [
|
|
49
|
-
"required",
|
|
50
|
-
{
|
|
51
|
-
"type": "regexp",
|
|
52
|
-
"pattern": "^.{8,}$",
|
|
53
|
-
"message": "Пароль повинен бути більше 8 символів"
|
|
54
|
-
}
|
|
55
|
-
],
|
|
56
|
-
"i": "Вноситься пароль, що буде використовуватися для входу в систему (рекомендоване використання складних паролів)"
|
|
57
|
-
},
|
|
58
|
-
"avatar": {
|
|
59
|
-
"type": "File",
|
|
60
|
-
"ua": "Аватар",
|
|
61
|
-
"i": "Додається зображення, що буде відображено в системі у якості аватара цього користувача"
|
|
62
|
-
},
|
|
63
|
-
"user_type": {
|
|
64
|
-
"type": "Select",
|
|
65
|
-
"ua": "Тип користувача",
|
|
66
|
-
"i": "Вноситься тип користувача",
|
|
67
|
-
"data": "user_type"
|
|
68
|
-
},
|
|
69
|
-
"enabled": {
|
|
70
|
-
"type": "Switcher",
|
|
71
|
-
"label": "Доступ"
|
|
72
|
-
},
|
|
73
|
-
"twofa": {
|
|
74
|
-
"type": "Switcher",
|
|
75
|
-
"label": "Двофакторна авторизація"
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
SELECT content_type_id, name FROM site.content_types where type='collection'
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
select a.id, a.title, tags from data.news a
|
|
2
|
-
left join lateral(select array_agg(tag_id) as tags from site.tag_data b where a.id=b.data_id)b on 1=1
|
|
3
|
-
|
|
4
|
-
where
|
|
5
|
-
case when '{{parent}}'<> ''
|
|
6
|
-
then '{{parent}}'=any(b.tags)
|
|
7
|
-
else true
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
and status='published'
|
|
11
|
-
|
|
12
|
-
order by a.updated_at
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
select tag_id, value from site.tags order by value
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"ua": "Користувачі",
|
|
3
|
-
"key": "uid",
|
|
4
|
-
"order": "cdate desc",
|
|
5
|
-
"access": "admin",
|
|
6
|
-
"sqlColumns": "*",
|
|
7
|
-
"form": "admin.users.form",
|
|
8
|
-
"table": "admin.users",
|
|
9
|
-
"sql": [
|
|
10
|
-
{
|
|
11
|
-
"name": "social_auth_sql",
|
|
12
|
-
"sql": "select social_auth_obj,social_auth_date from admin.users_social_auth where uid=t.uid limit 1"
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
"sql": "SELECT coalesce(sur_name, '') || ' ' || coalesce(user_name, '') || ' ' || coalesce(father_name, '') as full_name FROM admin.users WHERE uid = t.uid",
|
|
16
|
-
"name": "full_name_sql"
|
|
17
|
-
}
|
|
18
|
-
],
|
|
19
|
-
"columns": [
|
|
20
|
-
{
|
|
21
|
-
"ua": "ПІБ",
|
|
22
|
-
"name": "full_name",
|
|
23
|
-
"format": "select",
|
|
24
|
-
"data": "full_name_sql"
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"ua": "Тип користувача",
|
|
28
|
-
"name": "user_type_text",
|
|
29
|
-
"format": "select",
|
|
30
|
-
"data": "user_type_text"
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
"ua": "Статус доступу",
|
|
34
|
-
"name": "enabled"
|
|
35
|
-
}
|
|
36
|
-
],
|
|
37
|
-
"filters": [
|
|
38
|
-
{
|
|
39
|
-
"label": "Тип користувача",
|
|
40
|
-
"type": "Check",
|
|
41
|
-
"name": "user_type",
|
|
42
|
-
"data": "user_type"
|
|
43
|
-
}
|
|
44
|
-
],
|
|
45
|
-
"meta": {
|
|
46
|
-
"title": "full_name",
|
|
47
|
-
"search": "user_name,user_rnokpp"
|
|
48
|
-
},
|
|
49
|
-
"actions": [
|
|
50
|
-
"edit",
|
|
51
|
-
"del",
|
|
52
|
-
"add"
|
|
53
|
-
]
|
|
54
|
-
}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"table": "site.contents",
|
|
3
|
-
"columns": [
|
|
4
|
-
{
|
|
5
|
-
"label": "Slug",
|
|
6
|
-
"name": "slug",
|
|
7
|
-
"parent": "title",
|
|
8
|
-
"required": true,
|
|
9
|
-
"type": "slug"
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
"label": "Title",
|
|
13
|
-
"name": "title",
|
|
14
|
-
"required": true,
|
|
15
|
-
"type": "text",
|
|
16
|
-
"localization": true
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"label": "Status",
|
|
20
|
-
"name": "status",
|
|
21
|
-
"type": "select",
|
|
22
|
-
"data": "content.status",
|
|
23
|
-
"options": [
|
|
24
|
-
{
|
|
25
|
-
"id": "draft",
|
|
26
|
-
"text": "Draft"
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"id": "published",
|
|
30
|
-
"text": "Published"
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
"id": "archived",
|
|
34
|
-
"text": "Archived"
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
"id": "delayPublished",
|
|
38
|
-
"text": "Delay Published"
|
|
39
|
-
}
|
|
40
|
-
],
|
|
41
|
-
"required": true
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"label": "Publish at",
|
|
45
|
-
"name": "published_at",
|
|
46
|
-
"required": true,
|
|
47
|
-
"type": "datetime"
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
"label": "Зображення",
|
|
51
|
-
"name": "main_image",
|
|
52
|
-
"type": "mediaselect"
|
|
53
|
-
}
|
|
54
|
-
],
|
|
55
|
-
"filters": [
|
|
56
|
-
{
|
|
57
|
-
"extra": false,
|
|
58
|
-
"id": "status",
|
|
59
|
-
"name": "status",
|
|
60
|
-
"title": "Статус",
|
|
61
|
-
"type": "Check",
|
|
62
|
-
"data": "content.status",
|
|
63
|
-
"ua": "Статус"
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
"extra": false,
|
|
67
|
-
"label": "Publish at",
|
|
68
|
-
"name": "published_at",
|
|
69
|
-
"type": "Date"
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
"extra": false,
|
|
73
|
-
"name": "tag_list",
|
|
74
|
-
"type": "Tags",
|
|
75
|
-
"sql": "id in (select b.data_id from site.tags a left join site.tag_data b on a.tag_id=b.tag_id where a.tag_id=any($1))",
|
|
76
|
-
"label": "Теги"
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
"extra": false,
|
|
80
|
-
"columns": "slug,title",
|
|
81
|
-
"id": "search",
|
|
82
|
-
"name": "search",
|
|
83
|
-
"placeholder": "Пошук по тексту",
|
|
84
|
-
"title": "Пошук по тексту",
|
|
85
|
-
"type": "Text"
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
"extra": false,
|
|
89
|
-
"id": "created_at",
|
|
90
|
-
"name": "created_at",
|
|
91
|
-
"title": "Дата створення",
|
|
92
|
-
"type": "Date",
|
|
93
|
-
"ua": "Дата створення"
|
|
94
|
-
}
|
|
95
|
-
]
|
|
96
|
-
}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"table": "site.contents",
|
|
3
|
-
"columns": [
|
|
4
|
-
{
|
|
5
|
-
"label": "Slug",
|
|
6
|
-
"name": "slug",
|
|
7
|
-
"parent": "title",
|
|
8
|
-
"required": true,
|
|
9
|
-
"type": "slug"
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
"label": "Title",
|
|
13
|
-
"name": "title",
|
|
14
|
-
"required": true,
|
|
15
|
-
"type": "text",
|
|
16
|
-
"localization": true
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"label": "Status",
|
|
20
|
-
"name": "status",
|
|
21
|
-
"type": "select",
|
|
22
|
-
"data": "content.status",
|
|
23
|
-
"options": [
|
|
24
|
-
{
|
|
25
|
-
"id": "draft",
|
|
26
|
-
"text": "Draft"
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"id": "published",
|
|
30
|
-
"text": "Published"
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
"id": "archived",
|
|
34
|
-
"text": "Archived"
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
"id": "delayPublished",
|
|
38
|
-
"text": "Delay Published"
|
|
39
|
-
}
|
|
40
|
-
],
|
|
41
|
-
"required": true
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"label": "Publish at",
|
|
45
|
-
"name": "published_at",
|
|
46
|
-
"required": true,
|
|
47
|
-
"type": "datetime"
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
"label": "Контент",
|
|
51
|
-
"name": "single_body",
|
|
52
|
-
"type": "richtext",
|
|
53
|
-
"localization": true
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
"name": "single_sections",
|
|
57
|
-
"label": "Секції",
|
|
58
|
-
"type": "reference",
|
|
59
|
-
"localization": true
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
"label": "Зображення",
|
|
63
|
-
"name": "main_image",
|
|
64
|
-
"type": "mediaselect"
|
|
65
|
-
}
|
|
66
|
-
],
|
|
67
|
-
"filters": [
|
|
68
|
-
{
|
|
69
|
-
"extra": false,
|
|
70
|
-
"id": "status",
|
|
71
|
-
"name": "status",
|
|
72
|
-
"title": "Статус",
|
|
73
|
-
"type": "Check",
|
|
74
|
-
"data": "content.status",
|
|
75
|
-
"ua": "Статус"
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
"extra": false,
|
|
79
|
-
"label": "Publish at",
|
|
80
|
-
"name": "published_at",
|
|
81
|
-
"type": "Date"
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
"extra": false,
|
|
85
|
-
"label": "Контент",
|
|
86
|
-
"name": "single_body",
|
|
87
|
-
"type": "Text"
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
"extra": false,
|
|
91
|
-
"name": "tag_list",
|
|
92
|
-
"type": "Tags",
|
|
93
|
-
"sql": "id in (select b.data_id from site.tags a left join site.tag_data b on a.tag_id=b.tag_id where a.tag_id=any($1))",
|
|
94
|
-
"label": "Теги"
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
"extra": false,
|
|
98
|
-
"columns": "slug,title",
|
|
99
|
-
"id": "search",
|
|
100
|
-
"name": "search",
|
|
101
|
-
"placeholder": "Пошук по тексту",
|
|
102
|
-
"title": "Пошук по тексту",
|
|
103
|
-
"type": "Text"
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
"extra": false,
|
|
107
|
-
"id": "created_at",
|
|
108
|
-
"name": "created_at",
|
|
109
|
-
"title": "Дата створення",
|
|
110
|
-
"type": "Date",
|
|
111
|
-
"ua": "Дата створення"
|
|
112
|
-
}
|
|
113
|
-
]
|
|
114
|
-
}
|