@opengis/cms 0.0.2 → 0.0.3
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/.gitlab-ci.yml +36 -0
- package/config.example +21 -0
- package/docs/.vitepress/abbr.mjs +26 -0
- package/docs/.vitepress/config.mjs +119 -0
- package/docs/.vitepress/navigation.mjs +82 -0
- package/docs/.vitepress/theme/Layout.vue +17 -0
- package/docs/.vitepress/theme/components/NavigationLinks.vue +102 -0
- package/docs/.vitepress/theme/components/Panzoom.vue +169 -0
- package/docs/.vitepress/theme/index.mjs +15 -0
- package/docs/.vitepress/theme/style.scss +136 -0
- package/docs/abbr.json +4 -0
- package/docs/api/builder/cms.builder.delete.md +65 -0
- package/docs/api/builder/cms.builder.get.md +70 -0
- package/docs/api/builder/cms.builder.list.md +98 -0
- package/docs/api/builder/cms.builder.post.md +72 -0
- package/docs/api/builder/cms.builder.put.md +88 -0
- package/docs/api/category/cms.category.delete.md +60 -0
- package/docs/api/category/cms.category.get.md +61 -0
- package/docs/api/category/cms.category.list.md +77 -0
- package/docs/api/category/cms.category.post.md +62 -0
- package/docs/api/category/cms.category.put.md +78 -0
- package/docs/api/index.md +50 -0
- package/docs/api/manager/cms.manager.delete.md +64 -0
- package/docs/api/manager/cms.manager.get.md +72 -0
- package/docs/api/manager/cms.manager.list.md +96 -0
- package/docs/api/manager/cms.manager.post.md +70 -0
- package/docs/api/manager/cms.manager.put.md +86 -0
- package/docs/api/media/del.md +64 -0
- package/docs/api/media/edit.md +92 -0
- package/docs/api/media/list.md +70 -0
- package/docs/api/media/metadata.md +57 -0
- package/docs/api/media/preview.md +33 -0
- package/docs/api/media/upload.md +84 -0
- package/docs/db/erd.md +173 -0
- package/docs/db/index.md +7 -0
- package/docs/index.md +39 -0
- package/docs/public/logo-dark.svg +24 -0
- package/docs/public/logo-light.svg +24 -0
- package/docs/public/logo-short.svg +15 -0
- package/docs/public/logo.svg +19 -0
- package/docs/readme/index.md +6 -0
- package/docs/src/vs-button.vue +157 -0
- package/docs/vue/basic/button.md +144 -0
- package/docs/vue/index.md +9 -0
- package/index.html +14 -0
- package/package.json +2 -5
- package/server/app.js +25 -0
- package/server/config.js +5 -0
- package/server/index.js +23 -0
- package/server/migrations/media.sql +30 -0
- package/server/plugins/hook.js +91 -0
- package/server/plugins/vite.js +80 -0
- package/server/routes/builder/controllers/cms.builder.delete.js +21 -0
- package/server/routes/builder/controllers/cms.builder.get.js +17 -0
- package/server/routes/builder/controllers/cms.builder.list.js +16 -0
- package/server/routes/builder/controllers/cms.builder.post.js +21 -0
- package/server/routes/builder/controllers/cms.builder.put.js +23 -0
- package/server/routes/builder/index.mjs +22 -0
- package/server/routes/category/controllers/cms.category.delete.js +21 -0
- package/server/routes/category/controllers/cms.category.get.js +17 -0
- package/server/routes/category/controllers/cms.category.list.js +16 -0
- package/server/routes/category/controllers/cms.category.post.js +21 -0
- package/server/routes/category/controllers/cms.category.put.js +23 -0
- package/server/routes/category/index.mjs +22 -0
- package/server/routes/manager/controllers/cms.manager.delete.js +22 -0
- package/server/routes/manager/controllers/cms.manager.get.js +21 -0
- package/server/routes/manager/controllers/cms.manager.list.js +31 -0
- package/server/routes/manager/controllers/cms.manager.post.js +28 -0
- package/server/routes/manager/controllers/cms.manager.put.js +23 -0
- package/server/routes/manager/index.mjs +22 -0
- package/server/routes/media/controllers/delete.js +59 -0
- package/server/routes/media/controllers/edit.js +94 -0
- package/server/routes/media/controllers/list.js +74 -0
- package/server/routes/media/controllers/metadata.js +51 -0
- package/server/routes/media/controllers/preview.js +47 -0
- package/server/routes/media/controllers/upload.js +79 -0
- package/server/routes/media/index.mjs +16 -0
- package/server/routes/root.mjs +15 -0
- package/server/templates/cls/cms.category_type.json +10 -0
- package/server/templates/cls/cms.content_review_status.json +10 -0
- package/server/templates/cls/cms.content_status.json +10 -0
- package/server/templates/cls/cms.content_type.json +10 -0
- package/server/templates/cls/cms.lang.json +10 -0
- package/server/templates/page/login.html +59 -0
- package/server/templates/select/cms.category_id.sql +1 -0
- package/server/templates/select/cms.type_id.sql +1 -0
- package/src/App.vue +4 -0
- package/src/assets/tailwind/tailwind.js +62 -0
- package/src/assets/vue.svg +1 -0
- package/src/components/builder/vs-builder-content.vue +163 -0
- package/src/components/builder/vs-builder-menu.vue +142 -0
- package/src/components/formats/index.js +8 -0
- package/src/components/formats/vs-manager-table-date.vue +29 -0
- package/src/components/formats/vs-manager-table-switch.vue +16 -0
- package/src/components/icons/icon-actions.vue +24 -0
- package/src/components/icons/icon-arrow-left.vue +19 -0
- package/src/components/icons/icon-check.vue +23 -0
- package/src/components/icons/icon-chewron-right.vue +16 -0
- package/src/components/icons/icon-close.vue +22 -0
- package/src/components/icons/icon-edit.vue +22 -0
- package/src/components/icons/icon-folder.vue +18 -0
- package/src/components/icons/icon-folder2.vue +17 -0
- package/src/components/icons/icon-home.vue +16 -0
- package/src/components/icons/icon-image.vue +18 -0
- package/src/components/icons/icon-logo.vue +22 -0
- package/src/components/icons/icon-media.vue +22 -0
- package/src/components/icons/icon-point.vue +11 -0
- package/src/components/icons/icon-search.vue +22 -0
- package/src/components/icons/icon-table.vue +22 -0
- package/src/components/icons/icon-users.vue +18 -0
- package/src/components/icons/icon.plus.vue +18 -0
- package/src/components/manager/children/vs-manager-collection-content.vue +55 -0
- package/src/components/manager/children/vs-manager-collection-item-content.vue +116 -0
- package/src/components/manager/children/vs-manager-single-content.vue +112 -0
- package/src/components/manager/manager-table/vs-manager-colection-table-add.vue +84 -0
- package/src/components/manager/manager-table/vs-manager-collection-table.vue +59 -0
- package/src/components/manager/vs-manager-menu.vue +73 -0
- package/src/components/media/Breadcrumb.vue +73 -0
- package/src/components/shared-components/vs-not-data.vue +213 -0
- package/src/components/vs-main-menu.vue +53 -0
- package/src/helpers/debounce.js +10 -0
- package/src/helpers/translite.js +19 -0
- package/src/main.js +30 -0
- package/src/misc/import-file.js +32 -0
- package/src/pages/vs-builder.vue +22 -0
- package/src/pages/vs-layout.vue +17 -0
- package/src/pages/vs-manager.vue +30 -0
- package/src/pages/vs-media.vue +398 -0
- package/src/router/router.js +9 -0
- package/src/router/routes.config.js +40 -0
- package/src/style.css +0 -0
- package/src/templates/form-columns.js +70 -0
- package/src/templates/form-template.js +22 -0
- package/test/config.js +17 -0
- package/test/files/eye.svg +4 -0
- package/test/helper.js +30 -0
- package/test/routes/builder.test.js +99 -0
- package/test/routes/category.test.js +97 -0
- package/test/routes/manager.test.js +103 -0
- package/test/routes/media.test.js +252 -0
- package/vite.config.js +37 -0
- package/editor/dist/cms.js +0 -5900
- package/editor/dist/cms.umd.cjs +0 -19
- /package/{editor/dist → public}/vite.svg +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { pgClients, getMeta } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
export default async function builderGet({ pg = pgClients.client, params = {} }) {
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const { pk } = await getMeta({ table: 'site.content_types' });
|
|
7
|
+
|
|
8
|
+
if (!pk) {
|
|
9
|
+
return { message: 'table not found', status: 404 };
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { rows, rowCount: total } = await pg.query(
|
|
13
|
+
`select a.content_type_id as id, a.* FROM site.content_types a
|
|
14
|
+
where a.content_type_id=$1`, [params.id]
|
|
15
|
+
);
|
|
16
|
+
return { message: { total, rows }, status: 200 };
|
|
17
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { pgClients, getMeta } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
export default async function builderList({ pg = pgClients.client, query = {} }) {
|
|
4
|
+
|
|
5
|
+
const { pk } = await getMeta({ table: 'site.content_types' });
|
|
6
|
+
|
|
7
|
+
if (!pk) {
|
|
8
|
+
return { message: 'table not found', status: 404 };
|
|
9
|
+
}
|
|
10
|
+
const sql = `select a.content_type_id as id, a.* FROM site.content_types a
|
|
11
|
+
where ${query.content_type_id ? 'content_type_id=$1' : '1=1'}`
|
|
12
|
+
|
|
13
|
+
const { rows, rowCount: total } = await pg.query(sql, [query.content_type_id].filter((el) => el));
|
|
14
|
+
|
|
15
|
+
return { message: { total, rows }, status: 200 };
|
|
16
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { dataInsert, getMeta } from "@opengis/fastify-table/utils.js";
|
|
2
|
+
|
|
3
|
+
export default async function builderPost(req) {
|
|
4
|
+
const { user = {}, body = {} } = req;
|
|
5
|
+
|
|
6
|
+
const { pk } = await getMeta({ table: "site.content_types" });
|
|
7
|
+
|
|
8
|
+
if (!pk) {
|
|
9
|
+
return { message: "table not found", status: 404 };
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const resData = await dataInsert({
|
|
13
|
+
table: "site.content_types",
|
|
14
|
+
data: body,
|
|
15
|
+
uid: user?.uid,
|
|
16
|
+
});
|
|
17
|
+
// console.log(resData);
|
|
18
|
+
const res = resData?.rows[0];
|
|
19
|
+
|
|
20
|
+
return { id: res.content_type_id, rows: [res] };
|
|
21
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { dataUpdate, getMeta } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
export default async function builderPut(req) {
|
|
4
|
+
const { user = {}, body = {}, params = {} } = req;
|
|
5
|
+
if (!params.id) {
|
|
6
|
+
return { message: 'id is required', status: 400 };
|
|
7
|
+
}
|
|
8
|
+
const { pk } = await getMeta({ table: 'site.content_types' });
|
|
9
|
+
|
|
10
|
+
if (!pk) {
|
|
11
|
+
return { message: 'table not found', status: 404 };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const resData = await dataUpdate({
|
|
15
|
+
table: 'site.content_types',
|
|
16
|
+
data: body,
|
|
17
|
+
id: params.id,
|
|
18
|
+
});
|
|
19
|
+
// console.log(resData)
|
|
20
|
+
const res = resData;
|
|
21
|
+
|
|
22
|
+
return { id: res.content_type_id, rows: [res] };
|
|
23
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import cmsBuilderGet from './controllers/cms.builder.get.js';
|
|
2
|
+
import cmsBuilderList from './controllers/cms.builder.list.js';
|
|
3
|
+
import cmsBuilderPut from './controllers/cms.builder.put.js';
|
|
4
|
+
import cmsBuilderPost from './controllers/cms.builder.post.js';
|
|
5
|
+
import cmsBuilderDelete from './controllers/cms.builder.delete.js';
|
|
6
|
+
|
|
7
|
+
export default async function route(app) {
|
|
8
|
+
// builder add
|
|
9
|
+
app.post('/cms-builder', { config: { policy: ['site'] }}, cmsBuilderPost);
|
|
10
|
+
|
|
11
|
+
// builder edit
|
|
12
|
+
app.put('/cms-builder/:id', { config: { policy: ['site'] }}, cmsBuilderPut);
|
|
13
|
+
|
|
14
|
+
// builder list
|
|
15
|
+
app.get('/cms-builder', { config: { policy: ['site'] }}, cmsBuilderList);
|
|
16
|
+
|
|
17
|
+
// builder get
|
|
18
|
+
app.get('/cms-builder/:id', { config: { policy: ['site'] }}, cmsBuilderGet);
|
|
19
|
+
|
|
20
|
+
// builder delete
|
|
21
|
+
app.delete('/cms-builder/:id', { config: { policy: ['site'] }}, cmsBuilderDelete);
|
|
22
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { dataDelete, getMeta } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
export default async function categoryDelete({ user = {}, params = {} }) {
|
|
4
|
+
|
|
5
|
+
if (!params.id) {
|
|
6
|
+
return { message: 'id is required', status: 400 };
|
|
7
|
+
}
|
|
8
|
+
const { pk } = await getMeta({ table: 'site.categories' });
|
|
9
|
+
|
|
10
|
+
if (!pk) {
|
|
11
|
+
return { message: 'table not found', status: 404 };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const res = await dataDelete({
|
|
15
|
+
table: 'site.categories',
|
|
16
|
+
id: params.id,
|
|
17
|
+
uid: user?.uid
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
return { id: res.category_id, rows: [res] };
|
|
21
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { pgClients, getMeta, getTemplate } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
export default async function categoryGet({ pg = pgClients.client, params = {} }) {
|
|
4
|
+
|
|
5
|
+
const { pk } = await getMeta({ table: 'site.categories' });
|
|
6
|
+
|
|
7
|
+
if (!pk) {
|
|
8
|
+
return { message: 'table not found', status: 404 };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const { rows, rowCount: total } = await pg.query(
|
|
12
|
+
`select a.category_id as id, a.* FROM site.categories a
|
|
13
|
+
where a.category_id=$1`,
|
|
14
|
+
[params.id]
|
|
15
|
+
);
|
|
16
|
+
return { message: { total, rows }, status: 200 };
|
|
17
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { pgClients, getTemplate, getMeta } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
export default async function categoryList({ pg = pgClients.client, query = {} }) {
|
|
4
|
+
|
|
5
|
+
const { pk } = await getMeta({ table: 'site.categories' });
|
|
6
|
+
|
|
7
|
+
if (!pk) {
|
|
8
|
+
return { message: 'table not found', status: 404 };
|
|
9
|
+
}
|
|
10
|
+
const sql = `select a.category_id as id, a.* FROM site.categories a
|
|
11
|
+
where ${query.category_id ? 'category_id=$1' : '1=1'}`
|
|
12
|
+
|
|
13
|
+
const { rows, rowCount: total } = await pg.query(sql, [query.category_id].filter((el) => el));
|
|
14
|
+
|
|
15
|
+
return { message: { total, rows }, status: 200 };
|
|
16
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { dataInsert, getMeta } from "@opengis/fastify-table/utils.js";
|
|
2
|
+
|
|
3
|
+
export default async function categoryPost(req) {
|
|
4
|
+
const { user = {}, body = {} } = req;
|
|
5
|
+
|
|
6
|
+
const { pk } = await getMeta({ table: "site.categories" });
|
|
7
|
+
|
|
8
|
+
if (!pk) {
|
|
9
|
+
return { message: "table not found", status: 404 };
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const resData = await dataInsert({
|
|
13
|
+
table: "site.categories",
|
|
14
|
+
data: body,
|
|
15
|
+
uid: user?.uid,
|
|
16
|
+
});
|
|
17
|
+
// console.log(resData);
|
|
18
|
+
const res = resData?.rows[0];
|
|
19
|
+
|
|
20
|
+
return { id: res.category_id, rows: [res] };
|
|
21
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { dataUpdate, getMeta } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
export default async function categoryPut({ body = {}, params = {} }) {
|
|
4
|
+
|
|
5
|
+
if (!params.id) {
|
|
6
|
+
return { message: 'id is required', status: 400 };
|
|
7
|
+
}
|
|
8
|
+
const { pk } = await getMeta({ table: 'site.categories' });
|
|
9
|
+
|
|
10
|
+
if (!pk) {
|
|
11
|
+
return { message: 'table not found', status: 404 };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const resData = await dataUpdate({
|
|
15
|
+
table: 'site.categories',
|
|
16
|
+
data: body,
|
|
17
|
+
id: params.id,
|
|
18
|
+
});
|
|
19
|
+
// console.log(resData)
|
|
20
|
+
const res = resData;
|
|
21
|
+
|
|
22
|
+
return { id: res.category_id, rows: [res] };
|
|
23
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import cmsCategoryGet from './controllers/cms.category.get.js';
|
|
2
|
+
import cmsCategoryList from './controllers/cms.category.list.js';
|
|
3
|
+
import cmsCategoryPut from './controllers/cms.category.put.js';
|
|
4
|
+
import cmsCategoryPost from './controllers/cms.category.post.js';
|
|
5
|
+
import cmsCategoryDelete from './controllers/cms.category.delete.js'
|
|
6
|
+
|
|
7
|
+
export default async function route(app) {
|
|
8
|
+
// category add
|
|
9
|
+
app.post('/cms-category', {}, cmsCategoryPost);
|
|
10
|
+
|
|
11
|
+
// category edit
|
|
12
|
+
app.put('/cms-category/:id', {}, cmsCategoryPut);
|
|
13
|
+
|
|
14
|
+
// category list
|
|
15
|
+
app.get('/cms-category', { config: { policy: ['site'] }}, cmsCategoryList);
|
|
16
|
+
|
|
17
|
+
// category get
|
|
18
|
+
app.get('/cms-category/:id', {}, cmsCategoryGet);
|
|
19
|
+
|
|
20
|
+
// category delete
|
|
21
|
+
app.delete('/cms-category/:id', { config: { policy: ['site'] }}, cmsCategoryDelete);
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { dataDelete, getMeta } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
export default async function managerDelete({ user = {}, params = {} }) {
|
|
4
|
+
|
|
5
|
+
if (!params.id) {
|
|
6
|
+
return { message: 'id is required', status: 400 };
|
|
7
|
+
}
|
|
8
|
+
const { pk } = await getMeta({ table: 'site.contents' });
|
|
9
|
+
|
|
10
|
+
if (!pk) {
|
|
11
|
+
return { message: 'table not found', status: 404 };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const res = await dataDelete({
|
|
15
|
+
table: 'site.contents',
|
|
16
|
+
id: params.id,
|
|
17
|
+
uid: user?.uid
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
return { id: res.content_id, rows: [res] };
|
|
22
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { pgClients, getMeta } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
export default async function managerGet({ pg = pgClients.client, params = {} }) {
|
|
4
|
+
|
|
5
|
+
if (!params.template && params.id) return { message: 'bad request', status: 400 }
|
|
6
|
+
|
|
7
|
+
const { pk } = await getMeta({ table: 'site.contents' });
|
|
8
|
+
|
|
9
|
+
if (!pk) {
|
|
10
|
+
return { message: 'table not found', status: 404 };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { rows, rowCount: total } = await pg.query(
|
|
14
|
+
`select a.content_id as id, a.* FROM site.contents a
|
|
15
|
+
where template=$1 and content_id=$2`, [params.template, params.id]
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const { rows: type } = await pg.query(`select name, template, description, type from site.content_types where template=$1`, [params.template])
|
|
19
|
+
|
|
20
|
+
return { message: { total, rows, type: type[0] }, status: 200 };
|
|
21
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { pgClients, getMeta } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
const types = {
|
|
4
|
+
enabled: 'Switcher'
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export default async function builderList({ pg = pgClients.client, params = {} }) {
|
|
8
|
+
if (!params.template) {
|
|
9
|
+
return { message: 'not enougn params: template', status: 400 }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (!pg.pk?.['site.contents']) {
|
|
13
|
+
return { message: 'table not found', status: 404 };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { columns = [] } = await getMeta({ table: 'site.contents' });
|
|
17
|
+
|
|
18
|
+
const { rows, rowCount: total } = await pg.query(
|
|
19
|
+
`select a.content_id as id, a.* FROM site.contents a
|
|
20
|
+
where template=$1`, [params.template]
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const { rows: type } = await pg.query(`select name, template, description, type, columns from site.content_types where template=$1`, [params.template])
|
|
24
|
+
|
|
25
|
+
const columns1 = (type[0]?.columns || []).concat(
|
|
26
|
+
columns
|
|
27
|
+
.filter(el => !['cdate', 'editor_date', 'uid', 'editor_date'].includes(el.name))
|
|
28
|
+
.map(({ title, name }) => ({ title, name, type: types[name] || 'Text' }))
|
|
29
|
+
);
|
|
30
|
+
return { message: { total, rows, type: type[0], columns: columns1 }, status: 200 };
|
|
31
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { dataInsert, getMeta } from "@opengis/fastify-table/utils.js";
|
|
2
|
+
|
|
3
|
+
export default async function builderPost(req) {
|
|
4
|
+
const { user = {}, params= {}, body = {} } = req;
|
|
5
|
+
|
|
6
|
+
if (!params.template) return { message: 'bad request', status: 400 }
|
|
7
|
+
|
|
8
|
+
const { pk } = await getMeta({ table: "site.contents" });
|
|
9
|
+
|
|
10
|
+
if (!pk) {
|
|
11
|
+
return { message: "table not found", status: 404 };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const bodyModified = Object.assign(body, {
|
|
15
|
+
template: params.template
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
const resData = await dataInsert({
|
|
20
|
+
table: "site.contents",
|
|
21
|
+
data: bodyModified,
|
|
22
|
+
uid: user?.uid,
|
|
23
|
+
});
|
|
24
|
+
// console.log(resData);
|
|
25
|
+
const res = resData?.rows[0];
|
|
26
|
+
|
|
27
|
+
return { id: res.content_id, rows: [res] };
|
|
28
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { dataUpdate, getMeta } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
export default async function managerPut({ body = {}, params = {} }) {
|
|
4
|
+
|
|
5
|
+
if (!params.id) {
|
|
6
|
+
return { message: 'id is required', status: 400 };
|
|
7
|
+
}
|
|
8
|
+
const { pk } = await getMeta({ table: 'site.contents' });
|
|
9
|
+
|
|
10
|
+
if (!pk) {
|
|
11
|
+
return { message: 'table not found', status: 404 };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const resData = await dataUpdate({
|
|
15
|
+
table: 'site.contents',
|
|
16
|
+
data: body,
|
|
17
|
+
id: params.id,
|
|
18
|
+
});
|
|
19
|
+
// console.log(resData)
|
|
20
|
+
const res = resData;
|
|
21
|
+
|
|
22
|
+
return { id: res.content_id, rows: [res] };
|
|
23
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import cmsManagerGet from './controllers/cms.manager.get.js';
|
|
2
|
+
import cmsManagerList from './controllers/cms.manager.list.js';
|
|
3
|
+
import cmsManagerPut from './controllers/cms.manager.put.js';
|
|
4
|
+
import cmsManagerPost from './controllers/cms.manager.post.js';
|
|
5
|
+
import cmsManagerDelete from './controllers/cms.manager.delete.js';
|
|
6
|
+
|
|
7
|
+
export default async function route(app) {
|
|
8
|
+
// manager add
|
|
9
|
+
app.post('/cms-manager/:template', { config: { policy: ['site'] }}, cmsManagerPost);
|
|
10
|
+
|
|
11
|
+
// manager edit
|
|
12
|
+
app.put('/cms-manager/:id', { config: { policy: ['site'] }}, cmsManagerPut);
|
|
13
|
+
|
|
14
|
+
// manager list
|
|
15
|
+
app.get('/cms-manager/:template', { config: { policy: ['site'] }}, cmsManagerList);
|
|
16
|
+
|
|
17
|
+
// manager get
|
|
18
|
+
app.get('/cms-manager/:template/:id', { config: { policy: ['site'] }}, cmsManagerGet);
|
|
19
|
+
|
|
20
|
+
// manager delete
|
|
21
|
+
app.delete('/cms-manager/:id', { config: { policy: ['site'] }}, cmsManagerDelete);
|
|
22
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { rm } from 'node:fs/promises';
|
|
4
|
+
|
|
5
|
+
import { config, getToken, dataDelete, getFolder, pgClients } from "@opengis/fastify-table/utils.js";
|
|
6
|
+
|
|
7
|
+
const rootDir = getFolder(config, 'local');
|
|
8
|
+
|
|
9
|
+
export default async function deleteMedia({
|
|
10
|
+
pg = pgClients.client, params = {}, user = {},
|
|
11
|
+
}, reply) {
|
|
12
|
+
|
|
13
|
+
if (!params?.token) {
|
|
14
|
+
return reply.status(400).send('not enough params: token');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const tokenData = await getToken({
|
|
18
|
+
uid: user?.uid || 0,
|
|
19
|
+
token: params.token,
|
|
20
|
+
json: 1,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const { dir, name, relpath, id } = pg.pk?.['crm.media'] && tokenData?.type !== 'dir'
|
|
24
|
+
? await pg.query(`select media_id as id, uploaded_name as name, file_path as "relpath" from crm.media where $1 in (media_id, file_path)`, [tokenData?.id || tokenData?.relpath || params.token])
|
|
25
|
+
.then(el => el.rows?.[0] || {})
|
|
26
|
+
: tokenData;
|
|
27
|
+
|
|
28
|
+
if (!dir && !(id && relpath)) {
|
|
29
|
+
return reply.status(403).send('access restricted: root dir');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// delete file
|
|
33
|
+
if (id && relpath) {
|
|
34
|
+
const res = await dataDelete({
|
|
35
|
+
id,
|
|
36
|
+
table: 'crm.media',
|
|
37
|
+
uid: user?.uid || 0,
|
|
38
|
+
});
|
|
39
|
+
const filepath = path.join(rootDir, relpath);
|
|
40
|
+
|
|
41
|
+
if (existsSync(filepath)) {
|
|
42
|
+
await rm(filepath, { recursive: true });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
id: tokenData?.id || id,
|
|
47
|
+
name: res?.uploaded_name,
|
|
48
|
+
size: res?.size,
|
|
49
|
+
extension: res?.ext,
|
|
50
|
+
caption: res?.caption,
|
|
51
|
+
altname: res?.altname,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// delete directory
|
|
56
|
+
const dirpath = path.join(rootDir, relpath);
|
|
57
|
+
await rm(dirpath, { recursive: true });
|
|
58
|
+
return reply.status(200).send({ name: path.basename(relpath) });
|
|
59
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { rename, readdir } from 'node:fs/promises';
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
|
|
5
|
+
import { config, getToken, getFolder, dataUpdate, pgClients } from "@opengis/fastify-table/utils.js";
|
|
6
|
+
|
|
7
|
+
const rootDir = getFolder(config, 'local');
|
|
8
|
+
|
|
9
|
+
export default async function editMedia({
|
|
10
|
+
pg = pgClients.client, params = {}, user = {}, body = {},
|
|
11
|
+
}, reply) {
|
|
12
|
+
|
|
13
|
+
const tokenData = await getToken({
|
|
14
|
+
uid: user?.uid || 0,
|
|
15
|
+
token: params.token,
|
|
16
|
+
json: 1,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const objdata = pg.pk?.['crm.media'] && !tokenData
|
|
20
|
+
? await pg.query(`select media_id as id, uploaded_name as name, file_path as "relpath" from crm.media where media_id=$1`, [params.token]).then(el => el.rows?.[0] || {})
|
|
21
|
+
: tokenData;
|
|
22
|
+
|
|
23
|
+
const { id, name } = objdata;
|
|
24
|
+
const relpath = (objdata?.relpath || tokenData?.relpath)?.replace(/\\/g, '/');
|
|
25
|
+
|
|
26
|
+
if ((tokenData?.type === 'file' && !id) || !relpath) {
|
|
27
|
+
return reply.status(400).send('invalid params: token');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const data = {};
|
|
31
|
+
const oldfilepath = path.join(rootDir, relpath);
|
|
32
|
+
|
|
33
|
+
if (tokenData?.type === 'dir' && !body?.name) {
|
|
34
|
+
return reply.status(400).send('not enough body params: name');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (body?.name) {
|
|
38
|
+
const newfilepath = path.join(rootDir, path.dirname(relpath), body.name);
|
|
39
|
+
|
|
40
|
+
if (!existsSync(oldfilepath)) {
|
|
41
|
+
return reply.status(404).send('file / directory not found');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (existsSync(newfilepath)) {
|
|
45
|
+
return reply.status(400).send('file / directory with such name already exists');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// sync file path in db data
|
|
49
|
+
const arr = tokenData?.type === 'dir' ? await readdir(oldfilepath, { withFileTypes: true }) : [];
|
|
50
|
+
|
|
51
|
+
await rename(oldfilepath, newfilepath);
|
|
52
|
+
|
|
53
|
+
if (tokenData?.type === 'dir') {
|
|
54
|
+
const relpaths = arr.filter(el => el.isFile()).map(el => path.join(tokenData.relpath, el.name).replace(/\\/g, '/'));
|
|
55
|
+
const { rows = [] } = pg.pk?.['crm.media'] ? await pg.query(`select media_id as id, file_path as relpath from crm.media where file_path=any($1::text[])`, [relpaths]) : {};
|
|
56
|
+
await Promise.all(rows.map(async (el) => dataUpdate({
|
|
57
|
+
id: el.id,
|
|
58
|
+
table: 'crm.media',
|
|
59
|
+
data: {
|
|
60
|
+
file_path: el.relpath.replace(relpath.replace(/\\/g, '/'), path.join(path.dirname(relpath), body.name).replace(/\\/g, '/'))
|
|
61
|
+
},
|
|
62
|
+
uid: user?.uid || 0,
|
|
63
|
+
})));
|
|
64
|
+
return reply.status(200).send({
|
|
65
|
+
name: body.name,
|
|
66
|
+
relpath: path.join(path.dirname(relpath), body.name).replace(/\\/g, '/'),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
Object.assign(data, {
|
|
70
|
+
uploaded_name: body.name,
|
|
71
|
+
file_path: path.join(path.dirname(relpath), body.name).replace(/\\/g, '/'),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (body?.caption) Object.assign(data, { caption: body.caption });
|
|
76
|
+
if (body?.altname) Object.assign(data, { altname: body.altname });
|
|
77
|
+
|
|
78
|
+
const res = await dataUpdate({
|
|
79
|
+
id,
|
|
80
|
+
table: 'crm.media',
|
|
81
|
+
data,
|
|
82
|
+
uid: user?.uid || 0,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
id: tokenData?.id || id,
|
|
87
|
+
name: res?.uploaded_name,
|
|
88
|
+
relpath: res?.file_path,
|
|
89
|
+
size: res?.size,
|
|
90
|
+
extension: res?.ext,
|
|
91
|
+
caption: res?.caption,
|
|
92
|
+
altname: res?.altname,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
3
|
+
import { readdir, stat } from 'node:fs/promises';
|
|
4
|
+
|
|
5
|
+
import { config, getFolder, pgClients, setToken } from '@opengis/fastify-table/utils.js';
|
|
6
|
+
|
|
7
|
+
const rootDir = getFolder(config, 'local');
|
|
8
|
+
mkdirSync(path.join(rootDir, 'media'), { recursive: true });
|
|
9
|
+
|
|
10
|
+
export default async function listMedia(req, reply) {
|
|
11
|
+
const { pg = pgClients.client, query = {}, user = {} } = req;
|
|
12
|
+
const { dir } = query;
|
|
13
|
+
const dirpath = path.join(rootDir, 'media', dir || '');
|
|
14
|
+
|
|
15
|
+
if (dir && (typeof dir !== 'string' || dir.includes('..'))) {
|
|
16
|
+
return reply.status(403).send('invalid params: dir');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (!existsSync(dirpath)) {
|
|
20
|
+
return { data: [], dir };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const token = setToken({
|
|
24
|
+
ids: [JSON.stringify({ dir, name: dir, relpath: path.join('/media', dir || '').replace(/\\/g, '/') })],
|
|
25
|
+
uid: user?.uid || 0,
|
|
26
|
+
array: 1,
|
|
27
|
+
})?.[0];
|
|
28
|
+
|
|
29
|
+
const isDirectory = (await stat(dirpath)).isDirectory();
|
|
30
|
+
|
|
31
|
+
const items = isDirectory ? await readdir(dirpath) : [];
|
|
32
|
+
|
|
33
|
+
const relpaths = items.map(el => path.join('/media', dir || '', el).replace(/\\/g, '/'));
|
|
34
|
+
const { rows = [] } = await pg.query(`select media_id as id, uploaded_name as name, file_path as relpath from crm.media where file_path = any($1::text[])`, [relpaths]);
|
|
35
|
+
const ids = rows.reduce((acc, curr) => Object.assign(acc, { [curr.relpath]: curr.id }), {});
|
|
36
|
+
|
|
37
|
+
const data = await Promise.all(items.map(async (item) => {
|
|
38
|
+
const itempath = path.join(dirpath, item);
|
|
39
|
+
const extension = path.extname(item) === '' ? null : path.extname(item).split('.').pop();
|
|
40
|
+
const { ctime, mtime, size } = await stat(itempath);
|
|
41
|
+
const type = (await stat(itempath)).isDirectory() ? 'dir' : 'file';
|
|
42
|
+
const childList = type === 'dir' ? await readdir(itempath) : [];
|
|
43
|
+
const count = type === 'dir' ? childList.length : undefined;
|
|
44
|
+
return {
|
|
45
|
+
id: ids[path.join('/media', dir || '', item).replace(/\\/g, '/')],
|
|
46
|
+
name: item,
|
|
47
|
+
type,
|
|
48
|
+
count,
|
|
49
|
+
size,
|
|
50
|
+
extension,
|
|
51
|
+
token: setToken({
|
|
52
|
+
ids: [JSON.stringify({
|
|
53
|
+
id: ids[path.join('/media', dir || '', item).replace(/\\/g, '/')],
|
|
54
|
+
dir,
|
|
55
|
+
relpath: path.join('/media', dir || '', item).replace(/\\/g, '/'),
|
|
56
|
+
name: item,
|
|
57
|
+
type,
|
|
58
|
+
})],
|
|
59
|
+
uid: user?.uid || 0,
|
|
60
|
+
array: 1,
|
|
61
|
+
})[0],
|
|
62
|
+
ctime,
|
|
63
|
+
mtime,
|
|
64
|
+
};
|
|
65
|
+
}));
|
|
66
|
+
|
|
67
|
+
const result = { dir, token, data };
|
|
68
|
+
|
|
69
|
+
if (config.debug) {
|
|
70
|
+
Object.assign(result, { rootDir });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { stat } from 'node:fs/promises';
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
|
|
5
|
+
import { config, getToken, getFolder, pgClients } from "@opengis/fastify-table/utils.js";
|
|
6
|
+
|
|
7
|
+
const rootDir = getFolder(config, 'local');
|
|
8
|
+
|
|
9
|
+
export default async function metadataMedia({
|
|
10
|
+
pg = pgClients.client, params = {}, user = {},
|
|
11
|
+
}, reply) {
|
|
12
|
+
if (!params.token) {
|
|
13
|
+
return reply.status(400).send('not enough params: token');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const tokenData = await getToken({
|
|
17
|
+
uid: user?.uid || 0,
|
|
18
|
+
token: params.token,
|
|
19
|
+
json: 1,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const { relpath, caption, altname, id } = !tokenData && pg.pk?.['crm.media']
|
|
23
|
+
? await pg.query(`select media_id as id, file_path as "relpath", caption from crm.media where media_id=$1`, [params.token]).then(el => el.rows?.[0] || {})
|
|
24
|
+
: {};
|
|
25
|
+
|
|
26
|
+
if ((!tokenData?.name || tokenData?.type !== 'file') && !relpath) {
|
|
27
|
+
return reply.status(400).send('invalid params: token');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const filepath = tokenData?.name
|
|
31
|
+
? path.join(rootDir, 'media', tokenData.dir || '', tokenData.name)
|
|
32
|
+
: path.join(rootDir, relpath);
|
|
33
|
+
|
|
34
|
+
if (!existsSync(filepath)) {
|
|
35
|
+
return reply.status(404).send('file not found');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const stats = await stat(filepath);
|
|
39
|
+
const { ctime, mtime, size } = stats;
|
|
40
|
+
|
|
41
|
+
return reply.status(200).send({
|
|
42
|
+
id: tokenData?.id || id,
|
|
43
|
+
name: path.basename(filepath),
|
|
44
|
+
size,
|
|
45
|
+
extension: path.extname(filepath)?.split?.('.')?.pop?.(),
|
|
46
|
+
ctime, // creation timestamp
|
|
47
|
+
mtime, // last modification timestamp
|
|
48
|
+
caption,
|
|
49
|
+
altname,
|
|
50
|
+
});
|
|
51
|
+
}
|