@opengis/admin 0.4.16 → 0.4.17

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 (79) hide show
  1. package/README.md +97 -97
  2. package/dist/{add-page-CuSnPcPi.js → add-page-D3JHk421.js} +1 -1
  3. package/dist/{admin-interface-D-iedgAS.js → admin-interface-Bh0X1WRG.js} +229 -210
  4. package/dist/{admin-view-BFLFL7ja.js → admin-view-BaFEZfOb.js} +1 -1
  5. package/dist/admin.js +1 -1
  6. package/dist/admin.umd.cjs +1 -1
  7. package/dist/assets/logo.svg +41 -41
  8. package/dist/{card-view-qp3cCQHr.js → card-view-B6lmjnUp.js} +1 -1
  9. package/dist/{edit-page-YQeMJOYf.js → edit-page-BRMI75iP.js} +1 -1
  10. package/dist/{import-file-EI9a0fXk.js → import-file-DanTkH8S.js} +7 -7
  11. package/dist/{profile-page-7PoRBdwC.js → profile-page-Cvt3Wmr6.js} +1 -1
  12. package/dist/style.css +1 -1
  13. package/module/settings/card/admin.accounts.table/index.yml +7 -7
  14. package/module/settings/card/admin.accounts.table/rules.hbs +18 -18
  15. package/module/settings/card/admin.accounts.table/users.hbs +13 -13
  16. package/module/settings/card/admin.routes.table/groups.hbs +11 -11
  17. package/module/settings/card/admin.routes.table/users.hbs +16 -16
  18. package/module/settings/cls/core.actions.json +17 -17
  19. package/module/settings/cls/core.scope.json +13 -13
  20. package/module/settings/cls/properties.site_status.json +13 -13
  21. package/module/settings/cls/properties.widget_status.json +13 -13
  22. package/module/settings/cls/yes_no.json +11 -11
  23. package/module/settings/form/admin.accounts.form.json +13 -13
  24. package/module/settings/form/admin.properties.form.json +15 -15
  25. package/module/settings/form/admin.roles.form.json +21 -21
  26. package/module/settings/form/admin.user_properties.form.json +15 -15
  27. package/module/settings/form/admin.user_roles_card.form.json +13 -13
  28. package/module/settings/interface/admin.properties.json +4 -4
  29. package/module/settings/interface/admin.roles.json +4 -4
  30. package/module/settings/interface/admin.routes.json +4 -4
  31. package/module/settings/interface/admin.users.json +4 -4
  32. package/module/settings/select/core.routes.sql +1 -1
  33. package/module/settings/select/core.user_mentioned.sql +1 -1
  34. package/module/settings/select/core.user_uid.sql +1 -1
  35. package/module/settings/table/admin.properties.table.json +39 -39
  36. package/module/settings/table/admin.user_properties.table.json +34 -34
  37. package/package.json +2 -1
  38. package/server/helpers/core/coalesce.js +7 -7
  39. package/server/helpers/core/select.js +48 -48
  40. package/server/helpers/core/token.js +18 -18
  41. package/server/helpers/list/buttonHelper.js +21 -21
  42. package/server/helpers/list/utils/button.js +5 -5
  43. package/server/helpers/temp/contentList.js +58 -58
  44. package/server/helpers/temp/ifCond.js +101 -101
  45. package/server/helpers/utils/button.js +5 -5
  46. package/server/helpers/utils/mdToHTML.js +17 -17
  47. package/server/plugins/access/index.mjs +6 -6
  48. package/server/plugins/cron.js +10 -10
  49. package/server/plugins/docs.js +28 -28
  50. package/server/routes/access/controllers/access.group.js +29 -29
  51. package/server/routes/access/controllers/access.group.post.js +54 -54
  52. package/server/routes/access/index.mjs +11 -11
  53. package/server/routes/access/schema.mjs +67 -67
  54. package/server/routes/calendar/controllers/calendar.data.js +125 -125
  55. package/server/routes/calendar/index.mjs +7 -7
  56. package/server/routes/notifications/controllers/readNotifications.js +18 -18
  57. package/server/routes/notifications/controllers/testEmail.js +35 -35
  58. package/server/routes/notifications/controllers/userNotifications.js +53 -53
  59. package/server/routes/notifications/hook/onWidgetSet.js +56 -56
  60. package/server/routes/notifications/index.mjs +26 -26
  61. package/server/routes/root.mjs +3 -3
  62. package/server/routes/user/controllers/user.cls.id.js +14 -14
  63. package/server/routes/user/controllers/user.cls.js +72 -72
  64. package/server/routes/user/controllers/user.info.js +17 -17
  65. package/server/routes/util/controllers/code.generator.js +89 -89
  66. package/server/templates/cls/itree.recrzone_category.json +73 -73
  67. package/server/templates/cls/test.json +9 -9
  68. package/server/templates/form/admin.user_cls.data.form.json +49 -49
  69. package/server/templates/form/admin.user_group_rel.form.json +21 -21
  70. package/server/templates/form/form-user-pass.json +10 -10
  71. package/server/templates/form/form-user_group.json +39 -39
  72. package/server/templates/form/form-users.json +156 -156
  73. package/server/templates/form/user_group_access.form.json +22 -22
  74. package/server/templates/select/account_id.json +2 -2
  75. package/server/templates/table/gis.dataset.table.json +43 -43
  76. package/server/templates/table/management.user_group.table.json +112 -112
  77. package/server/templates/table/management.users.table.json +126 -126
  78. package/server/utils/addNotification.js +21 -21
  79. package/server/utils/sendNotification.js +89 -89
