directus
This commit is contained in:
18
.env
18
.env
@@ -20,12 +20,12 @@ MAIL_PASSWORD=4592fcb94599ee1a45b4ac2386fd0a64-102c75d8-ca2870e6
|
|||||||
MAIL_FROM="KLZ Cables <postmaster@mg.mintel.me>"
|
MAIL_FROM="KLZ Cables <postmaster@mg.mintel.me>"
|
||||||
MAIL_RECIPIENTS=marc@cablecreations.de,info@klz-cables.com
|
MAIL_RECIPIENTS=marc@cablecreations.de,info@klz-cables.com
|
||||||
|
|
||||||
# Strapi
|
# Directus
|
||||||
STRAPI_DATABASE_NAME=strapi
|
DIRECTUS_URL=https://cms.klz-cables.com
|
||||||
STRAPI_DATABASE_USERNAME=strapi
|
DIRECTUS_KEY=59fb8f4c1a51b18fe28ad947f713914e
|
||||||
STRAPI_DATABASE_PASSWORD=strapi_password_change_me
|
DIRECTUS_SECRET=7459038d41401dfb11254cf7f1ef2d0f
|
||||||
APP_KEYS=toBeModified1,toBeModified2,toBeModified3,toBeModified4
|
DIRECTUS_ADMIN_EMAIL=admin@klz-cables.com
|
||||||
API_TOKEN_SALT=tobemodified
|
DIRECTUS_ADMIN_PASSWORD=admin
|
||||||
ADMIN_JWT_SECRET=tobemodified
|
DIRECTUS_DB_NAME=directus
|
||||||
TRANSFER_TOKEN_SALT=tobemodified
|
DIRECTUS_DB_USER=directus
|
||||||
JWT_SECRET=tobemodified
|
DIRECTUS_DB_PASSWORD=directus
|
||||||
|
|||||||
@@ -85,10 +85,21 @@ jobs:
|
|||||||
MAIL_FROM=${{ secrets.MAIL_FROM }}
|
MAIL_FROM=${{ secrets.MAIL_FROM }}
|
||||||
MAIL_RECIPIENTS=${{ secrets.MAIL_RECIPIENTS }}
|
MAIL_RECIPIENTS=${{ secrets.MAIL_RECIPIENTS }}
|
||||||
|
|
||||||
|
# Directus
|
||||||
|
DIRECTUS_URL=https://cms.klz-cables.com
|
||||||
|
DIRECTUS_KEY=${{ secrets.DIRECTUS_KEY }}
|
||||||
|
DIRECTUS_SECRET=${{ secrets.DIRECTUS_SECRET }}
|
||||||
|
DIRECTUS_ADMIN_EMAIL=${{ secrets.DIRECTUS_ADMIN_EMAIL }}
|
||||||
|
DIRECTUS_ADMIN_PASSWORD=${{ secrets.DIRECTUS_ADMIN_PASSWORD }}
|
||||||
|
DIRECTUS_DB_NAME=directus
|
||||||
|
DIRECTUS_DB_USER=directus
|
||||||
|
DIRECTUS_DB_PASSWORD=${{ secrets.DIRECTUS_DB_PASSWORD }}
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Upload .env and deploy
|
# Upload .env and docker-compose.yml
|
||||||
scp -o StrictHostKeyChecking=accept-new /tmp/klz-cables.env root@alpha.mintel.me:/home/deploy/sites/klz-cables.com/.env
|
scp -o StrictHostKeyChecking=accept-new /tmp/klz-cables.env root@alpha.mintel.me:/home/deploy/sites/klz-cables.com/.env
|
||||||
|
scp -o StrictHostKeyChecking=accept-new docker-compose.yml root@alpha.mintel.me:/home/deploy/sites/klz-cables.com/docker-compose.yml
|
||||||
|
|
||||||
ssh -o StrictHostKeyChecking=accept-new root@alpha.mintel.me bash << EOF
|
ssh -o StrictHostKeyChecking=accept-new root@alpha.mintel.me bash << EOF
|
||||||
set -e
|
set -e
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
node_modules
|
|
||||||
.tmp
|
|
||||||
.cache
|
|
||||||
dist
|
|
||||||
build
|
|
||||||
.env
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
FROM node:20-alpine
|
|
||||||
|
|
||||||
# Installing libvips-dev for sharp Compatibility
|
|
||||||
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev vips-dev git > /dev/null 2>&1
|
|
||||||
|
|
||||||
WORKDIR /opt/
|
|
||||||
COPY package.json package-lock.json ./
|
|
||||||
RUN npm install -g node-gyp
|
|
||||||
RUN npm config set fetch-retry-maxtimeout 600000 -g && npm ci
|
|
||||||
ENV PATH=/opt/node_modules/.bin:$PATH
|
|
||||||
|
|
||||||
WORKDIR /opt/app
|
|
||||||
COPY . .
|
|
||||||
RUN NODE_ENV=production npm run build
|
|
||||||
EXPOSE 1337
|
|
||||||
CMD ["npm", "run", "develop"]
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
export default ({ env }) => ({
|
|
||||||
auth: {
|
|
||||||
secret: env('ADMIN_JWT_SECRET'),
|
|
||||||
},
|
|
||||||
apiToken: {
|
|
||||||
salt: env('API_TOKEN_SALT'),
|
|
||||||
},
|
|
||||||
transfer: {
|
|
||||||
token: {
|
|
||||||
salt: env('TRANSFER_TOKEN_SALT'),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
export default {
|
|
||||||
rest: {
|
|
||||||
defaultLimit: 25,
|
|
||||||
maxLimit: 100,
|
|
||||||
withCount: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
export default ({ env }) => ({
|
|
||||||
connection: {
|
|
||||||
client: 'postgres',
|
|
||||||
connection: {
|
|
||||||
host: env('DATABASE_HOST', '127.0.0.1'),
|
|
||||||
port: env.int('DATABASE_PORT', 5432),
|
|
||||||
database: env('DATABASE_NAME', 'strapi'),
|
|
||||||
user: env('DATABASE_USERNAME', 'strapi'),
|
|
||||||
password: env('DATABASE_PASSWORD', 'strapi'),
|
|
||||||
ssl: env.bool('DATABASE_SSL', false),
|
|
||||||
},
|
|
||||||
pool: { min: env.int('DATABASE_POOL_MIN', 2), max: env.int('DATABASE_POOL_MAX', 10) },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
export default ({ env }) => ({
|
|
||||||
host: env('HOST', '0.0.0.0'),
|
|
||||||
port: env.int('PORT', 1337),
|
|
||||||
app: {
|
|
||||||
keys: env.array('APP_KEYS'),
|
|
||||||
},
|
|
||||||
webhooks: {
|
|
||||||
populateRelations: env.bool('WEBHOOKS_POPULATE_RELATIONS', false),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
19637
cms/package-lock.json
generated
19637
cms/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,39 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "klz-cms",
|
|
||||||
"private": true,
|
|
||||||
"version": "0.1.0",
|
|
||||||
"description": "Strapi CMS for KLZ Cables",
|
|
||||||
"scripts": {
|
|
||||||
"develop": "strapi develop",
|
|
||||||
"start": "strapi start",
|
|
||||||
"build": "strapi build",
|
|
||||||
"strapi": "strapi"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@strapi/strapi": "4.25.11",
|
|
||||||
"@strapi/plugin-users-permissions": "4.25.11",
|
|
||||||
"@strapi/plugin-i18n": "4.25.11",
|
|
||||||
"pg": "8.11.3",
|
|
||||||
"react": "^18.0.0",
|
|
||||||
"react-dom": "^18.0.0",
|
|
||||||
"react-router-dom": "^5.2.0",
|
|
||||||
"styled-components": "^5.2.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/node": "^18.0.0",
|
|
||||||
"@types/react": "^18.0.0",
|
|
||||||
"@types/react-dom": "^18.0.0",
|
|
||||||
"typescript": "^5.0.0"
|
|
||||||
},
|
|
||||||
"author": {
|
|
||||||
"name": "A Strapi developer"
|
|
||||||
},
|
|
||||||
"strapi": {
|
|
||||||
"uuid": "klz-cms"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18.0.0 <=20.x.x",
|
|
||||||
"npm": ">=6.0.0"
|
|
||||||
},
|
|
||||||
"license": "MIT"
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
{
|
|
||||||
"kind": "collectionType",
|
|
||||||
"collectionName": "applications",
|
|
||||||
"info": {
|
|
||||||
"singularName": "application",
|
|
||||||
"pluralName": "applications",
|
|
||||||
"displayName": "Application"
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"draftAndPublish": false
|
|
||||||
},
|
|
||||||
"attributes": {
|
|
||||||
"job": {
|
|
||||||
"type": "relation",
|
|
||||||
"relation": "manyToOne",
|
|
||||||
"target": "api::job.job"
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"email": {
|
|
||||||
"type": "email",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"resume": {
|
|
||||||
"type": "media",
|
|
||||||
"multiple": false,
|
|
||||||
"required": true,
|
|
||||||
"allowedTypes": [
|
|
||||||
"files"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"message": {
|
|
||||||
"type": "text"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreController('api::application.application');
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreRouter('api::application.application');
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreService('api::application.application');
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
{
|
|
||||||
"kind": "collectionType",
|
|
||||||
"collectionName": "categories",
|
|
||||||
"info": {
|
|
||||||
"singularName": "category",
|
|
||||||
"pluralName": "categories",
|
|
||||||
"displayName": "Category"
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"draftAndPublish": false
|
|
||||||
},
|
|
||||||
"pluginOptions": {
|
|
||||||
"i18n": {
|
|
||||||
"localized": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"attributes": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"required": true,
|
|
||||||
"pluginOptions": {
|
|
||||||
"i18n": {
|
|
||||||
"localized": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"slug": {
|
|
||||||
"type": "uid",
|
|
||||||
"targetField": "name",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"products": {
|
|
||||||
"type": "relation",
|
|
||||||
"relation": "manyToMany",
|
|
||||||
"target": "api::product.product",
|
|
||||||
"mappedBy": "categories"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreController('api::category.category');
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreRouter('api::category.category');
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreService('api::category.category');
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"kind": "collectionType",
|
|
||||||
"collectionName": "contact_messages",
|
|
||||||
"info": {
|
|
||||||
"singularName": "contact-message",
|
|
||||||
"pluralName": "contact-messages",
|
|
||||||
"displayName": "Contact Message"
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"draftAndPublish": false
|
|
||||||
},
|
|
||||||
"attributes": {
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"email": {
|
|
||||||
"type": "email",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"subject": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"message": {
|
|
||||||
"type": "text",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreController('api::contact-message.contact-message');
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreRouter('api::contact-message.contact-message');
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreService('api::contact-message.contact-message');
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"kind": "collectionType",
|
|
||||||
"collectionName": "jobs",
|
|
||||||
"info": {
|
|
||||||
"singularName": "job",
|
|
||||||
"pluralName": "jobs",
|
|
||||||
"displayName": "Job"
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"draftAndPublish": true
|
|
||||||
},
|
|
||||||
"pluginOptions": {
|
|
||||||
"i18n": {
|
|
||||||
"localized": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"attributes": {
|
|
||||||
"title": {
|
|
||||||
"type": "string",
|
|
||||||
"required": true,
|
|
||||||
"pluginOptions": {
|
|
||||||
"i18n": {
|
|
||||||
"localized": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"description": {
|
|
||||||
"type": "richtext",
|
|
||||||
"pluginOptions": {
|
|
||||||
"i18n": {
|
|
||||||
"localized": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"location": {
|
|
||||||
"type": "string",
|
|
||||||
"pluginOptions": {
|
|
||||||
"i18n": {
|
|
||||||
"localized": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreController('api::job.job');
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreRouter('api::job.job');
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreService('api::job.job');
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
{
|
|
||||||
"kind": "collectionType",
|
|
||||||
"collectionName": "products",
|
|
||||||
"info": {
|
|
||||||
"singularName": "product",
|
|
||||||
"pluralName": "products",
|
|
||||||
"displayName": "Product",
|
|
||||||
"description": ""
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"draftAndPublish": true
|
|
||||||
},
|
|
||||||
"pluginOptions": {
|
|
||||||
"i18n": {
|
|
||||||
"localized": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"attributes": {
|
|
||||||
"title": {
|
|
||||||
"type": "string",
|
|
||||||
"required": true,
|
|
||||||
"pluginOptions": {
|
|
||||||
"i18n": {
|
|
||||||
"localized": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sku": {
|
|
||||||
"type": "uid",
|
|
||||||
"targetField": "title",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"description": {
|
|
||||||
"type": "text",
|
|
||||||
"pluginOptions": {
|
|
||||||
"i18n": {
|
|
||||||
"localized": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"application": {
|
|
||||||
"type": "text",
|
|
||||||
"pluginOptions": {
|
|
||||||
"i18n": {
|
|
||||||
"localized": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"content": {
|
|
||||||
"type": "richtext",
|
|
||||||
"pluginOptions": {
|
|
||||||
"i18n": {
|
|
||||||
"localized": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"images": {
|
|
||||||
"type": "media",
|
|
||||||
"multiple": true,
|
|
||||||
"required": false,
|
|
||||||
"allowedTypes": [
|
|
||||||
"images"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"categories": {
|
|
||||||
"type": "relation",
|
|
||||||
"relation": "manyToMany",
|
|
||||||
"target": "api::category.category",
|
|
||||||
"inversedBy": "products"
|
|
||||||
},
|
|
||||||
"technicalData": {
|
|
||||||
"type": "json",
|
|
||||||
"pluginOptions": {
|
|
||||||
"i18n": {
|
|
||||||
"localized": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreController('api::product.product');
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreRouter('api::product.product');
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreService('api::product.product');
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
{
|
|
||||||
"kind": "singleType",
|
|
||||||
"collectionName": "settings",
|
|
||||||
"info": {
|
|
||||||
"singularName": "setting",
|
|
||||||
"pluralName": "settings",
|
|
||||||
"displayName": "Setting"
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"draftAndPublish": true
|
|
||||||
},
|
|
||||||
"pluginOptions": {
|
|
||||||
"i18n": {
|
|
||||||
"localized": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"attributes": {
|
|
||||||
"siteName": {
|
|
||||||
"type": "string",
|
|
||||||
"pluginOptions": {
|
|
||||||
"i18n": {
|
|
||||||
"localized": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"siteDescription": {
|
|
||||||
"type": "text",
|
|
||||||
"pluginOptions": {
|
|
||||||
"i18n": {
|
|
||||||
"localized": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"logo": {
|
|
||||||
"type": "media",
|
|
||||||
"multiple": false,
|
|
||||||
"allowedTypes": [
|
|
||||||
"images"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreController('api::setting.setting');
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreRouter('api::setting.setting');
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import { factories } from '@strapi/strapi';
|
|
||||||
export default factories.createCoreService('api::setting.setting');
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
export default {
|
|
||||||
/**
|
|
||||||
* An asynchronous register function that runs before
|
|
||||||
* your application is initialized.
|
|
||||||
*
|
|
||||||
* This gives you an opportunity to extend code.
|
|
||||||
*/
|
|
||||||
register(/*{ strapi }*/) {},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An asynchronous bootstrap function that runs before
|
|
||||||
* your application gets started.
|
|
||||||
*
|
|
||||||
* This gives you an opportunity to set up your data model,
|
|
||||||
* run jobs, or perform some special logic.
|
|
||||||
*/
|
|
||||||
bootstrap(/*{ strapi }*/) {},
|
|
||||||
};
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "@strapi/typescript-utils/tsconfigs/server",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "dist",
|
|
||||||
"rootDir": "."
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"src/**/*.ts",
|
|
||||||
"config/**/*.ts",
|
|
||||||
"src/**/*.tsx"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"node_modules/",
|
|
||||||
"build/",
|
|
||||||
"dist/",
|
|
||||||
".cache/",
|
|
||||||
".tmp/",
|
|
||||||
"src/admin/",
|
|
||||||
"**/*.test.ts",
|
|
||||||
"src/plugins/**"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,23 @@
|
|||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
env_file:
|
image: node:20-alpine
|
||||||
- .env
|
working_dir: /app
|
||||||
cms:
|
command: sh -c "npm install && npx next dev"
|
||||||
ports:
|
volumes:
|
||||||
- "1337:1337"
|
- .:/app
|
||||||
|
environment:
|
||||||
|
NODE_ENV: development
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.klz-app-local.rule=Host(`klz.local`)"
|
||||||
|
- "traefik.http.routers.klz-app-local.entrypoints=web"
|
||||||
|
- "traefik.http.routers.klz-app-local.service=klz-cables"
|
||||||
|
|
||||||
|
directus:
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.klz-directus-local.rule=Host(`cms.klz.local`)"
|
||||||
|
- "traefik.http.routers.klz-directus-local.entrypoints=web"
|
||||||
|
- "traefik.http.routers.klz-directus-local.service=klz-directus"
|
||||||
|
environment:
|
||||||
|
PUBLIC_URL: http://cms.klz.local
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ services:
|
|||||||
restart: always
|
restart: always
|
||||||
networks:
|
networks:
|
||||||
- infra
|
- infra
|
||||||
ports:
|
|
||||||
- "3000:3000"
|
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
labels:
|
labels:
|
||||||
@@ -28,55 +26,54 @@ services:
|
|||||||
# Middlewares
|
# Middlewares
|
||||||
- "traefik.http.routers.klz-cables.middlewares=klz-forward,compress"
|
- "traefik.http.routers.klz-cables.middlewares=klz-forward,compress"
|
||||||
|
|
||||||
cms:
|
directus:
|
||||||
build:
|
image: directus/directus:10.10
|
||||||
context: ./cms
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
restart: always
|
restart: always
|
||||||
networks:
|
networks:
|
||||||
- infra
|
- infra
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
DATABASE_CLIENT: postgres
|
KEY: ${DIRECTUS_KEY}
|
||||||
DATABASE_HOST: cms-db
|
SECRET: ${DIRECTUS_SECRET}
|
||||||
DATABASE_PORT: 5432
|
ADMIN_EMAIL: ${DIRECTUS_ADMIN_EMAIL}
|
||||||
DATABASE_NAME: ${STRAPI_DATABASE_NAME:-strapi}
|
ADMIN_PASSWORD: ${DIRECTUS_ADMIN_PASSWORD}
|
||||||
DATABASE_USERNAME: ${STRAPI_DATABASE_USERNAME:-strapi}
|
DB_CLIENT: 'pg'
|
||||||
DATABASE_PASSWORD: ${STRAPI_DATABASE_PASSWORD:-strapi}
|
DB_HOST: 'directus-db'
|
||||||
NODE_ENV: ${NODE_ENV:-development}
|
DB_PORT: '5432'
|
||||||
STRAPI_URL: ${STRAPI_URL:-https://cms.klz-cables.com}
|
DB_DATABASE: ${DIRECTUS_DB_NAME:-directus}
|
||||||
|
DB_USER: ${DIRECTUS_DB_USER:-directus}
|
||||||
|
DB_PASSWORD: ${DIRECTUS_DB_PASSWORD:-directus}
|
||||||
|
WEBSOCKETS_ENABLED: 'true'
|
||||||
|
PUBLIC_URL: ${DIRECTUS_URL:-https://cms.klz-cables.com}
|
||||||
volumes:
|
volumes:
|
||||||
- ./cms/config:/opt/app/config
|
- ./directus/uploads:/directus/uploads
|
||||||
- ./cms/src:/opt/app/src
|
- ./directus/extensions:/directus/extensions
|
||||||
- ./cms/package.json:/opt/app/package.json
|
|
||||||
- ./cms/package-lock.json:/opt/app/package-lock.json
|
|
||||||
- ./cms/public/uploads:/opt/app/public/uploads
|
|
||||||
labels:
|
labels:
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.klz-cms.rule=Host(`cms.klz-cables.com`) || Host(`cms-staging.klz-cables.com`)"
|
- "traefik.http.routers.klz-directus.rule=Host(`cms.klz-cables.com`) || Host(`cms-staging.klz-cables.com`)"
|
||||||
- "traefik.http.routers.klz-cms.entrypoints=websecure"
|
- "traefik.http.routers.klz-directus.entrypoints=websecure"
|
||||||
- "traefik.http.routers.klz-cms.tls.certresolver=le"
|
- "traefik.http.routers.klz-directus.tls.certresolver=le"
|
||||||
- "traefik.http.routers.klz-cms.tls=true"
|
- "traefik.http.routers.klz-directus.tls=true"
|
||||||
- "traefik.http.services.klz-cms.loadbalancer.server.port=1337"
|
- "traefik.http.services.klz-directus.loadbalancer.server.port=8055"
|
||||||
|
|
||||||
cms-db:
|
directus-db:
|
||||||
image: postgres:16-alpine
|
image: postgres:15-alpine
|
||||||
restart: always
|
restart: always
|
||||||
networks:
|
networks:
|
||||||
- infra
|
- infra
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_DB: ${STRAPI_DATABASE_NAME:-strapi}
|
POSTGRES_DB: ${DIRECTUS_DB_NAME:-directus}
|
||||||
POSTGRES_USER: ${STRAPI_DATABASE_USERNAME:-strapi}
|
POSTGRES_USER: ${DIRECTUS_DB_USER:-directus}
|
||||||
POSTGRES_PASSWORD: ${STRAPI_DATABASE_PASSWORD:-strapi}
|
POSTGRES_PASSWORD: ${DIRECTUS_DB_PASSWORD:-directus}
|
||||||
volumes:
|
volumes:
|
||||||
- cms-db-data:/var/lib/postgresql/data
|
- directus-db-data:/var/lib/postgresql/data
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
infra:
|
infra:
|
||||||
external: true
|
external: true
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
cms-db-data:
|
directus-db-data:
|
||||||
|
|||||||
81
docker-compose.yml.bak
Normal file
81
docker-compose.yml.bak
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
services:
|
||||||
|
app:
|
||||||
|
image: registry.infra.mintel.me/mintel/klz-cables.com:latest
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- infra
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
# HTTP ⇒ HTTPS redirect
|
||||||
|
- "traefik.http.routers.klz-cables-web.rule=(Host(`klz-cables.com`) || Host(`www.klz-cables.com`) || Host(`staging.klz-cables.com`)) && !PathPrefix(`/.well-known/acme-challenge/`)"
|
||||||
|
- "traefik.http.routers.klz-cables-web.entrypoints=web"
|
||||||
|
- "traefik.http.routers.klz-cables-web.middlewares=redirect-https"
|
||||||
|
# HTTPS router
|
||||||
|
- "traefik.http.routers.klz-cables.rule=Host(`klz-cables.com`) || Host(`www.klz-cables.com`) || Host(`staging.klz-cables.com`)"
|
||||||
|
- "traefik.http.routers.klz-cables.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.klz-cables.tls.certresolver=le"
|
||||||
|
- "traefik.http.routers.klz-cables.tls=true"
|
||||||
|
- "traefik.http.routers.klz-cables.service=klz-cables"
|
||||||
|
- "traefik.http.services.klz-cables.loadbalancer.server.port=3000"
|
||||||
|
- "traefik.http.services.klz-cables.loadbalancer.server.scheme=http"
|
||||||
|
# Forwarded Headers
|
||||||
|
- "traefik.http.middlewares.klz-forward.headers.customrequestheaders.X-Forwarded-Proto=https"
|
||||||
|
- "traefik.http.middlewares.klz-forward.headers.customrequestheaders.X-Forwarded-Ssl=on"
|
||||||
|
# Middlewares
|
||||||
|
- "traefik.http.routers.klz-cables.middlewares=klz-forward,compress"
|
||||||
|
|
||||||
|
cms:
|
||||||
|
build:
|
||||||
|
context: ./cms
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- infra
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
DATABASE_CLIENT: postgres
|
||||||
|
DATABASE_HOST: cms-db
|
||||||
|
DATABASE_PORT: 5432
|
||||||
|
DATABASE_NAME: ${STRAPI_DATABASE_NAME:-strapi}
|
||||||
|
DATABASE_USERNAME: ${STRAPI_DATABASE_USERNAME:-strapi}
|
||||||
|
DATABASE_PASSWORD: ${STRAPI_DATABASE_PASSWORD:-strapi}
|
||||||
|
NODE_ENV: ${NODE_ENV:-development}
|
||||||
|
STRAPI_URL: ${STRAPI_URL:-https://cms.klz-cables.com}
|
||||||
|
volumes:
|
||||||
|
- ./cms/config:/opt/app/config
|
||||||
|
- ./cms/src:/opt/app/src
|
||||||
|
- ./cms/package.json:/opt/app/package.json
|
||||||
|
- ./cms/package-lock.json:/opt/app/package-lock.json
|
||||||
|
- ./cms/public/uploads:/opt/app/public/uploads
|
||||||
|
- ./cms/dist:/opt/app/dist
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.klz-cms.rule=Host(`cms.klz-cables.com`) || Host(`cms-staging.klz-cables.com`)"
|
||||||
|
- "traefik.http.routers.klz-cms.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.klz-cms.tls.certresolver=le"
|
||||||
|
- "traefik.http.routers.klz-cms.tls=true"
|
||||||
|
- "traefik.http.services.klz-cms.loadbalancer.server.port=1337"
|
||||||
|
|
||||||
|
cms-db:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- infra
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: ${STRAPI_DATABASE_NAME:-strapi}
|
||||||
|
POSTGRES_USER: ${STRAPI_DATABASE_USERNAME:-strapi}
|
||||||
|
POSTGRES_PASSWORD: ${STRAPI_DATABASE_PASSWORD:-strapi}
|
||||||
|
volumes:
|
||||||
|
- cms-db-data:/var/lib/postgresql/data
|
||||||
|
|
||||||
|
networks:
|
||||||
|
infra:
|
||||||
|
external: true
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
cms-db-data:
|
||||||
111
lib/directus.ts
Normal file
111
lib/directus.ts
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import { createDirectus, rest, staticToken, authentication, readItems, readItem } from '@directus/sdk';
|
||||||
|
|
||||||
|
const DIRECTUS_URL = process.env.DIRECTUS_URL || 'http://localhost:8055';
|
||||||
|
// We use Admin credentials for server-side operations if no token is provided
|
||||||
|
// This approach allows "auto-connect" without manual token generation
|
||||||
|
const DIRECTUS_EMAIL = process.env.DIRECTUS_ADMIN_EMAIL;
|
||||||
|
const DIRECTUS_PASSWORD = process.env.DIRECTUS_ADMIN_PASSWORD;
|
||||||
|
|
||||||
|
// Use a static token if provided (preferred for prod), otherwise fall back to admin auth
|
||||||
|
const DIRECTUS_TOKEN = process.env.DIRECTUS_API_TOKEN;
|
||||||
|
|
||||||
|
// Initialize the client
|
||||||
|
const client = createDirectus(DIRECTUS_URL)
|
||||||
|
.with(rest())
|
||||||
|
.with(authentication());
|
||||||
|
|
||||||
|
// Helper to authenticate if needed
|
||||||
|
async function ensureAuthenticated() {
|
||||||
|
if (DIRECTUS_TOKEN) {
|
||||||
|
client.setToken(DIRECTUS_TOKEN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DIRECTUS_EMAIL && DIRECTUS_PASSWORD) {
|
||||||
|
// Check if we already have a valid token (optional optimization, but simple login is robust)
|
||||||
|
try {
|
||||||
|
await client.login(DIRECTUS_EMAIL, DIRECTUS_PASSWORD);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to authenticate with Directus:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Product {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
sku: string;
|
||||||
|
description: string;
|
||||||
|
application: string;
|
||||||
|
content: string; // rich text
|
||||||
|
technical_data: any; // json
|
||||||
|
locale: string;
|
||||||
|
images?: {
|
||||||
|
directus_files_id: string;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maps Directus response to match our internal Product interface (mimicking Strapi for now)
|
||||||
|
function mapDirectusProduct(item: any): any {
|
||||||
|
return {
|
||||||
|
id: item.id,
|
||||||
|
title: item.title,
|
||||||
|
sku: item.sku,
|
||||||
|
description: item.description,
|
||||||
|
application: item.application,
|
||||||
|
content: item.content,
|
||||||
|
technicalData: item.technical_data,
|
||||||
|
locale: item.locale || 'de', // default
|
||||||
|
// Map images structure if needed
|
||||||
|
images: item.images ? {
|
||||||
|
data: item.images.map((img: any) => ({
|
||||||
|
attributes: {
|
||||||
|
url: `${DIRECTUS_URL}/assets/${img.directus_files_id}`,
|
||||||
|
alternativeText: img.caption || ''
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
} : undefined
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getProducts(locale: string = 'de') {
|
||||||
|
await ensureAuthenticated();
|
||||||
|
try {
|
||||||
|
const items = await client.request(readItems('products', {
|
||||||
|
filter: {
|
||||||
|
_and: [
|
||||||
|
{ locale: { _eq: locale } }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
fields: ['*', 'images.directus_files_id']
|
||||||
|
}));
|
||||||
|
|
||||||
|
return items.map(mapDirectusProduct);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching products from Directus:', error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getProductBySku(sku: string, locale: string = 'de') {
|
||||||
|
await ensureAuthenticated();
|
||||||
|
try {
|
||||||
|
const items = await client.request(readItems('products', {
|
||||||
|
filter: {
|
||||||
|
_and: [
|
||||||
|
{ sku: { _eq: sku } },
|
||||||
|
{ locale: { _eq: locale } }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
fields: ['*', 'images.directus_files_id']
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!items || items.length === 0) return null;
|
||||||
|
return mapDirectusProduct(items[0]);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error fetching product ${sku} from Directus:`, error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default client;
|
||||||
13
package-lock.json
generated
13
package-lock.json
generated
@@ -8,6 +8,7 @@
|
|||||||
"name": "klz-cables-nextjs",
|
"name": "klz-cables-nextjs",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@directus/sdk": "^18.0.3",
|
||||||
"@react-email/components": "^1.0.6",
|
"@react-email/components": "^1.0.6",
|
||||||
"@react-pdf/renderer": "^4.3.2",
|
"@react-pdf/renderer": "^4.3.2",
|
||||||
"@sentry/nextjs": "^8.55.0",
|
"@sentry/nextjs": "^8.55.0",
|
||||||
@@ -1360,6 +1361,18 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@directus/sdk": {
|
||||||
|
"version": "18.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@directus/sdk/-/sdk-18.0.3.tgz",
|
||||||
|
"integrity": "sha512-PnEDRDqr2x/DG3HZ3qxU7nFp2nW6zqJqswjii57NhriXgTz4TBUI8NmSdzQvnyHuTL9J0nedYfQGfW4v8odS1A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/directus/directus?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@emnapi/core": {
|
"node_modules/@emnapi/core": {
|
||||||
"version": "1.7.1",
|
"version": "1.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz",
|
||||||
|
|||||||
12
package.json
12
package.json
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@directus/sdk": "^18.0.3",
|
||||||
"@react-email/components": "^1.0.6",
|
"@react-email/components": "^1.0.6",
|
||||||
"@react-pdf/renderer": "^4.3.2",
|
"@react-pdf/renderer": "^4.3.2",
|
||||||
"@sentry/nextjs": "^8.55.0",
|
"@sentry/nextjs": "^8.55.0",
|
||||||
@@ -57,7 +58,8 @@
|
|||||||
"name": "klz-cables-nextjs",
|
"name": "klz-cables-nextjs",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "docker network create infra 2>/dev/null || true && docker-compose up -d",
|
||||||
|
"dev:local": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
@@ -65,13 +67,7 @@
|
|||||||
"test": "vitest run --passWithNoTests",
|
"test": "vitest run --passWithNoTests",
|
||||||
"test:og": "vitest run tests/og-image.test.ts",
|
"test:og": "vitest run tests/og-image.test.ts",
|
||||||
"pdf:datasheets": "tsx ./scripts/generate-pdf-datasheets.ts",
|
"pdf:datasheets": "tsx ./scripts/generate-pdf-datasheets.ts",
|
||||||
"pdf:datasheets:legacy": "tsx ./scripts/generate-pdf-datasheets-pdf-lib.ts",
|
"pdf:datasheets:legacy": "tsx ./scripts/generate-pdf-datasheets-pdf-lib.ts"
|
||||||
"cms:dev": "docker network create infra 2>/dev/null || true && docker-compose up -d cms cms-db",
|
|
||||||
"cms:stop": "docker-compose stop cms cms-db",
|
|
||||||
"cms:logs": "docker-compose logs -f cms",
|
|
||||||
"cms:export": "./scripts/strapi-sync.sh export",
|
|
||||||
"cms:import": "./scripts/strapi-sync.sh import",
|
|
||||||
"cms:migrate": "tsx ./scripts/migrate-to-strapi.ts"
|
|
||||||
},
|
},
|
||||||
"version": "1.0.0"
|
"version": "1.0.0"
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user