@opengis/cms 0.0.60 → 0.0.61

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 (43) hide show
  1. package/README.md +4 -4
  2. package/dist/{ArticlesPage-BjYzvTWM.js → ArticlesPage-CFjE_cw_.js} +3 -3
  3. package/dist/{CollectionsBreadcrumb-HePNJb-d.js → CollectionsBreadcrumb-BCxeRikP.js} +1 -1
  4. package/dist/CollectionsBreadcrumb.vue_vue_type_script_setup_true_lang-umRzB5mY.js +53 -0
  5. package/dist/{Dashboard-CXkg_pk8.js → Dashboard-C1eGscNd.js} +132 -132
  6. package/dist/{EditCollectionPage-BycuD920.js → EditCollectionPage-3Q57ptN3.js} +2 -2
  7. package/dist/{MenuAddPage-QTnwCoGh.js → MenuAddPage-D-p3gFgm.js} +1 -1
  8. package/dist/{MenuBody-Bi0ONVZf.js → MenuBody-rN5j4YBu.js} +2 -2
  9. package/dist/{MenuItemPage-B7Y9KFyb.js → MenuItemPage-BoJw885D.js} +3 -3
  10. package/dist/{MenuList-BLIpeqSd.js → MenuList-DFEBS0NB.js} +53 -53
  11. package/dist/{MenuPage-3W6jZ15H.js → MenuPage-BCZB_S8j.js} +1 -1
  12. package/dist/{MenuWrapper-OrOv6sOb.js → MenuWrapper-AZ_8s-zd.js} +1 -1
  13. package/dist/{MonacoEditor-ByPT8pnv.js → MonacoEditor-Db-3Jc3E.js} +1 -1
  14. package/dist/MonacoEditor.vue_vue_type_script_setup_true_lang-B1DrxmQX.js +84 -0
  15. package/dist/{UniversalTable-GBd_pStq.js → UniversalTable-CzqPG-tY.js} +80 -80
  16. package/dist/{UniversalTablePagination-Dw2hc0nc.js → UniversalTablePagination-4gL47A7I.js} +46 -46
  17. package/dist/{contentForm-yMn63kza.js → contentForm-CLStrfSg.js} +3 -6
  18. package/dist/index.js +5 -5
  19. package/dist/{vs-builder-monaco-Cw-f19gc.js → vs-builder-monaco-B3Jj0V31.js} +1 -1
  20. package/package.json +69 -69
  21. package/server/migrations/fixes.sql +5 -2
  22. package/server/migrations/site.sql +4 -3
  23. package/server/routes/cms/controllers/deleteContent.js +7 -7
  24. package/server/routes/cms/controllers/getContent.js +6 -6
  25. package/server/routes/cms/controllers/getContentBySlug.js +13 -13
  26. package/server/routes/cms/controllers/getPermissions.js +15 -15
  27. package/server/routes/cms/controllers/insertContent.js +28 -19
  28. package/server/routes/cms/controllers/setPermissions.js +49 -49
  29. package/server/routes/cms/controllers/updateContent.js +12 -47
  30. package/server/routes/cms/utils/getCollection.js +1 -1
  31. package/server/routes/cms/utils/getSingle.js +1 -1
  32. package/server/routes/cms/utils/requestTranslation.js +28 -6
  33. package/server/routes/cms/utils/updateLocalization.js +1 -6
  34. package/server/routes/cmsSpace/controllers/deleteSpace.js +1 -0
  35. package/server/routes/cmsSpace/controllers/getSpaces.js +1 -0
  36. package/server/routes/cmsSpace/controllers/insertSpace.js +1 -0
  37. package/server/routes/cmsSpace/controllers/updateSpace.js +1 -0
  38. package/server/routes/contentType/controllers/contentTypeList.js +4 -11
  39. package/server/routes/contentType/controllers/editContentType.js +7 -25
  40. package/server/routes/contentType/controllers/getContentType.js +5 -13
  41. package/server/templates/select/core.user_mentioned.sql +1 -1
  42. package/dist/CollectionsBreadcrumb.vue_vue_type_script_setup_true_lang-BJh-tjam.js +0 -53
  43. package/dist/MonacoEditor.vue_vue_type_script_setup_true_lang-C8cip9Ci.js +0 -84
