@opengis/cms 0.0.59 → 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.
- package/README.md +4 -4
- package/dist/{ArticlesPage-BjYzvTWM.js → ArticlesPage-CFjE_cw_.js} +3 -3
- package/dist/{CollectionsBreadcrumb-HePNJb-d.js → CollectionsBreadcrumb-BCxeRikP.js} +1 -1
- package/dist/CollectionsBreadcrumb.vue_vue_type_script_setup_true_lang-umRzB5mY.js +53 -0
- package/dist/{Dashboard-CXkg_pk8.js → Dashboard-C1eGscNd.js} +132 -132
- package/dist/EditCollectionPage-3Q57ptN3.js +188 -0
- package/dist/{MenuAddPage-QTnwCoGh.js → MenuAddPage-D-p3gFgm.js} +1 -1
- package/dist/{MenuBody-Bi0ONVZf.js → MenuBody-rN5j4YBu.js} +2 -2
- package/dist/{MenuItemPage-B7Y9KFyb.js → MenuItemPage-BoJw885D.js} +3 -3
- package/dist/{MenuList-BLIpeqSd.js → MenuList-DFEBS0NB.js} +53 -53
- package/dist/{MenuPage-3W6jZ15H.js → MenuPage-BCZB_S8j.js} +1 -1
- package/dist/{MenuWrapper-OrOv6sOb.js → MenuWrapper-AZ_8s-zd.js} +1 -1
- package/dist/{MonacoEditor-ByPT8pnv.js → MonacoEditor-Db-3Jc3E.js} +1 -1
- package/dist/MonacoEditor.vue_vue_type_script_setup_true_lang-B1DrxmQX.js +84 -0
- package/dist/{UniversalTable-GBd_pStq.js → UniversalTable-CzqPG-tY.js} +80 -80
- package/dist/{UniversalTablePagination-Dw2hc0nc.js → UniversalTablePagination-4gL47A7I.js} +46 -46
- package/dist/{contentForm-Buku-lel.js → contentForm-CLStrfSg.js} +49 -52
- package/dist/index.js +5 -5
- package/dist/{vs-builder-monaco-Cw-f19gc.js → vs-builder-monaco-B3Jj0V31.js} +1 -1
- package/package.json +69 -69
- package/server/migrations/fixes.sql +5 -2
- package/server/migrations/site.sql +4 -3
- package/server/routes/cms/controllers/deleteContent.js +7 -7
- package/server/routes/cms/controllers/getContent.js +6 -6
- package/server/routes/cms/controllers/getContentBySlug.js +13 -13
- package/server/routes/cms/controllers/getPermissions.js +15 -15
- package/server/routes/cms/controllers/insertContent.js +28 -19
- package/server/routes/cms/controllers/setPermissions.js +49 -49
- package/server/routes/cms/controllers/updateContent.js +12 -47
- package/server/routes/cms/utils/getCollection.js +1 -1
- package/server/routes/cms/utils/getSingle.js +1 -1
- package/server/routes/cms/utils/insertContentLocalization.js +1 -1
- package/server/routes/cms/utils/requestTranslation.js +73 -23
- package/server/routes/cms/utils/updateLocalization.js +1 -6
- package/server/routes/cmsSpace/controllers/deleteSpace.js +1 -0
- package/server/routes/cmsSpace/controllers/getSpaces.js +1 -0
- package/server/routes/cmsSpace/controllers/insertSpace.js +1 -0
- package/server/routes/cmsSpace/controllers/updateSpace.js +1 -0
- package/server/routes/contentType/controllers/contentTypeList.js +4 -11
- package/server/routes/contentType/controllers/editContentType.js +7 -25
- package/server/routes/contentType/controllers/getContentType.js +5 -13
- package/server/templates/select/core.user_mentioned.sql +1 -1
- package/dist/CollectionsBreadcrumb.vue_vue_type_script_setup_true_lang-BJh-tjam.js +0 -53
- package/dist/EditCollectionPage-CqYHpEON.js +0 -187
- package/dist/MonacoEditor.vue_vue_type_script_setup_true_lang-C8cip9Ci.js +0 -84
- package/dist/images/logo.png +0 -0
- package/dist/index.html +0 -29
- package/dist/vite.svg +0 -1
|
@@ -4,7 +4,7 @@ import { ArrowLeft as Je, HelpCircle as He, Settings as Ke, Save as qe, Loader2
|
|
|
4
4
|
import { useI18n as Qe } from "vue-i18n";
|
|
5
5
|
import { g as We } from "./getField-CpwVE28P.js";
|
|
6
6
|
import { inputs as x, VForm as ue } from "@opengis/form";
|
|
7
|
-
import { notify as
|
|
7
|
+
import { notify as P } from "@opengis/core";
|
|
8
8
|
const Xe = [
|
|
9
9
|
{
|
|
10
10
|
key: "title",
|
|
@@ -66,16 +66,16 @@ const Xe = [
|
|
|
66
66
|
), be = h(
|
|
67
67
|
() => import("./VsPreview-DwETkOpb.js")
|
|
68
68
|
), he = h(
|
|
69
|
-
() => import("./CollectionsBreadcrumb-
|
|
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
|
-
const { t:
|
|
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(() => {
|
|
73
73
|
var e;
|
|
74
74
|
return ((e = X.value) == null ? void 0 : e.cms) || {};
|
|
75
|
-
}), ke = m(() => Array.isArray(
|
|
75
|
+
}), ke = m(() => Array.isArray(B.value.locales) ? B.value.locales : []), O = m(
|
|
76
76
|
() => ke.value.filter(Boolean)
|
|
77
77
|
), Y = m(
|
|
78
|
-
() =>
|
|
78
|
+
() => B.value.locale || O.value[0] || "uk"
|
|
79
79
|
);
|
|
80
80
|
De(
|
|
81
81
|
X,
|
|
@@ -114,14 +114,14 @@ const Xe = [
|
|
|
114
114
|
return Xe.flatMap((t) => {
|
|
115
115
|
const o = {
|
|
116
116
|
...t,
|
|
117
|
-
label:
|
|
117
|
+
label: r(t.label)
|
|
118
118
|
};
|
|
119
119
|
if (!t.localization || e.length === 0)
|
|
120
120
|
return [o];
|
|
121
121
|
const a = e.map((n) => ({
|
|
122
122
|
...t,
|
|
123
123
|
key: `${t.key}:${n}`,
|
|
124
|
-
label: `${
|
|
124
|
+
label: `${r(t.label)} (${n})`,
|
|
125
125
|
localization: !1
|
|
126
126
|
}));
|
|
127
127
|
return [o, ...a];
|
|
@@ -129,21 +129,18 @@ const Xe = [
|
|
|
129
129
|
}), g = p({}), i = p({
|
|
130
130
|
title: "",
|
|
131
131
|
status: "draft"
|
|
132
|
-
}), J = p(null), L = p(""),
|
|
133
|
-
() =>
|
|
134
|
-
var e;
|
|
135
|
-
return (((e = i.value) == null ? void 0 : e.type) || J.value) === "single";
|
|
136
|
-
}
|
|
132
|
+
}), J = p(null), L = p(""), F = m(
|
|
133
|
+
() => J.value === "single"
|
|
137
134
|
), Te = m(() => {
|
|
138
135
|
const e = [
|
|
139
|
-
{ id: "content", name:
|
|
140
|
-
{ id: "seo", name:
|
|
141
|
-
{ id: "tags", name:
|
|
136
|
+
{ id: "content", name: r("cms.builder.content") },
|
|
137
|
+
{ id: "seo", name: r("cms.builder.seo") },
|
|
138
|
+
{ id: "tags", name: r("cms.builder.tags") }
|
|
142
139
|
];
|
|
143
|
-
return N.value && e.push({ id: "preview", name:
|
|
140
|
+
return N.value && e.push({ id: "preview", name: r("cms.builder.preview") }), e;
|
|
144
141
|
}), A = p("content"), ee = m(() => {
|
|
145
|
-
var s,
|
|
146
|
-
const e = ((s = d.params) == null ? void 0 : s.collection) || ((
|
|
142
|
+
var s, c, l, k, f, b, y, T, oe;
|
|
143
|
+
const e = ((s = d.params) == null ? void 0 : s.collection) || ((c = d.params) == null ? void 0 : c.id), t = (l = i.value) == null ? void 0 : l.content_type_id, o = t ? (f = (k = Q.value) == null ? void 0 : k.find((K) => K.id === t)) == null ? void 0 : f.title : null;
|
|
147
144
|
if (o)
|
|
148
145
|
return o;
|
|
149
146
|
if (L.value)
|
|
@@ -154,24 +151,24 @@ const Xe = [
|
|
|
154
151
|
if (a)
|
|
155
152
|
return a;
|
|
156
153
|
const n = (T = d.params) == null ? void 0 : T.id;
|
|
157
|
-
return
|
|
154
|
+
return F.value && n && e === n && ((oe = i.value) != null && oe.title) ? i.value.title : e === "pages" ? r("cms.articles.title") : e;
|
|
158
155
|
}), Se = m(() => {
|
|
159
156
|
var t, o;
|
|
160
|
-
const e =
|
|
161
|
-
return ((t = i.value) == null ? void 0 : t.title) || ((o = d.params) != null && o.id ?
|
|
157
|
+
const e = F.value ? "cms.builder.editPage" : "cms.builder.editCollection";
|
|
158
|
+
return ((t = i.value) == null ? void 0 : t.title) || ((o = d.params) != null && o.id ? r(e) : r("cms.articles.createArticle"));
|
|
162
159
|
}), Ve = m(() => {
|
|
163
|
-
var s,
|
|
164
|
-
const e = ((s = d.params) == null ? void 0 : s.collection) || ((
|
|
160
|
+
var s, c, l;
|
|
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: ee.value,
|
|
163
|
+
label: F.value ? r("cms.navigation.singletons") : ee.value,
|
|
167
164
|
route: `collections/${e}`
|
|
168
165
|
}
|
|
169
166
|
];
|
|
170
167
|
return t ? n.push({
|
|
171
|
-
label: a ?
|
|
168
|
+
label: a ? r("cms.collections.edit") : o,
|
|
172
169
|
route: `collections/${e}/${t}`
|
|
173
170
|
}) : n.push({
|
|
174
|
-
label:
|
|
171
|
+
label: r("cms.articles.createArticle"),
|
|
175
172
|
route: `collections/${e}/create`
|
|
176
173
|
}), n;
|
|
177
174
|
}), Ae = (e) => {
|
|
@@ -186,9 +183,9 @@ const Xe = [
|
|
|
186
183
|
throw new Error("Failed to fetch article");
|
|
187
184
|
const s = await n.json();
|
|
188
185
|
if (_.value = (s == null ? void 0 : s.columns) || [], s != null && s.preview_path && (N.value = s == null ? void 0 : s.preview_path), J.value = (s == null ? void 0 : s.type) || null, s.rows) {
|
|
189
|
-
let
|
|
190
|
-
Array.isArray(
|
|
191
|
-
const l = ((o =
|
|
186
|
+
let c = s.rows;
|
|
187
|
+
Array.isArray(c) || (c = [c]), i.value = c[0];
|
|
188
|
+
const l = ((o = c[0]) == null ? void 0 : o.content_type_id) || e;
|
|
192
189
|
if (l) {
|
|
193
190
|
const k = await fetch(`/api/cms-type/${l}`);
|
|
194
191
|
if (k.ok) {
|
|
@@ -196,7 +193,7 @@ const Xe = [
|
|
|
196
193
|
L.value = (f == null ? void 0 : f.title) || (f == null ? void 0 : f.name) || L.value;
|
|
197
194
|
}
|
|
198
195
|
}
|
|
199
|
-
await ce(), (a =
|
|
196
|
+
await ce(), (a = c[0]) != null && a.meta ? g.value = { ...c[0].meta } : g.value = {
|
|
200
197
|
title: "",
|
|
201
198
|
description: "",
|
|
202
199
|
keywords: "",
|
|
@@ -249,12 +246,12 @@ const Xe = [
|
|
|
249
246
|
const e = (t = i.value) == null ? void 0 : t.content_type_id;
|
|
250
247
|
return e ? `/collections/${e}/edit` : null;
|
|
251
248
|
}), ze = () => {
|
|
252
|
-
var o, a, n;
|
|
249
|
+
var o, a, n, s;
|
|
253
250
|
if (!H.value)
|
|
254
251
|
return;
|
|
255
252
|
const e = ((o = d.params) == null ? void 0 : o.collection) || ((a = d.params) == null ? void 0 : a.id), t = (n = d.params) == null ? void 0 : n.id;
|
|
256
253
|
if (e && t) {
|
|
257
|
-
V.push(`/collections/${
|
|
254
|
+
V.push(`/collections/${(s = i.value) == null ? void 0 : s.content_type_id}/edit`);
|
|
258
255
|
return;
|
|
259
256
|
}
|
|
260
257
|
V.push(H.value);
|
|
@@ -265,24 +262,24 @@ const Xe = [
|
|
|
265
262
|
try {
|
|
266
263
|
(await fetch(
|
|
267
264
|
`/api/cms-translate?id=${t}&collection=${e}&to=en&nocache=1`
|
|
268
|
-
)).ok ? (
|
|
269
|
-
title:
|
|
270
|
-
message:
|
|
265
|
+
)).ok ? (P({
|
|
266
|
+
title: r("cms.collections.translateContentSuccess"),
|
|
267
|
+
message: r("cms.collections.translateContentSuccess"),
|
|
271
268
|
type: "success"
|
|
272
|
-
}), await te(e, t)) :
|
|
273
|
-
title:
|
|
274
|
-
message:
|
|
269
|
+
}), await te(e, t)) : P({
|
|
270
|
+
title: r("cms.collections.translateContentError"),
|
|
271
|
+
message: r("cms.collections.translateContentError"),
|
|
275
272
|
type: "error"
|
|
276
273
|
});
|
|
277
274
|
} finally {
|
|
278
275
|
z.value = !1;
|
|
279
276
|
}
|
|
280
277
|
}, Fe = async (e) => {
|
|
281
|
-
var
|
|
282
|
-
const t = (
|
|
278
|
+
var c, l, k, f;
|
|
279
|
+
const t = (c = d.params) == null ? void 0 : c.collection, o = (l = d.params) == null ? void 0 : l.id, a = await D.value.validate();
|
|
283
280
|
if (a) {
|
|
284
|
-
|
|
285
|
-
title:
|
|
281
|
+
P({
|
|
282
|
+
title: r("cms.validation"),
|
|
286
283
|
message: JSON.stringify(a),
|
|
287
284
|
type: "warning"
|
|
288
285
|
});
|
|
@@ -322,21 +319,21 @@ const Xe = [
|
|
|
322
319
|
} catch (y) {
|
|
323
320
|
console.warn("Could not parse response to get ID:", y);
|
|
324
321
|
}
|
|
325
|
-
|
|
326
|
-
title:
|
|
327
|
-
message:
|
|
322
|
+
P({
|
|
323
|
+
title: r("cms.common.success"),
|
|
324
|
+
message: r("cms.common.successMessage"),
|
|
328
325
|
type: "success"
|
|
329
326
|
});
|
|
330
327
|
} catch (b) {
|
|
331
|
-
console.error("Submit error:", b),
|
|
332
|
-
title:
|
|
328
|
+
console.error("Submit error:", b), P({
|
|
329
|
+
title: r("cms.common.error"),
|
|
333
330
|
message: "Помилка збереження",
|
|
334
331
|
type: "error"
|
|
335
332
|
});
|
|
336
333
|
}
|
|
337
334
|
};
|
|
338
335
|
return (e, t) => {
|
|
339
|
-
var o, a, n, s,
|
|
336
|
+
var o, a, n, s, c;
|
|
340
337
|
return w(), $("div", Ye, [
|
|
341
338
|
u("div", Ze, [
|
|
342
339
|
C(v(he), {
|
|
@@ -353,7 +350,7 @@ const Xe = [
|
|
|
353
350
|
C(v(Je), { class: "w-5 h-5" })
|
|
354
351
|
]),
|
|
355
352
|
u("h1", st, j(e.$t(
|
|
356
|
-
|
|
353
|
+
F.value ? "cms.builder.editPage" : "cms.builder.editCollection"
|
|
357
354
|
)) + ' "' + j(i.value.title) + '" ', 1),
|
|
358
355
|
u("a", {
|
|
359
356
|
href: `https://cms.opengis.info/${v(G)}/guides/content/`,
|
|
@@ -364,7 +361,7 @@ const Xe = [
|
|
|
364
361
|
], 8, ot)
|
|
365
362
|
]),
|
|
366
363
|
u("div", lt, [
|
|
367
|
-
H.value &&
|
|
364
|
+
H.value && F.value ? (w(), $("button", {
|
|
368
365
|
key: 0,
|
|
369
366
|
onClick: ze,
|
|
370
367
|
type: "button",
|
|
@@ -389,7 +386,7 @@ const Xe = [
|
|
|
389
386
|
(w(!0), $(Ne, null, Me(Te.value, (l) => (w(), $("button", {
|
|
390
387
|
key: l.id,
|
|
391
388
|
onClick: (k) => {
|
|
392
|
-
A.value = l.id, console.log("cmsSettings:",
|
|
389
|
+
A.value = l.id, console.log("cmsSettings:", B.value.value);
|
|
393
390
|
},
|
|
394
391
|
class: ne([
|
|
395
392
|
"inline-flex flex-1 items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm data-[state=active]:bg-blue-50 data-[state=active]:text-blue-700 data-[state=active]:border-blue-200",
|
|
@@ -476,7 +473,7 @@ const Xe = [
|
|
|
476
473
|
])) : S("", !0),
|
|
477
474
|
A.value === "preview" ? (w(), $("div", bt, [
|
|
478
475
|
C(v(be), {
|
|
479
|
-
slug: (
|
|
476
|
+
slug: (c = i.value) == null ? void 0 : c.slug,
|
|
480
477
|
preview_path: N.value
|
|
481
478
|
}, null, 8, ["slug", "preview_path"])
|
|
482
479
|
])) : S("", !0)
|
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-
|
|
7
|
-
() => import("./MenuPage-
|
|
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-
|
|
9
|
+
() => import("./MenuItemPage-BoJw885D.js")
|
|
10
10
|
), F = u(
|
|
11
|
-
() => import("./MenuAddPage-
|
|
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-
|
|
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-
|
|
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.
|
|
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, {
|
|
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
|
|
25
|
-
`select content_id
|
|
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
|
|
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
|
|
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
|
}
|