@@ -1,89 +1,89 @@
1
- import { getTemplate, handlebarsSync, pgClients, getToken } from "@opengis/fastify-table/utils.js";
2
-
3
- function dayOfTheYear(date) {
4
- const start = new Date(date.getFullYear(), 0, 0);
5
- const diff = (date - start) + ((start.getTimezoneOffset() - date.getTimezoneOffset()) * 60 * 1000);
6
- const oneDay = 1000 * 60 * 60 * 24;
7
- const day = Math.floor(diff / oneDay);
8
- return day;
9
- }
10
-
11
- export default async function codeGenerator({
12
- pg = pgClients.client, params = {}, user = {}, query = {},
13
- }, reply) {
14
- const { token, column } = params;
15
- const data = query.data?.split?.(';') || [];
16
-
17
- if (!token || !column) {
18
- return reply.status(400).send('not enough params: token / column');
19
- }
20
-
21
- if (!user?.uid) {
22
- return reply.status(401).send('access restricted: token');
23
- }
24
-
25
- const tokenData = await getToken({ token, uid: user?.uid, json: 1 }) || {};
26
-
27
- if (!tokenData?.form || !tokenData?.table) {
28
- return reply.status(401).send('token not allow');
29
- }
30
-
31
- const loadTemplate = await getTemplate('form', tokenData.form);
32
- const schema = loadTemplate?.schema || loadTemplate;
33
-
34
- if (!schema) {
35
- return reply.status(404).send('form not found');
36
- }
37
-
38
- if (!schema?.[column]?.template) {
39
- return reply.status(400).send('template not specified');
40
- }
41
-
42
- const columnValue = data.find(el => el.startsWith(column))?.split('=')?.pop();
43
-
44
- const loadTable = await getTemplate('table', tokenData.table);
45
- const table = loadTable?.table || tokenData.table;
46
-
47
- if (!pg.pk?.[table]) {
48
- return reply.status(404).send('table pk not found');
49
- }
50
-
51
- const { count = 0 } = await pg.query(
52
- `select count(*) from ${table} where ${columnValue ? `${column}::text = '${columnValue}'` : 'true'} limit 1`,
53
- ).then(el => el.rows?.[0] || {});
54
-
55
- const { NUMY = 0 } = await pg.query(
56
- `select ${column} as "NUMY" from ${table} where ${column} is not null and date_part('year', cdate) = $1 order by cdate desc limit 1`,
57
- [(new Date()).getFullYear()]
58
- ).then(el => el.rows?.[0] || {});
59
-
60
- const date = new Date();
61
-
62
- const template = schema[column].template.match(/NUM[M|Y] \d/g)
63
- .reduce((acc, curr) => acc.replace(
64
- curr.startsWith('{{{') ? `{{{${curr}}}}` : `{{${curr}}}`,
65
- handlebarsSync.compile(`{{paddingNumber value padding}}`)({ padding: curr.substring(4, curr.length)?.trim?.(), value: curr.startsWith('NUMY') ? NUMY : +count + 1 })),
66
- schema[column].template
67
- );
68
- const result = handlebarsSync.compile(template)({
69
- HH: date.getHours(), // hours 24h: 14:00 = 14
70
- HH12: (date.getHours() + 24) % 12 || 12, // hours 12h: 14:00 = 2
71
- HH24: date.getHours(), // hours 24h: 14:00 = 14
72
- MI: date.getMinutes(), // minutes
73
- SS: date.getSeconds(), // seconds
74
-
75
- YYYY: date.getFullYear(), // full year: 2025
76
- YY: date.getFullYear().toString().substring(2, 4), // last 2 digits of year: 25
77
-
78
- MONTH: date.toLocaleString('en', { month: 'long' }).toUpperCase(), // month name: MARCH
79
- MON: date.toLocaleString('en', { month: 'long' }).substring(0, 3).toUpperCase(), // month name abbrev: MAR
80
- MM: date.getMonth() + 1, // month number: 1 - january, 12 - december
81
-
82
- D: date.getDay(), // day of the week: 1 - monday, 7 - sunday
83
- DD: date.getDate(), // day of the month: january 4 = 4
84
- DDD: dayOfTheYear(date), // day of the year: march 4 = 63
85
- ...data,
86
- });
87
-
88
- return reply.status(200).send(result);
89
- }
1
+ import { getTemplate, handlebarsSync, pgClients, getToken } from "@opengis/fastify-table/utils.js";
2
+
3
+ function dayOfTheYear(date) {
4
+ const start = new Date(date.getFullYear(), 0, 0);
5
+ const diff = (date - start) + ((start.getTimezoneOffset() - date.getTimezoneOffset()) * 60 * 1000);
6
+ const oneDay = 1000 * 60 * 60 * 24;
7
+ const day = Math.floor(diff / oneDay);
8
+ return day;
9
+ }
10
+
11
+ export default async function codeGenerator({
12
+ pg = pgClients.client, params = {}, user = {}, query = {},
13
+ }, reply) {
14
+ const { token, column } = params;
15
+ const data = query.data?.split?.(';') || [];
16
+
17
+ if (!token || !column) {
18
+ return reply.status(400).send('not enough params: token / column');
19
+ }
20
+
21
+ if (!user?.uid) {
22
+ return reply.status(401).send('access restricted: token');
23
+ }
24
+
25
+ const tokenData = await getToken({ token, uid: user?.uid, json: 1 }) || {};
26
+
27
+ if (!tokenData?.form || !tokenData?.table) {
28
+ return reply.status(401).send('token not allow');
29
+ }
30
+
31
+ const loadTemplate = await getTemplate('form', tokenData.form);
32
+ const schema = loadTemplate?.schema || loadTemplate;
33
+
34
+ if (!schema) {
35
+ return reply.status(404).send('form not found');
36
+ }
37
+
38
+ if (!schema?.[column]?.template) {
39
+ return reply.status(400).send('template not specified');
40
+ }
41
+
42
+ const columnValue = data.find(el => el.startsWith(column))?.split('=')?.pop();
43
+
44
+ const loadTable = await getTemplate('table', tokenData.table);
45
+ const table = loadTable?.table || tokenData.table;
46
+
47
+ if (!pg.pk?.[table]) {
48
+ return reply.status(404).send('table pk not found');
49
+ }
50
+
51
+ const { count = 0 } = await pg.query(
52
+ `select count(*) from ${table} where ${columnValue ? `${column}::text = '${columnValue}'` : 'true'} limit 1`,
53
+ ).then(el => el.rows?.[0] || {});
54
+
55
+ const { NUMY = 0 } = await pg.query(
56
+ `select ${column} as "NUMY" from ${table} where ${column} is not null and date_part('year', cdate) = $1 order by cdate desc limit 1`,
57
+ [(new Date()).getFullYear()]
58
+ ).then(el => el.rows?.[0] || {});
59
+
60
+ const date = new Date();
61
+
62
+ const template = schema[column].template.match(/NUM[M|Y] \d/g)
63
+ .reduce((acc, curr) => acc.replace(
64
+ curr.startsWith('{{{') ? `{{{${curr}}}}` : `{{${curr}}}`,
65
+ handlebarsSync.compile(`{{paddingNumber value padding}}`)({ padding: curr.substring(4, curr.length)?.trim?.(), value: curr.startsWith('NUMY') ? NUMY : +count + 1 })),
66
+ schema[column].template
67
+ );
68
+ const result = handlebarsSync.compile(template)({
69
+ HH: date.getHours(), // hours 24h: 14:00 = 14
70
+ HH12: (date.getHours() + 24) % 12 || 12, // hours 12h: 14:00 = 2
71
+ HH24: date.getHours(), // hours 24h: 14:00 = 14
72
+ MI: date.getMinutes(), // minutes
73
+ SS: date.getSeconds(), // seconds
74
+
75
+ YYYY: date.getFullYear(), // full year: 2025
76
+ YY: date.getFullYear().toString().substring(2, 4), // last 2 digits of year: 25
77
+
78
+ MONTH: date.toLocaleString('en', { month: 'long' }).toUpperCase(), // month name: MARCH
79
+ MON: date.toLocaleString('en', { month: 'long' }).substring(0, 3).toUpperCase(), // month name abbrev: MAR
80
+ MM: date.getMonth() + 1, // month number: 1 - january, 12 - december
81
+
82
+ D: date.getDay(), // day of the week: 1 - monday, 7 - sunday
83
+ DD: date.getDate(), // day of the month: january 4 = 4
84
+ DDD: dayOfTheYear(date), // day of the year: march 4 = 63
85
+ ...data,
86
+ });
87
+
88
+ return reply.status(200).send(result);
89
+ }
@@ -1,74 +1,74 @@
1
- [
2
- {
3
- "id": "12",
4
- "text": "Розділювальна смуга",
5
- "color": "#85754e",
6
- "en": "Dividing line"
7
- },
8
- {
9
- "id": "6",
10
- "text": "Бульвар",
11
- "color": "#00703c",
12
- "en": "Boulevard"
13
- },
14
- {
15
- "id": "1",
16
- "text": "Вуличні насадження",
17
- "color": "#8fbc8f",
18
- "en": "Street plantings"
19
- },
20
- {
21
- "id": "2",
22
- "text": "Парк",
23
- "color": "#a2cd5a",
24
- "en": "Park"
25
- },
26
- {
27
- "id": "3",
28
- "text": "Сад",
29
- "color": "#5e8c31",
30
- "en": "Garden"
31
- },
32
- {
33
- "id": "4",
34
- "text": "Сквер",
35
- "color": "#00ced1",
36
- "en": "Square"
37
- },
38
- {
39
- "id": "9",
40
- "text": "Рекреаційна зона",
41
- "color": "#e1a95f",
42
- "en": "Recreational zone"
43
- },
44
- {
45
- "id": "10",
46
- "text": "Санітарно-захисна зона",
47
- "color": "#6e7b8b",
48
- "en": "Sanitary protection zone"
49
- },
50
- {
51
- "id": "11",
52
- "text": "Зелені насадження прибудинкової території",
53
- "color": "#ace1af",
54
- "en": "Green plantations in local areas"
55
- },
56
- {
57
- "id": "5",
58
- "text": "Прибережні зелені насадження",
59
- "color": "#698b69",
60
- "en": "Coastal green plantations"
61
- },
62
- {
63
- "id": "7",
64
- "text": "Лісопарк",
65
- "color": "#6e8b3d",
66
- "en": "Forest park"
67
- },
68
- {
69
- "id": "8",
70
- "text": "Міський ліс",
71
- "color": "#4a5d23",
72
- "en": "Urban forest"
73
- }
1
+ [
2
+ {
3
+ "id": "12",
4
+ "text": "Розділювальна смуга",
5
+ "color": "#85754e",
6
+ "en": "Dividing line"
7
+ },
8
+ {
9
+ "id": "6",
10
+ "text": "Бульвар",
11
+ "color": "#00703c",
12
+ "en": "Boulevard"
13
+ },
14
+ {
15
+ "id": "1",
16
+ "text": "Вуличні насадження",
17
+ "color": "#8fbc8f",
18
+ "en": "Street plantings"
19
+ },
20
+ {
21
+ "id": "2",
22
+ "text": "Парк",
23
+ "color": "#a2cd5a",
24
+ "en": "Park"
25
+ },
26
+ {
27
+ "id": "3",
28
+ "text": "Сад",
29
+ "color": "#5e8c31",
30
+ "en": "Garden"
31
+ },
32
+ {
33
+ "id": "4",
34
+ "text": "Сквер",
35
+ "color": "#00ced1",
36
+ "en": "Square"
37
+ },
38
+ {
39
+ "id": "9",
40
+ "text": "Рекреаційна зона",
41
+ "color": "#e1a95f",
42
+ "en": "Recreational zone"
43
+ },
44
+ {
45
+ "id": "10",
46
+ "text": "Санітарно-захисна зона",
47
+ "color": "#6e7b8b",
48
+ "en": "Sanitary protection zone"
49
+ },
50
+ {
51
+ "id": "11",
52
+ "text": "Зелені насадження прибудинкової території",
53
+ "color": "#ace1af",
54
+ "en": "Green plantations in local areas"
55
+ },
56
+ {
57
+ "id": "5",
58
+ "text": "Прибережні зелені насадження",
59
+ "color": "#698b69",
60
+ "en": "Coastal green plantations"
61
+ },
62
+ {
63
+ "id": "7",
64
+ "text": "Лісопарк",
65
+ "color": "#6e8b3d",
66
+ "en": "Forest park"
67
+ },
68
+ {
69
+ "id": "8",
70
+ "text": "Міський ліс",
71
+ "color": "#4a5d23",
72
+ "en": "Urban forest"
73
+ }
74
74
  ]
@@ -1,10 +1,10 @@
1
- [
2
- {
3
- "id": 1,
4
- "text": "test"
5
- },
6
- {
7
- "id": 2,
8
- "text": "test2"
9
- }
1
+ [
2
+ {
3
+ "id": 1,
4
+ "text": "test"
5
+ },
6
+ {
7
+ "id": 2,
8
+ "text": "test2"
9
+ }
10
10
  ]
@@ -1,50 +1,50 @@
1
- {
2
- "label_style": "vertical",
3
- "schema": {
4
- "code": {
5
- "type": "Text",
6
- "ua": "Код",
7
- "ru": "Код",
8
- "en": "Code",
9
- "placeholder": {
10
- "ua": "Код",
11
- "ru": "Код",
12
- "en": "Code"
13
- },
14
- "validators": [
15
- "required"
16
- ],
17
- "col": 6
18
- },
19
- "name": {
20
- "type": "Text",
21
- "ua": "Назва",
22
- "ru": "Название",
23
- "en": "Name",
24
- "placeholder": {
25
- "ua": "Назва",
26
- "ru": "Название",
27
- "en": "Name"
28
- },
29
- "validators": [
30
- "required"
31
- ],
32
- "col": 6
33
- },
34
- "icon": {
35
- "type": "File",
36
- "multi": false,
37
- "ua": "Іконка",
38
- "ru": "Иконка",
39
- "en": "Icon",
40
- "col": 6
41
- },
42
- "color": {
43
- "type": "ColorPicker",
44
- "ua": "Колір",
45
- "ru": "Цвет",
46
- "en": "Color",
47
- "col": 6
48
- }
49
- }
1
+ {
2
+ "label_style": "vertical",
3
+ "schema": {
4
+ "code": {
5
+ "type": "Text",
6
+ "ua": "Код",
7
+ "ru": "Код",
8
+ "en": "Code",
9
+ "placeholder": {
10
+ "ua": "Код",
11
+ "ru": "Код",
12
+ "en": "Code"
13
+ },
14
+ "validators": [
15
+ "required"
16
+ ],
17
+ "col": 6
18
+ },
19
+ "name": {
20
+ "type": "Text",
21
+ "ua": "Назва",
22
+ "ru": "Название",
23
+ "en": "Name",
24
+ "placeholder": {
25
+ "ua": "Назва",
26
+ "ru": "Название",
27
+ "en": "Name"
28
+ },
29
+ "validators": [
30
+ "required"
31
+ ],
32
+ "col": 6
33
+ },
34
+ "icon": {
35
+ "type": "File",
36
+ "multi": false,
37
+ "ua": "Іконка",
38
+ "ru": "Иконка",
39
+ "en": "Icon",
40
+ "col": 6
41
+ },
42
+ "color": {
43
+ "type": "ColorPicker",
44
+ "ua": "Колір",
45
+ "ru": "Цвет",
46
+ "en": "Color",
47
+ "col": 6
48
+ }
49
+ }
50
50
  }
@@ -1,22 +1,22 @@
1
- {
2
- "schema": {
3
- "user_uid": {
4
- "type": "Autocomplete",
5
- "data": "user_id",
6
- "ua": "Користувач",
7
- "validators": [
8
- "required"
9
- ]
10
- },
11
- "user_access": {
12
- "type": "Select2",
13
- "data": "user_access",
14
- "placeholder": "Згідно налаштувань інтерфейсів",
15
- "ua": "Доступ"
16
- },
17
- "expiration": {
18
- "type": "DatePicker",
19
- "ua": "Закінчення терміну дії доступу до групи"
20
- }
21
- }
1
+ {
2
+ "schema": {
3
+ "user_uid": {
4
+ "type": "Autocomplete",
5
+ "data": "user_id",
6
+ "ua": "Користувач",
7
+ "validators": [
8
+ "required"
9
+ ]
10
+ },
11
+ "user_access": {
12
+ "type": "Select2",
13
+ "data": "user_access",
14
+ "placeholder": "Згідно налаштувань інтерфейсів",
15
+ "ua": "Доступ"
16
+ },
17
+ "expiration": {
18
+ "type": "DatePicker",
19
+ "ua": "Закінчення терміну дії доступу до групи"
20
+ }
21
+ }
22
22
  }
@@ -1,11 +1,11 @@
1
- {
2
- "login":{"type":"Text","ua":"Логін","ru":"Логин"},
3
- "password":{"type":"Password","ua":"Пароль","ru":"Пароль","validators": [
4
- {
5
- "type": "regexp",
6
- "regexp": "^.{8,}$",
7
- "flags": "gm",
8
- "message": "Пароль повинен бути більше 8 символів"
9
- }
10
- ]}
1
+ {
2
+ "login":{"type":"Text","ua":"Логін","ru":"Логин"},
3
+ "password":{"type":"Password","ua":"Пароль","ru":"Пароль","validators": [
4
+ {
5
+ "type": "regexp",
6
+ "regexp": "^.{8,}$",
7
+ "flags": "gm",
8
+ "message": "Пароль повинен бути більше 8 символів"
9
+ }
10
+ ]}
11
11
  }
@@ -1,40 +1,40 @@
1
- {
2
- "schema": {
3
- "group_name": {
4
- "type": "Text",
5
- "data": "customer_id",
6
- "ua": "Назва",
7
- "i": "Вноситься загальна назва групи доступу українською мовою",
8
- "ru": "Название"
9
- },
10
- "info": {
11
- "type": "Text",
12
- "ua": "Опис",
13
- "i": "Додається текстовий опис групи доступу, що буде збережений в системі",
14
- "ru": "Описание"
15
- },
16
- "license": {
17
- "type": "Select2",
18
- "data": "license",
19
- "ua": "Ліцензія",
20
- "ru": "Лицензия",
21
- "default": "0"
22
- },
23
- "product_code": {
24
- "type": "Select2",
25
- "data": "product_code",
26
- "ua": "Код продукту",
27
- "ru": "Код продукта",
28
- "default": "0"
29
- },
30
- "allow_ip": {
31
- "type": "Text",
32
- "ua": "IP адреси",
33
- "ru": "IP адреса"
34
- },
35
- "permission.edit_everything": {
36
- "type": "Switcher",
37
- "ua": "Редагувати не тільки власні записи"
38
- }
39
- }
1
+ {
2
+ "schema": {
3
+ "group_name": {
4
+ "type": "Text",
5
+ "data": "customer_id",
6
+ "ua": "Назва",
7
+ "i": "Вноситься загальна назва групи доступу українською мовою",
8
+ "ru": "Название"
9
+ },
10
+ "info": {
11
+ "type": "Text",
12
+ "ua": "Опис",
13
+ "i": "Додається текстовий опис групи доступу, що буде збережений в системі",
14
+ "ru": "Описание"
15
+ },
16
+ "license": {
17
+ "type": "Select2",
18
+ "data": "license",
19
+ "ua": "Ліцензія",
20
+ "ru": "Лицензия",
21
+ "default": "0"
22
+ },
23
+ "product_code": {
24
+ "type": "Select2",
25
+ "data": "product_code",
26
+ "ua": "Код продукту",
27
+ "ru": "Код продукта",
28
+ "default": "0"
29
+ },
30
+ "allow_ip": {
31
+ "type": "Text",
32
+ "ua": "IP адреси",
33
+ "ru": "IP адреса"
34
+ },
35
+ "permission.edit_everything": {
36
+ "type": "Switcher",
37
+ "ua": "Редагувати не тільки власні записи"
38
+ }
39
+ }
40
40
  }