@@ -1,6 +1,6 @@
1
- import { defineComponent as f, mergeModels as x, useModel as w, computed as h, openBlock as r, createElementBlock as d, createElementVNode as t, toDisplayString as n, createTextVNode as u, createVNode as b, unref as p, Fragment as g, renderList as k, normalizeClass as y } from "vue";
2
- import { ChevronLeft as _, ChevronRight as $ } from "lucide-vue-next";
3
- const M = { class: "flex items-center justify-between px-6 py-4 border-t border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-800" }, C = { class: "flex justify-between flex-1 sm:hidden" }, j = { class: "relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50" }, P = { class: "relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50" }, N = { class: "hidden sm:flex-1 sm:flex sm:items-center sm:justify-between" }, T = { class: "text-sm text-slate-600 dark:text-slate-400" }, V = { class: "font-medium text-slate-800 dark:text-slate-100" }, z = { class: "font-medium text-slate-800 dark:text-slate-100" }, B = {
1
+ import { defineComponent as f, mergeModels as p, useModel as w, computed as h, openBlock as d, createElementBlock as c, createElementVNode as e, toDisplayString as n, createTextVNode as u, createVNode as b, unref as g, Fragment as v, renderList as k, normalizeClass as y } from "vue";
2
+ import { ChevronLeft as $, ChevronRight as M } from "lucide-vue-next";
3
+ const C = { class: "flex items-center justify-between px-6 py-4 border-t border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-800" }, _ = { class: "flex justify-between flex-1 sm:hidden" }, j = { class: "relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50" }, P = { class: "relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50" }, N = { class: "hidden sm:flex-1 sm:flex sm:items-center sm:justify-between" }, T = { class: "text-sm text-slate-600 dark:text-slate-400" }, V = { class: "font-medium text-slate-800 dark:text-slate-100" }, z = { class: "font-medium text-slate-800 dark:text-slate-100" }, B = {
4
4
  class: "relative z-0 inline-flex space-x-2 rounded-md shadow-sm",
5
5
  "aria-label": "Pagination"
6
6
  }, E = ["disabled"], L = { class: "sr-only" }, S = { class: "space-x-1" }, D = {
@@ -8,7 +8,7 @@ const M = { class: "flex items-center justify-between px-6 py-4 border-t border-
8
8
  class: "px-2 py-2 text-gray-400"
9
9
  }, F = ["onClick"], R = ["disabled"], U = { class: "sr-only" }, G = /* @__PURE__ */ f({
10
10
  __name: "UniversalTablePagination",
11
- props: /* @__PURE__ */ x({
11
+ props: /* @__PURE__ */ p({
12
12
  total: {},
13
13
  count: {},
14
14
  limit: {}
@@ -17,66 +17,66 @@ const M = { class: "flex items-center justify-between px-6 py-4 border-t border-
17
17
  pageModifiers: {}
18
18
  }),
19
19
  emits: ["update:page"],
20
- setup(c) {
21
- const s = w(c, "page"), i = h(() => Math.ceil(c.total / c.limit)), v = h(() => {
22
- const a = [];
23
- if (i.value <= 4) {
24
- for (let l = 1; l <= i.value; l++)
25
- a.push(l);
26
- return a;
20
+ setup(a) {
21
+ const t = w(a, "page"), r = h(() => Math.ceil(a.total / a.limit)), x = h(() => {
22
+ const s = [];
23
+ if (r.value <= 4) {
24
+ for (let i = 1; i <= r.value; i++)
25
+ s.push(i);
26
+ return s;
27
27
  }
28
- const o = Math.max(2, s.value - 2), m = Math.min(i.value - 1, s.value + 2);
29
- a.push(1), o > 2 && a.push("ellipsis");
30
- for (let l = o; l <= m; l++)
31
- a.push(l);
32
- return m < i.value - 1 && a.push("ellipsis"), a.push(i.value), a;
28
+ const o = Math.max(2, t.value - 2), m = Math.min(r.value - 1, t.value + 2);
29
+ s.push(1), o > 2 && s.push("ellipsis");
30
+ for (let i = o; i <= m; i++)
31
+ s.push(i);
32
+ return m < r.value - 1 && s.push("ellipsis"), s.push(r.value), s;
33
33
  });
34
- return (e, a) => (r(), d("div", M, [
35
- t("div", C, [
36
- t("button", j, n(e.$t("cms.common.pagination.previous")), 1),
37
- t("button", P, n(e.$t("cms.common.pagination.next")), 1)
34
+ return (l, s) => (d(), c("div", C, [
35
+ e("div", _, [
36
+ e("button", j, n(l.$t("cms.common.pagination.previous")), 1),
37
+ e("button", P, n(l.$t("cms.common.pagination.next")), 1)
38
38
  ]),
39
- t("div", N, [
40
- t("div", null, [
41
- t("p", T, [
42
- u(n(e.$t("cms.common.pagination.showing")) + " ", 1),
43
- t("span", V, n(e.count), 1),
44
- u(" " + n(e.$t("cms.common.pagination.of")) + " ", 1),
45
- t("span", z, n(e.total), 1),
46
- u(" " + n(e.$t("cms.common.pagination.results")), 1)
39
+ e("div", N, [
40
+ e("div", null, [
41
+ e("p", T, [
42
+ u(n(l.$t("cms.common.pagination.showing")) + " ", 1),
43
+ e("span", V, n(a.count), 1),
44
+ u(" " + n(l.$t("cms.common.pagination.of")) + " ", 1),
45
+ e("span", z, n(a.total), 1),
46
+ u(" " + n(l.$t("cms.common.pagination.results")), 1)
47
47
  ])
48
48
  ]),
49
- t("div", null, [
50
- t("nav", B, [
51
- t("button", {
52
- onClick: a[0] || (a[0] = (o) => s.value = s.value > 1 ? s.value - 1 : 1),
53
- disabled: s.value === 1,
49
+ e("div", null, [
50
+ e("nav", B, [
51
+ e("button", {
52
+ onClick: s[0] || (s[0] = (o) => t.value = t.value > 1 ? t.value - 1 : 1),
53
+ disabled: t.value === 1,
54
54
  class: "inline-flex items-center justify-center whitespace-nowrap font-medium transition-colors border shadow-sm rounded-md text-xs h-8 w-8 p-0 bg-white border-slate-300 text-slate-600 disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed hover:text-accent-foreground hover:bg-slate-50 dark:bg-slate-700 dark:border-slate-600 dark:text-slate-300 dark:hover:bg-slate-600"
55
55
  }, [
56
- t("span", L, n(e.$t("cms.common.pagination.previous")), 1),
57
- b(p(_), { class: "w-5 h-5" })
56
+ e("span", L, n(l.$t("cms.common.pagination.previous")), 1),
57
+ b(g($), { class: "w-5 h-5" })
58
58
  ], 8, E),
59
- t("div", S, [
60
- (r(!0), d(g, null, k(v.value, (o, m) => (r(), d(g, {
59
+ e("div", S, [
60
+ (d(!0), c(v, null, k(x.value, (o, m) => (d(), c(v, {
61
61
  key: o + "-" + m
62
62
  }, [
63
- o === "ellipsis" ? (r(), d("span", D, "...")) : (r(), d("button", {
63
+ o === "ellipsis" ? (d(), c("span", D, "...")) : (d(), c("button", {
64
64
  key: 1,
65
- onClick: (l) => s.value = o,
65
+ onClick: (i) => t.value = o,
66
66
  class: y(["inline-flex items-center justify-center whitespace-nowrap font-medium transition-colors h-8 w-8 p-0 text-sm rounded-md", {
67
- "border shadow-sm hover:text-accent-foreground bg-white dark:bg-slate-700 border-slate-300 dark:border-slate-600 text-slate-600 dark:text-slate-300 hover:border-blue-600 hover:bg-slate-50 dark:hover:bg-slate-600": o !== s.value,
68
- "shadow bg-blue-600 hover:bg-blue-700 text-white border-blue-600": o === s.value
67
+ "border shadow-sm hover:text-accent-foreground bg-white dark:bg-slate-700 border-slate-300 dark:border-slate-600 text-slate-600 dark:text-slate-300 hover:border-blue-600 hover:bg-slate-50 dark:hover:bg-slate-600": o !== t.value,
68
+ "shadow bg-blue-600 hover:bg-blue-700 text-white border-blue-600": o === t.value
69
69
  }])
70
70
  }, n(o), 11, F))
71
71
  ], 64))), 128))
72
72
  ]),
73
- t("button", {
74
- onClick: a[1] || (a[1] = (o) => s.value = s.value < Math.ceil(e.total / e.limit) ? s.value + 1 : Math.ceil(e.total / e.limit)),
75
- disabled: s.value === Math.ceil(e.total / e.limit),
73
+ e("button", {
74
+ onClick: s[1] || (s[1] = (o) => t.value = t.value < Math.ceil(a.total / a.limit) ? t.value + 1 : Math.ceil(a.total / a.limit)),
75
+ disabled: t.value === Math.ceil(a.total / a.limit),
76
76
  class: "inline-flex items-center justify-center whitespace-nowrap font-medium transition-colors border shadow-sm rounded-md text-xs h-8 w-8 p-0 bg-white border-slate-300 text-slate-600 disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed hover:text-accent-foreground hover:bg-slate-50 dark:bg-slate-700 dark:border-slate-600 dark:text-slate-300 dark:hover:bg-slate-600"
77
77
  }, [
78
- t("span", U, n(e.$t("cms.common.pagination.next")), 1),
79
- b(p($), { class: "w-5 h-5" })
78
+ e("span", U, n(l.$t("cms.common.pagination.next")), 1),
79
+ b(g(M), { class: "w-5 h-5" })
80
80
  ], 8, R)
81
81
  ])
82
82
  ])
@@ -66,7 +66,7 @@ const Xe = [
66
66
  ), be = h(
67
67
  () => import("./VsPreview-DwETkOpb.js")
68
68
  ), he = h(
69
- () => import("./CollectionsBreadcrumb-HePNJb-d.js")
69
+ () => import("./CollectionsBreadcrumb-BCxeRikP.js")
70
70
  );
71
71
  x["vs-input-custom-datatable"] = fe, x["vs-input-reference"] = de, x["vs-input-texteditor"] = me, x["vs-input-mediaselect"] = E, x["vs-input-file"] = E, x["vs-input-image"] = E, x["vs-input-richtext-md"] = pe, x["vs-input-integer"] = ve, x["vs-input-relation-link"] = ye;
72
72
  const { t: r, locale: G } = Qe(), V = Ue(), d = Oe(), Q = le("cms.menu", null) || le("menu", p([])), _ = p([]), D = p({}), W = p({}), I = p({}), N = p(""), M = p(!0), R = Be(), U = R == null ? void 0 : R.appContext, we = (U == null ? void 0 : U.config.globalProperties) || {}, X = Ee(we, "$settings"), B = m(() => {
@@ -130,10 +130,7 @@ const Xe = [
130
130
  title: "",
131
131
  status: "draft"
132
132
  }), J = p(null), L = p(""), F = m(
133
- () => {
134
- var e;
135
- return (((e = i.value) == null ? void 0 : e.type) || J.value) === "single";
136
- }
133
+ () => J.value === "single"
137
134
  ), Te = m(() => {
138
135
  const e = [
139
136
  { id: "content", name: r("cms.builder.content") },
@@ -163,7 +160,7 @@ const Xe = [
163
160
  var s, c, l;
164
161
  const e = ((s = d.params) == null ? void 0 : s.collection) || ((c = d.params) == null ? void 0 : c.id), t = (l = d.params) == null ? void 0 : l.id, o = Se.value, a = o === ee.value, n = [
165
162
  {
166
- label: F ? r("cms.navigation.singletons") : ee.value,
163
+ label: F.value ? r("cms.navigation.singletons") : ee.value,
167
164
  route: `collections/${e}`
168
165
  }
169
166
  ];
package/dist/index.js CHANGED
@@ -3,12 +3,12 @@ import { useRoute as $, routeLocationKey as K } from "vue-router";
3
3
  const O = "menu", B = (s, c, a) => {
4
4
  const o = s == null ? void 0 : s.trim(), l = a == null ? void 0 : a.trim();
5
5
  return o ? o === O ? c ? c === "create" ? { type: "createMenu", collection: o } : { type: "editMenu", collection: o, id: c } : { type: "menu", collection: o } : l === "edit" && c ? { type: "editCollection", collection: o, id: c } : c === "edit" ? { type: "editCollection", collection: o } : c ? c === "create" ? { type: "createArticle", collection: o } : { type: "editArticle", collection: o, id: c } : { type: "articles", collection: o } : { type: "collections" };
6
- }, R = u(() => import("./CollectionsPage-DHfPNql6.js")), L = u(() => import("./ArticlesPage-BjYzvTWM.js")), C = u(() => import("./contentForm-yMn63kza.js")), N = u(() => import("./EditCollectionPage-BycuD920.js")), W = u(
7
- () => import("./MenuPage-3W6jZ15H.js")
6
+ }, R = u(() => import("./CollectionsPage-DHfPNql6.js")), L = u(() => import("./ArticlesPage-CFjE_cw_.js")), C = u(() => import("./contentForm-CLStrfSg.js")), N = u(() => import("./EditCollectionPage-3Q57ptN3.js")), W = u(
7
+ () => import("./MenuPage-BCZB_S8j.js")
8
8
  ), j = u(
9
- () => import("./MenuItemPage-B7Y9KFyb.js")
9
+ () => import("./MenuItemPage-BoJw885D.js")
10
10
  ), F = u(
11
- () => import("./MenuAddPage-QTnwCoGh.js")
11
+ () => import("./MenuAddPage-D-p3gFgm.js")
12
12
  ), S = {
13
13
  collections: R,
14
14
  articles: L,
@@ -96,7 +96,7 @@ const O = "menu", B = (s, c, a) => {
96
96
  });
97
97
  return M(K, b), (e, n) => v.value ? (g(), k(x(v.value), { key: w.value })) : (g(), E("div", V, D(e.$t("cms.navigation.collections")), 1));
98
98
  }
99
- }), H = u(() => import("./Dashboard-CXkg_pk8.js")), J = u(() => import("./MenuWrapper-OrOv6sOb.js")), Q = q;
99
+ }), H = u(() => import("./Dashboard-C1eGscNd.js")), J = u(() => import("./MenuWrapper-AZ_8s-zd.js")), Q = q;
100
100
  export {
101
101
  Q as Content,
102
102
  H as Dashboard,
@@ -1,5 +1,5 @@
1
1
  import { ref as l, useModel as m, onMounted as u, openBlock as r, createElementBlock as d, createVNode as i, createCommentVNode as s } from "vue";
2
- import { _ as c } from "./MonacoEditor.vue_vue_type_script_setup_true_lang-C8cip9Ci.js";
2
+ import { _ as c } from "./MonacoEditor.vue_vue_type_script_setup_true_lang-B1DrxmQX.js";
3
3
  const g = {
4
4
  __name: "vs-builder-monaco",
5
5
  props: {
package/package.json CHANGED
@@ -1,69 +1,69 @@
1
- {
2
- "name": "@opengis/cms",
3
- "version": "0.0.60",
4
- "description": "cms",
5
- "type": "module",
6
- "author": "Softpro",
7
- "main": "./dist/index.js",
8
- "types": "./dist/index.d.ts",
9
- "license": "EULA",
10
- "files": [
11
- "module",
12
- "locales",
13
- "dist",
14
- "server",
15
- "plugin.js",
16
- "utils.js",
17
- "utils.d.ts",
18
- "input-types.json"
19
- ],
20
- "scripts": {
21
- "patch": "npm version patch && git push && npm publish",
22
- "test": "node --test test/**/*.test.js",
23
- "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
24
- "dev": "NODE_ENV=dev bun --env-file=.env.ip server ",
25
- "admin": "vite admin",
26
- "build": "vite build admin",
27
- "build:lib": "vue-tsc -p tsconfig.build.json --noEmit && vite build && npm run build:types",
28
- "build:types": "vue-tsc -p tsconfig.types.json",
29
- "proxy": "vite dev admin",
30
- "start": "bun --env-file=.env.ip server",
31
- "prod": "NODE_ENV=production bun --env-file=.env.ip server ",
32
- "ip": "bun --env-file=.env.ip server",
33
- "lemken": "bun --env-file=.env.local-lemken server",
34
- "demo": "node --env-file=.env.demo --env-file=.env server",
35
- "i18n:sync": "node i18n-sync.cjs",
36
- "prepublishOnly": "bun build:lib",
37
- "softpro": "bun --env-file=.env.softpro server",
38
- "softpro1": "NODE_ENV=production bun --env-file=.env.prod-softpro.local server"
39
- },
40
- "resolutions": {
41
- "rollup": "4.30.0"
42
- },
43
- "devDependencies": {
44
- "@fastify/compress": "^8.1.0",
45
- "@opengis/core": "^0.0.30",
46
- "@opengis/fastify-table": "^2.0.147",
47
- "@opengis/filter": "^0.1.31",
48
- "@opengis/form": "^0.0.121",
49
- "@tailwindcss/typography": "0.5.10",
50
- "@tsconfig/node22": "^22.0.2",
51
- "@vitejs/plugin-vue": "5.0.4",
52
- "@vueuse/head": "2.0.0",
53
- "autoprefixer": "10.4.18",
54
- "eslint": "8.49.0",
55
- "js-yaml": "^4.1.0",
56
- "lucide-vue-next": "^0.564.0",
57
- "postcss": "8.4.35",
58
- "sass": "^1.92.1",
59
- "tailwindcss": "3.4.1",
60
- "typescript": "~5.8.0",
61
- "vite": "5.1.4",
62
- "vitest": "3.2.4",
63
- "vue": "^3.5.17",
64
- "vue-i18n": "11.1.5",
65
- "vue-router": "4.4.3",
66
- "vue-tsc": "^2.2.10",
67
- "vuedraggable": "4.1.0"
68
- }
69
- }
1
+ {
2
+ "name": "@opengis/cms",
3
+ "version": "0.0.61",
4
+ "description": "cms",
5
+ "type": "module",
6
+ "author": "Softpro",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "license": "EULA",
10
+ "files": [
11
+ "module",
12
+ "locales",
13
+ "dist",
14
+ "server",
15
+ "plugin.js",
16
+ "utils.js",
17
+ "utils.d.ts",
18
+ "input-types.json"
19
+ ],
20
+ "scripts": {
21
+ "patch": "npm version patch && git push && npm publish",
22
+ "test": "node --test test/**/*.test.js",
23
+ "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
24
+ "dev": "NODE_ENV=dev bun --env-file=.env.ip server ",
25
+ "admin": "vite admin",
26
+ "build": "vite build admin",
27
+ "build:lib": "vue-tsc -p tsconfig.build.json --noEmit && vite build && npm run build:types",
28
+ "build:types": "vue-tsc -p tsconfig.types.json",
29
+ "proxy": "vite dev admin",
30
+ "start": "bun --env-file=.env.ip server",
31
+ "prod": "NODE_ENV=production bun --env-file=.env.ip server ",
32
+ "ip": "bun --env-file=.env.ip server",
33
+ "lemken": "bun --env-file=.env.local-lemken server",
34
+ "demo": "node --env-file=.env.demo --env-file=.env server",
35
+ "i18n:sync": "node i18n-sync.cjs",
36
+ "prepublishOnly": "bun build:lib",
37
+ "softpro": "bun --env-file=.env.softpro server",
38
+ "softpro1": "NODE_ENV=production bun --env-file=.env.prod-softpro.local server"
39
+ },
40
+ "resolutions": {
41
+ "rollup": "4.30.0"
42
+ },
43
+ "devDependencies": {
44
+ "@fastify/compress": "^8.1.0",
45
+ "@opengis/core": "^0.0.30",
46
+ "@opengis/fastify-table": "^2.0.147",
47
+ "@opengis/filter": "^0.1.31",
48
+ "@opengis/form": "^0.0.121",
49
+ "@tailwindcss/typography": "0.5.10",
50
+ "@tsconfig/node22": "^22.0.2",
51
+ "@vitejs/plugin-vue": "5.0.4",
52
+ "@vueuse/head": "2.0.0",
53
+ "autoprefixer": "10.4.18",
54
+ "eslint": "8.49.0",
55
+ "js-yaml": "^4.1.0",
56
+ "lucide-vue-next": "^0.564.0",
57
+ "postcss": "8.4.35",
58
+ "sass": "^1.92.1",
59
+ "tailwindcss": "3.4.1",
60
+ "typescript": "~5.8.0",
61
+ "vite": "5.1.4",
62
+ "vitest": "3.2.4",
63
+ "vue": "^3.5.17",
64
+ "vue-i18n": "11.1.5",
65
+ "vue-router": "4.4.3",
66
+ "vue-tsc": "^2.2.10",
67
+ "vuedraggable": "4.1.0"
68
+ }
69
+ }
@@ -1,10 +1,13 @@
1
1
  create schema if not exists site;
2
2
 
3
- ALTER TABLE if exists site.spaces add column if not exists locales text[];
3
+ /*ALTER TABLE if exists site.spaces add column if not exists locales text[];
4
4
  ALTER TABLE IF exists site.spaces add column if not exists default_locale text;
5
5
  ALTER TABLE if exists site.spaces alter column default_locale set default 'ua';
6
6
  update site.spaces set default_locale = 'ua' where default_locale is null;
7
- ALTER TABLE if exists site.spaces alter column default_locale set not null;
7
+ ALTER TABLE if exists site.spaces alter column default_locale set not null;*/
8
+ -- uncomment after a while or leave old data as is
9
+ /* --- alter table site.contents drop column if exists space_id;
10
+ drop table if exists site.spaces cascade; */
8
11
 
9
12
  ALTER TABLE if exists site.media ADD COLUMN IF NOT EXISTS subdir TEXT;
10
13
  COMMENT ON COLUMN site.media.subdir is 'Піддиректорія';
@@ -271,7 +271,7 @@ COMMENT ON COLUMN site.tokens.token_type IS 'Type of token, such as CMA or PAT.'
271
271
  COMMENT ON COLUMN site.tokens.token_status IS 'Current status of the token (e.g., Active).';
272
272
  COMMENT ON COLUMN site.tokens.space_id IS 'Identifier for the associated space.';
273
273
 
274
- CREATE TABLE if not exists site.spaces (
274
+ /*CREATE TABLE if not exists site.spaces (
275
275
  space_id text PRIMARY KEY default next_id(), -- Unique identifier for the space
276
276
  name TEXT NOT NULL, -- Human-readable name of the space
277
277
  created_at TIMESTAMP NOT NULL default now(), -- When the space was created
@@ -296,6 +296,7 @@ COMMENT ON COLUMN site.spaces.default_locale IS 'Default language/locale of the
296
296
  COMMENT ON COLUMN site.spaces.plan IS 'Plan type (e.g., "Free", "Premium")';
297
297
 
298
298
  alter table site.spaces alter column default_locale set default 'uk';
299
+ */
299
300
 
300
301
  CREATE TABLE if not exists site.organizations (
301
302
  organization_id TEXT PRIMARY KEY DEFAULT next_id(), -- Unique identifier for the organization
@@ -348,7 +349,7 @@ COMMENT ON COLUMN site.comments.thread_id IS 'ID of the top-level thread this co
348
349
 
349
350
  CREATE TABLE if not exists site.contents (
350
351
  content_id text PRIMARY KEY default next_id(),
351
- space_id text,
352
+ -- space_id text,
352
353
  content_type_id text NOT NULL,
353
354
  created_at TIMESTAMP NOT NULL DEFAULT now(),
354
355
  updated_at TIMESTAMP NOT NULL DEFAULT now(),
@@ -363,7 +364,7 @@ CREATE TABLE if not exists site.contents (
363
364
  updated_by text,
364
365
  meta json,
365
366
  main_image text,
366
- FOREIGN KEY (space_id) REFERENCES site.spaces(space_id),
367
+ -- FOREIGN KEY (space_id) REFERENCES site.spaces(space_id),
367
368
  FOREIGN KEY (content_type_id) REFERENCES site.content_types(content_type_id),
368
369
  FOREIGN KEY (created_by) REFERENCES admin.users(uid),
369
370
  FOREIGN KEY (published_by) REFERENCES admin.users(uid),
@@ -11,15 +11,15 @@ export default async function deleteContent(req, reply) {
11
11
  const { type, id } = params;
12
12
 
13
13
  if (!type) {
14
- return reply.status(400).send('not enough params: type');
14
+ return reply.status(400).send({ error: 'not enough params: type', code: 400 });
15
15
  }
16
16
 
17
17
  if (!id) {
18
- return reply.status(400).send('not enough params: id');
18
+ return reply.status(400).send({ error: 'not enough params: id', code: 400 });
19
19
  }
20
20
 
21
21
  if (id === 'pages') {
22
- return reply.status(403).send('access restricted: pages contents cannot be deleted');
22
+ return reply.status(403).send({ error: 'access restricted: pages contents cannot be deleted', code: 403 });
23
23
  }
24
24
 
25
25
  const { ctid, dbtable } = await pg.query('select content_type_id as ctid, table_name as dbtable from site.content_types where $1 in (content_type_id, name)', [params.type])
@@ -30,7 +30,7 @@ export default async function deleteContent(req, reply) {
30
30
  where a.relam=2 and b.nspname='data'`).then(el => el.rows?.[0]?.array_agg || []) : [];
31
31
 
32
32
  if (!arr.length && type !== 'pages') {
33
- return reply.status(400).send('empty schema: data');
33
+ return reply.status(400).send({ error: 'empty schema: data', code: 400 });
34
34
  }
35
35
 
36
36
  const table = arr.find(el => el === params.type);
@@ -47,11 +47,11 @@ export default async function deleteContent(req, reply) {
47
47
  ).then(el => el.rows?.[0] || {});
48
48
 
49
49
  if (!cid) {
50
- return reply.status(404).send('contents not found');
50
+ return reply.status(404).send({ error: 'contents not found', code: 404 });
51
51
  }
52
52
 
53
53
  if (cid === 'pages') {
54
- return reply.status(403).send('access restricted: pages contents cannot be deleted');
54
+ return reply.status(403).send({ error: 'access restricted: pages contents cannot be deleted', code: 403 });
55
55
  }
56
56
 
57
57
  if (status === 'archived') {
@@ -81,7 +81,7 @@ export default async function deleteContent(req, reply) {
81
81
 
82
82
  // custom table
83
83
  if (!table && !dbtable) {
84
- return reply.status(400).send('invalid params: type');
84
+ return reply.status(400).send({ error: 'invalid params: type', code: 400 });
85
85
  }
86
86
 
87
87
  const status = await pg.query(`select status from data."${(table || dbtable)}" where id =$1`, [id]).then(el => el.rows?.[0]?.status);
@@ -57,11 +57,11 @@ export default async function getContent(req, reply, opt) {
57
57
  ).then(el => el.rows?.[0]?.isvalid);
58
58
 
59
59
  if (!config.local && !isValidToken && config.mode !== 'cms' && !called) {
60
- return reply.status(403).send('access restricted: token');
60
+ return reply.status(403).send({ error: 'access restricted: token', code: 403 });
61
61
  }
62
62
 
63
63
  if (!type) {
64
- return reply.status(400).send('not enough params: type');
64
+ return reply.status(400).send({ error: 'not enough params: type', code: 400 });
65
65
  }
66
66
 
67
67
  const { contentId, contentTypeId, meta } = params.type === 'pages'
@@ -69,7 +69,7 @@ export default async function getContent(req, reply, opt) {
69
69
  : await pg.query(`select content_id as "contentId", content_type_id as "contentTypeId", meta from site.contents where $1 in (slug, content_id, content_type_id)`, [params.type]).then(el => el.rows?.[0] || {});
70
70
 
71
71
  if (!contentId) {
72
- return reply.status(404).send('content not found');
72
+ return reply.status(404).send({ error: 'content not found', code: 404 });
73
73
  }
74
74
 
75
75
  const { table, contentType, preview, columns: columns1 } = await pg.query(
@@ -78,7 +78,7 @@ export default async function getContent(req, reply, opt) {
78
78
  ).then(el => el.rows?.[0] || {});
79
79
 
80
80
  if (!contentType && params.type !== 'pages') {
81
- return reply.status(404).send('content type not found');
81
+ return reply.status(404).send({ error: 'content type not found', code: 404 });
82
82
  }
83
83
 
84
84
  const loadTable = contentType === 'collection' && table
@@ -86,7 +86,7 @@ export default async function getContent(req, reply, opt) {
86
86
  : await getTemplate('table', 'single.default.table');
87
87
  const { columns: defaultColumns = [], filters: defaultFilters = [] } = loadTable || {};
88
88
 
89
- defaultColumns.forEach(col => Object.assign(col, { default: true }));
89
+ defaultColumns.forEach(col => Object.assign(col, { defaultColumn: true }));
90
90
 
91
91
  const columns = (columns1 || []).filter(col => !defaultColumns.map(el => el.name).includes(col.name));
92
92
 
@@ -105,7 +105,7 @@ export default async function getContent(req, reply, opt) {
105
105
  }
106
106
 
107
107
  if (result?.message) {
108
- return reply.status(result.status || 500).send(result.message);
108
+ return reply.status(result.status || 500).send({ error: result.message, code: result.status || 500 });
109
109
  }
110
110
 
111
111
  Object.assign(result, { meta });
@@ -4,11 +4,11 @@ import inputTypes from '../utils/inputTypes.js';
4
4
 
5
5
  export default async function getContentBySlug({ pg = pgClients.client, params = {}, headers = {} }, reply) {
6
6
  if (!params.slug) {
7
- return reply.status(400).send('not enough params: slug');
7
+ return reply.status(400).send({ error: 'not enough params: slug', code: 400 });
8
8
  }
9
9
 
10
10
  if (!pg?.pk?.['site.content_types']) {
11
- return reply.status(404).send('table not found');
11
+ return reply.status(404).send({ error: 'table not found', code: 404 });
12
12
  }
13
13
 
14
14
  // headers.authorization = 'Bearer tokenExample'
@@ -18,18 +18,18 @@ export default async function getContentBySlug({ pg = pgClients.client, params =
18
18
  ).then(el => el.rows?.[0]?.isvalid);
19
19
 
20
20
  if (!config.local && !isValidToken && config.mode !== 'cms') {
21
- return reply.status(403).send('access restricted: token');
21
+ return reply.status(403).send({ error: 'access restricted: token', code: 403 });
22
22
  }
23
23
 
24
- const { cid } = await pg.query(
25
- `select content_id as cid from site.contents where $1 in (content_id,slug) limit 1`,
24
+ const cid = await pg.query(
25
+ `select content_id from site.contents where $1 in (content_id,slug) limit 1`,
26
26
  [params.slug],
27
- ).then(el => el.rows?.[0] || {});
27
+ ).then(el => el.rows?.[0]?.content_id);
28
28
 
29
29
  if (cid) {
30
- const { rows: data = [] } = await pg.query(
30
+ const data = await pg.query(
31
31
  `select field_key, field_type, field_value, field_value_object, content_id from site.content_data where content_id=$1`, [cid]
32
- );
32
+ ).then(el => el.rows || []);
33
33
 
34
34
  const meta = await pg.query(
35
35
  'select title, status, revision, locale, slug, content_type_id, (select columns from site.content_types where content_type_id=a.content_type_id limit 1) as columns from site.contents a where content_id=$1 limit 1',
@@ -63,7 +63,7 @@ export default async function getContentBySlug({ pg = pgClients.client, params =
63
63
  const { rows: contentTypes = [] } = await pg.query(`select content_type_id as ctid, table_name as table, type from site.content_types where table_name is not null and type='collection' `);
64
64
 
65
65
  if (!contentTypes.length || contentTypes.find(row => row.table && pg.pk[row.table])) {
66
- return reply.status(404).send('content not found');
66
+ return reply.status(404).send({ error: 'content not found', code: 404 });
67
67
  }
68
68
 
69
69
  const tlist = await pg.query(`select array_agg((select nspname from pg_namespace where oid=relnamespace)||'.'||relname) tlist
@@ -74,20 +74,20 @@ export default async function getContentBySlug({ pg = pgClients.client, params =
74
74
  const { dataid, ctid } = await pg.query(q).then(el => el.rows?.[0] || {});
75
75
 
76
76
  if (!dataid) {
77
- return reply.status(404).send('content not found: 2');
77
+ return reply.status(404).send({ error: 'content not found: 2', code: 404 });
78
78
  }
79
79
 
80
80
  if (!ctid) {
81
- return reply.status(404).send('content not found: 3');
81
+ return reply.status(404).send({ error: 'content not found: 3', code: 404 });
82
82
  }
83
83
 
84
84
  const meta = await pg.query('select content_type_id, type, table_name as table, title, status, name as slug, columns from site.content_types where content_type_id=$1', [ctid]).then(el => el.rows?.[0] || {});
85
85
 
86
86
  if (!meta?.table) {
87
- return reply.status(404).send('content not found: 4');
87
+ return reply.status(404).send({ error: 'content not found: 4', code: 404 });
88
88
  }
89
89
 
90
- const { rows = [] } = await pg.query(`select * from data.${meta.table} where id=$1`, [dataid]);
90
+ const rows = await pg.query(`select * from data.${meta.table} where id=$1`, [dataid]).then(el => el.rows || []);
91
91
 
92
92
  return reply.status(200).send({ ...meta, custom: true, rows });
93
93
  }
@@ -1,16 +1,16 @@
1
- import { pgClients } from '@opengis/fastify-table/utils.js';
2
-
3
- export default async function getPermissions(req, reply) {
4
- const { pg = pgClients.client, params = {}, user = {} } = req;
5
-
6
- if (!user?.uid) {
7
- return reply.status(401).send('unauthorized');
8
- }
9
-
10
- const { rows = [] } = await pg.query(
11
- `select * from site.permissions where ${params.id ? 'user_id=$1' : 'true'}`,
12
- [params.id].filter(Boolean),
13
- );
14
-
15
- return { permissions: rows };
1
+ import { pgClients } from '@opengis/fastify-table/utils.js';
2
+
3
+ export default async function getPermissions(req, reply) {
4
+ const { pg = pgClients.client, params = {}, user = {} } = req;
5
+
6
+ if (!user?.uid) {
7
+ return reply.status(401).send('unauthorized');
8
+ }
9
+
10
+ const { rows = [] } = await pg.query(
11
+ `select * from site.permissions where ${params.id ? 'user_id=$1' : 'true'}`,
12
+ [params.id].filter(Boolean),
13
+ );
14
+
15
+ return { permissions: rows };
16
16
  }