1.2
This commit is contained in:
parent
0dc1478d15
commit
e9e243b87f
3
.dockerignore
Normal file
3
.dockerignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
backend/node_modules
|
||||||
|
frontend/node_modules
|
||||||
|
frontend/build
|
||||||
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
node_modules/
|
||||||
|
*/node_modules/
|
||||||
|
**/node_modules/
|
||||||
|
*/build/
|
||||||
|
**/build/
|
||||||
|
.DS_Store
|
||||||
|
.env
|
||||||
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
# Test Editor
|
# Test Editor 100
|
||||||
|
|
||||||
## This project was generated by [Flatlogic Platform](https://flatlogic.com).
|
## This project was generated by [Flatlogic Platform](https://flatlogic.com).
|
||||||
|
|
||||||
|
|||||||
26
app-shell/.eslintrc.cjs
Normal file
26
app-shell/.eslintrc.cjs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
const globals = require('globals');
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
files: ['**/*.js', '**/*.ts', '**/*.tsx'],
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 2021,
|
||||||
|
sourceType: 'module',
|
||||||
|
globals: {
|
||||||
|
...globals.browser,
|
||||||
|
...globals.node,
|
||||||
|
},
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
},
|
||||||
|
plugins: ['@typescript-eslint'],
|
||||||
|
rules: {
|
||||||
|
'no-unused-vars': 'warn',
|
||||||
|
'no-console': 'off',
|
||||||
|
'indent': ['error', 2],
|
||||||
|
'quotes': ['error', 'single'],
|
||||||
|
'semi': ['error', 'always'],
|
||||||
|
|
||||||
|
'@typescript-eslint/no-unused-vars': 'warn',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
11
app-shell/.prettierrc
Normal file
11
app-shell/.prettierrc
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"printWidth": 80,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"quoteProps": "as-needed",
|
||||||
|
"jsxSingleQuote": true,
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"bracketSameLine": false,
|
||||||
|
"arrowParens": "always"
|
||||||
|
}
|
||||||
7
app-shell/.sequelizerc
Normal file
7
app-shell/.sequelizerc
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
const path = require('path');
|
||||||
|
module.exports = {
|
||||||
|
"config": path.resolve("src", "db", "db.config.js"),
|
||||||
|
"models-path": path.resolve("src", "db", "models"),
|
||||||
|
"seeders-path": path.resolve("src", "db", "seeders"),
|
||||||
|
"migrations-path": path.resolve("src", "db", "migrations")
|
||||||
|
};
|
||||||
23
app-shell/Dockerfile
Normal file
23
app-shell/Dockerfile
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
FROM node:20.15.1-alpine
|
||||||
|
|
||||||
|
RUN apk update && apk add bash
|
||||||
|
# Create app directory
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
# Install app dependencies
|
||||||
|
# A wildcard is used to ensure both package.json AND package-lock.json are copied
|
||||||
|
# where available (npm@5+)
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
RUN yarn install
|
||||||
|
# If you are building your code for production
|
||||||
|
# RUN npm ci --only=production
|
||||||
|
|
||||||
|
|
||||||
|
# Bundle app source
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
|
||||||
|
EXPOSE 4000
|
||||||
|
|
||||||
|
CMD [ "yarn", "start" ]
|
||||||
13
app-shell/README.md
Normal file
13
app-shell/README.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#test - template backend,
|
||||||
|
|
||||||
|
#### Run App on local machine:
|
||||||
|
|
||||||
|
##### Install local dependencies:
|
||||||
|
|
||||||
|
- `yarn install`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
##### Start build:
|
||||||
|
|
||||||
|
- `yarn start`
|
||||||
42
app-shell/package.json
Normal file
42
app-shell/package.json
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"name": "app-shell",
|
||||||
|
"description": "app-shell",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node ./src/index.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/parser": "^7.26.7",
|
||||||
|
"adm-zip": "^0.5.16",
|
||||||
|
"axios": "^1.6.7",
|
||||||
|
"bcrypt": "5.1.1",
|
||||||
|
"cors": "2.8.5",
|
||||||
|
"eslint": "^9.13.0",
|
||||||
|
"express": "4.18.2",
|
||||||
|
"formidable": "1.2.2",
|
||||||
|
"helmet": "4.1.1",
|
||||||
|
"json2csv": "^5.0.7",
|
||||||
|
"jsonwebtoken": "8.5.1",
|
||||||
|
"lodash": "4.17.21",
|
||||||
|
"moment": "2.30.1",
|
||||||
|
"multer": "^1.4.4",
|
||||||
|
"passport": "^0.7.0",
|
||||||
|
"passport-google-oauth2": "^0.2.0",
|
||||||
|
"passport-jwt": "^4.0.1",
|
||||||
|
"passport-microsoft": "^0.1.0",
|
||||||
|
"postcss": "^8.5.1",
|
||||||
|
"sequelize-json-schema": "^2.1.1",
|
||||||
|
"pg": "^8.13.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"devDependencies": {
|
||||||
|
"@typescript-eslint/eslint-plugin": "^8.12.2",
|
||||||
|
"@typescript-eslint/parser": "^8.12.2",
|
||||||
|
"cross-env": "7.0.3",
|
||||||
|
"mocha": "8.1.3",
|
||||||
|
"nodemon": "^3.1.7",
|
||||||
|
"sequelize-cli": "6.6.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
42
app-shell/src/config.js
Normal file
42
app-shell/src/config.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
|
||||||
|
project_uuid: '19b1c1bd-792c-4fae-95df-528206c8b6ab',
|
||||||
|
flHost: process.env.NODE_ENV === 'production' ? 'https://flatlogic.com/projects' : 'http://localhost:3000/projects',
|
||||||
|
|
||||||
|
gitea_domain: process.env.GITEA_DOMAIN || 'gitea.flatlogic.app',
|
||||||
|
gitea_username: process.env.GITEA_USERNAME || 'admin',
|
||||||
|
gitea_api_token: process.env.GITEA_API_TOKEN || null,
|
||||||
|
github_repo_url: process.env.GITHUB_REPO_URL || null,
|
||||||
|
github_token: process.env.GITHUB_TOKEN || null,
|
||||||
|
|
||||||
|
eventTypes: {
|
||||||
|
COMMIT: 'PROJECT_DEV_COMMIT',
|
||||||
|
COMMIT_STARTED: 'COMMIT_STARTED',
|
||||||
|
COMMIT_FAILED: 'COMMIT_FAILED',
|
||||||
|
COMMIT_COMPLETED: 'COMMIT_COMPLETED',
|
||||||
|
REPO_INIT_COMPLETED: 'REPO_INIT_COMPLETED',
|
||||||
|
REPO_INIT_STARTED: 'REPO_INIT_STARTED',
|
||||||
|
REPO_INIT_FAILED: 'REPO_INIT_FAILED',
|
||||||
|
REMOTE_REPO_CREATION_STARTED: 'REMOTE_REPO_CREATION_STARTED',
|
||||||
|
REMOTE_REPO_CREATION_COMPLETED: 'REMOTE_REPO_CREATION_COMPLETED',
|
||||||
|
REMOTE_REPO_CREATION_FAILED: 'REMOTE_REPO_CREATION_FAILED',
|
||||||
|
FETCH_RESET_STARTED: 'FETCH_RESET_STARTED',
|
||||||
|
FETCH_RESET_COMPLETED: 'FETCH_RESET_COMPLETED',
|
||||||
|
RESET_TO_BRANCH_COMPLETED: 'RESET_TO_BRANCH_COMPLETED',
|
||||||
|
RESET_TO_BRANCH_FAILED: 'RESET_TO_BRANCH_FAILED',
|
||||||
|
VALIDATION_ERROR: 'VALIDATION_ERROR',
|
||||||
|
DEPLOYMENT: 'DEPLOYMENT_STATUS',
|
||||||
|
BUILD_ERROR: 'BUILD_ERROR',
|
||||||
|
RUNTIME_ERROR: 'RUNTIME_ERROR',
|
||||||
|
USER_ACTION: 'USER_ACTION',
|
||||||
|
READ_PROJECT_TREE_STARTED: 'READ_PROJECT_TREE_STARTED',
|
||||||
|
READ_PROJECT_TREE_COMPLETED: 'READ_PROJECT_TREE_COMPLETED',
|
||||||
|
READ_PROJECT_TREE_FAILED: 'READ_PROJECT_TREE_FAILED',
|
||||||
|
FILE_VALIDATION_STARTED: 'FILE_VALIDATION_STARTED',
|
||||||
|
FILE_VALIDATION_COMPLETED: 'FILE_VALIDATION_COMPLETED',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = config;
|
||||||
23
app-shell/src/helpers.js
Normal file
23
app-shell/src/helpers.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
const jwt = require('jsonwebtoken');
|
||||||
|
const config = require('./config');
|
||||||
|
|
||||||
|
module.exports = class Helpers {
|
||||||
|
static wrapAsync(fn) {
|
||||||
|
return function (req, res, next) {
|
||||||
|
fn(req, res, next).catch(next);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static commonErrorHandler(error, req, res, next) {
|
||||||
|
if ([400, 403, 404].includes(error.code)) {
|
||||||
|
return res.status(error.code).send(error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error(error);
|
||||||
|
return res.status(500).send(error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static jwtSign(data) {
|
||||||
|
return jwt.sign(data, config.secret_key, { expiresIn: '6h' });
|
||||||
|
}
|
||||||
|
};
|
||||||
54
app-shell/src/index.js
Normal file
54
app-shell/src/index.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const cors = require('cors');
|
||||||
|
const app = express();
|
||||||
|
const bodyParser = require('body-parser');
|
||||||
|
const checkPermissions = require('./middlewares/check-permissions');
|
||||||
|
const modifyPath = require('./middlewares/modify-path');
|
||||||
|
const VCS = require('./services/vcs');
|
||||||
|
|
||||||
|
const executorRoutes = require('./routes/executor');
|
||||||
|
const vcsRoutes = require('./routes/vcs');
|
||||||
|
|
||||||
|
// Function to initialize the Git repository
|
||||||
|
function initRepo() {
|
||||||
|
const projectId = '30652';
|
||||||
|
return VCS.initRepo(projectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the Express app on APP_SHELL_PORT (4000)
|
||||||
|
function startServer() {
|
||||||
|
const PORT = 4000;
|
||||||
|
app.listen(PORT, () => {
|
||||||
|
console.log(`Listening on port ${PORT}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run Git check after the server is up
|
||||||
|
function runGitCheck() {
|
||||||
|
initRepo()
|
||||||
|
.then(result => {
|
||||||
|
console.log(result?.message ? result.message : result);
|
||||||
|
// Here you can add additional logic if needed
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('Error during repo initialization:', err);
|
||||||
|
// Optionally exit the process if Git check is critical:
|
||||||
|
// process.exit(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
app.use(cors({ origin: true }));
|
||||||
|
app.use(bodyParser.json());
|
||||||
|
app.use(checkPermissions);
|
||||||
|
app.use(modifyPath);
|
||||||
|
|
||||||
|
app.use('/executor', executorRoutes);
|
||||||
|
app.use('/vcs', vcsRoutes);
|
||||||
|
|
||||||
|
// Start the app_shell server
|
||||||
|
startServer();
|
||||||
|
|
||||||
|
// Now perform Git check
|
||||||
|
runGitCheck();
|
||||||
|
|
||||||
|
module.exports = app;
|
||||||
17
app-shell/src/middlewares/check-permissions.js
Normal file
17
app-shell/src/middlewares/check-permissions.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
const config = require('../config');
|
||||||
|
|
||||||
|
function checkPermissions(req, res, next) {
|
||||||
|
const project_uuid = config.project_uuid;
|
||||||
|
const requiredHeader = 'X-Project-UUID';
|
||||||
|
const headerValue = req.headers[requiredHeader.toLowerCase()];
|
||||||
|
// Logging whatever request we're getting
|
||||||
|
console.log('Request:', req.url, req.method, req.body, req.headers);
|
||||||
|
|
||||||
|
if (headerValue && headerValue === project_uuid) {
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
res.status(403).send({ error: 'Stop right there, criminal scum! Your project UUID is invalid or missing.' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = checkPermissions;
|
||||||
8
app-shell/src/middlewares/modify-path.js
Normal file
8
app-shell/src/middlewares/modify-path.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
function modifyPath(req, res, next) {
|
||||||
|
if (req.body && req.body.path) {
|
||||||
|
req.body.path = '../../../' + req.body.path;
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = modifyPath;
|
||||||
312
app-shell/src/routes/executor.js
Normal file
312
app-shell/src/routes/executor.js
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const multer = require('multer');
|
||||||
|
const upload = multer({ dest: 'uploads/' });
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
const ExecutorService = require('../services/executor');
|
||||||
|
|
||||||
|
const wrapAsync = require('../helpers').wrapAsync;
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
'/read_project_tree',
|
||||||
|
wrapAsync(async (req, res) => {
|
||||||
|
const { path } = req.body;
|
||||||
|
const tree = await ExecutorService.readProjectTree(path);
|
||||||
|
res.status(200).send(tree);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
'/read_file',
|
||||||
|
wrapAsync(async (req, res) => {
|
||||||
|
const { path, showLines } = req.body;
|
||||||
|
const content = await ExecutorService.readFileContents(path, showLines);
|
||||||
|
res.status(200).send(content);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
'/count_file_lines',
|
||||||
|
wrapAsync(async (req, res) => {
|
||||||
|
const { path } = req.body;
|
||||||
|
const content = await ExecutorService.countFileLines(path);
|
||||||
|
res.status(200).send(content);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// router.post(
|
||||||
|
// '/read_file_header',
|
||||||
|
// wrapAsync(async (req, res) => {
|
||||||
|
// const { path, N } = req.body;
|
||||||
|
// try {
|
||||||
|
// const header = await ExecutorService.readFileHeader(path, N);
|
||||||
|
// res.status(200).send(header);
|
||||||
|
// } catch (error) {
|
||||||
|
// res.status(500).send({
|
||||||
|
// error: true,
|
||||||
|
// message: error.message,
|
||||||
|
// details: error.details || error.stack,
|
||||||
|
// validation: error.validation
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }),
|
||||||
|
// );
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
'/read_file_line_context',
|
||||||
|
wrapAsync(async (req, res) => {
|
||||||
|
const { path, lineNumber, windowSize, showLines } = req.body;
|
||||||
|
try {
|
||||||
|
const context = await ExecutorService.readFileLineContext(path, lineNumber, windowSize, showLines);
|
||||||
|
res.status(200).send(context);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send({
|
||||||
|
error: true,
|
||||||
|
message: error.message,
|
||||||
|
details: error.details || error.stack,
|
||||||
|
validation: error.validation
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
'/write_file',
|
||||||
|
wrapAsync(async (req, res) => {
|
||||||
|
const { path, fileContents, comment } = req.body;
|
||||||
|
try {
|
||||||
|
await ExecutorService.writeFile(path, fileContents, comment);
|
||||||
|
res.status(200).send({ message: 'File written successfully' });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send({
|
||||||
|
error: true,
|
||||||
|
message: error.message,
|
||||||
|
details: error.details || error.stack,
|
||||||
|
validation: error.validation
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
'/insert_file_content',
|
||||||
|
wrapAsync(async (req, res) => {
|
||||||
|
const { path, lineNumber, newContent, message } = req.body;
|
||||||
|
try {
|
||||||
|
await ExecutorService.insertFileContent(path, lineNumber, newContent, message);
|
||||||
|
res.status(200).send({ message: 'File written successfully' });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send({
|
||||||
|
error: true,
|
||||||
|
message: error.message,
|
||||||
|
details: error.details || error.stack,
|
||||||
|
validation: error.validation
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
'/replace_file_line',
|
||||||
|
wrapAsync(async (req, res) => {
|
||||||
|
const { path, lineNumber, newText } = req.body;
|
||||||
|
try {
|
||||||
|
const result = await ExecutorService.replaceFileLine(path, lineNumber, newText);
|
||||||
|
res.status(200).send(result);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send({
|
||||||
|
error: true,
|
||||||
|
message: error.message,
|
||||||
|
details: error.details || error.stack,
|
||||||
|
validation: error.validation
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
router.post(
|
||||||
|
'/replace_file_chunk',
|
||||||
|
wrapAsync(async (req, res) => {
|
||||||
|
const { path, startLine, endLine, newCode } = req.body;
|
||||||
|
try {
|
||||||
|
const result = await ExecutorService.replaceFileChunk(path, startLine, endLine, newCode);
|
||||||
|
res.status(200).send(result);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send({
|
||||||
|
error: true,
|
||||||
|
message: error.message,
|
||||||
|
details: error.details || error.stack,
|
||||||
|
validation: error.validation
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
'/delete_file_lines',
|
||||||
|
wrapAsync(async (req, res) => {
|
||||||
|
const { path, startLine, endLine, message } = req.body;
|
||||||
|
try {
|
||||||
|
const result = await ExecutorService.deleteFileLines(path, startLine, endLine, message);
|
||||||
|
res.status(200).send(result);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send({
|
||||||
|
error: true,
|
||||||
|
message: error.message,
|
||||||
|
details: error.details || error.stack,
|
||||||
|
validation: error.validation
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
'/validate_file',
|
||||||
|
wrapAsync(async (req, res) => {
|
||||||
|
const { path } = req.body;
|
||||||
|
try {
|
||||||
|
const validationResult = await ExecutorService.validateFile(path);
|
||||||
|
res.status(200).send({ validationResult });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send({
|
||||||
|
error: true,
|
||||||
|
message: error.message,
|
||||||
|
details: error.details || error.stack,
|
||||||
|
validation: error.validation
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
'/check_frontend_runtime_error',
|
||||||
|
wrapAsync(async (req, res) => {
|
||||||
|
try {
|
||||||
|
const result = await ExecutorService.checkFrontendRuntimeLogs();
|
||||||
|
res.status(200).send(result);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send({ error: error });
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
'/replace_code_block',
|
||||||
|
wrapAsync(async (req, res) => {
|
||||||
|
const {path, oldCode, newCode, message} = req.body;
|
||||||
|
try {
|
||||||
|
const response = await ExecutorService.replaceCodeBlock(path, oldCode, newCode, message);
|
||||||
|
res.status(200).send(response);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send({
|
||||||
|
error: true,
|
||||||
|
message: error.message,
|
||||||
|
details: error.details || error.stack,
|
||||||
|
validation: error.validation
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
router.post('/update_project_files_from_scheme',
|
||||||
|
upload.single('file'), // 'file' - name of the field in the form
|
||||||
|
async (req, res) => {
|
||||||
|
console.log('Request received');
|
||||||
|
console.log('Headers:', req.headers);
|
||||||
|
if (!req.file) {
|
||||||
|
return res.status(400).json({ error: 'No file uploaded' });
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('File info:', {
|
||||||
|
originalname: req.file.originalname,
|
||||||
|
path: req.file.path,
|
||||||
|
size: req.file.size,
|
||||||
|
mimetype: req.file.mimetype
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log('Starting update process...');
|
||||||
|
const result = await ExecutorService.updateProjectFilesFromScheme(req.file.path);
|
||||||
|
console.log('Update completed, result:', result);
|
||||||
|
|
||||||
|
console.log('Removing temp file...');
|
||||||
|
fs.unlinkSync(req.file.path);
|
||||||
|
console.log('Temp file removed');
|
||||||
|
|
||||||
|
console.log('Sending response...');
|
||||||
|
return res.json(result);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error in route handler:', error);
|
||||||
|
if (req.file) {
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(req.file.path);
|
||||||
|
console.log('Temp file removed after error');
|
||||||
|
} catch (unlinkError) {
|
||||||
|
console.error('Error removing temp file:', unlinkError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.error('Update project files error:', error);
|
||||||
|
return res.status(500).json({
|
||||||
|
error: error.message,
|
||||||
|
stack: process.env.NODE_ENV === 'development' ? error.stack : undefined
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
'/get_db_schema',
|
||||||
|
wrapAsync(async (req, res) => {
|
||||||
|
try {
|
||||||
|
|
||||||
|
const jsonSchema = await ExecutorService.getDBSchema();
|
||||||
|
res.status(200).send({ jsonSchema });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send({ error: error });
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
'/execute_sql',
|
||||||
|
wrapAsync(async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { query } = req.body;
|
||||||
|
const result = await ExecutorService.executeSQL(query);
|
||||||
|
res.status(200).send(result);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send({ error: error });
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
'/search_files',
|
||||||
|
wrapAsync(async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { searchStrings } = req.body;
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof searchStrings !== 'string' &&
|
||||||
|
!(
|
||||||
|
Array.isArray(searchStrings) &&
|
||||||
|
searchStrings.every(item => typeof item === 'string')
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return res.status(400).send({ error: 'searchStrings must be a string or an array of strings' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await ExecutorService.searchFiles(searchStrings);
|
||||||
|
res.status(200).send(result);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send({ error: error.message });
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
router.use('/', require('../helpers').commonErrorHandler);
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
40
app-shell/src/routes/vcs.js
Normal file
40
app-shell/src/routes/vcs.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const wrapAsync = require('../helpers').wrapAsync; // Ваша обёртка для обработки асинхронных маршрутов
|
||||||
|
const VSC = require('../services/vcs');
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.post('/init', wrapAsync(async (req, res) => {
|
||||||
|
const result = await VSC.initRepo();
|
||||||
|
res.status(200).send(result);
|
||||||
|
}));
|
||||||
|
|
||||||
|
router.post('/commit', wrapAsync(async (req, res) => {
|
||||||
|
const { message, files } = req.body;
|
||||||
|
const result = await VSC.commitChanges(message, files);
|
||||||
|
res.status(200).send(result);
|
||||||
|
}));
|
||||||
|
|
||||||
|
router.post('/log', wrapAsync(async (req, res) => {
|
||||||
|
const result = await VSC.getLog();
|
||||||
|
res.status(200).send(result);
|
||||||
|
}));
|
||||||
|
|
||||||
|
router.post('/rollback', wrapAsync(async (req, res) => {
|
||||||
|
const { ref } = req.body;
|
||||||
|
// const result = await VSC.checkout(ref);
|
||||||
|
const result = await VSC.revert(ref);
|
||||||
|
res.status(200).send(result);
|
||||||
|
}));
|
||||||
|
|
||||||
|
router.post('/sync-to-stable', wrapAsync(async (req, res) => {
|
||||||
|
const result = await VSC.mergeDevIntoMaster();
|
||||||
|
res.status(200).send(result);
|
||||||
|
}));
|
||||||
|
|
||||||
|
router.post('/reset-dev', wrapAsync(async (req, res) => {
|
||||||
|
const result = await VSC.resetDevBranch();
|
||||||
|
res.status(200).send(result);
|
||||||
|
}));
|
||||||
|
|
||||||
|
router.use('/', require('../helpers').commonErrorHandler);
|
||||||
|
module.exports = router;
|
||||||
88
app-shell/src/services/database.js
Normal file
88
app-shell/src/services/database.js
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// Database.js
|
||||||
|
const { Client } = require('pg');
|
||||||
|
const config = require('../../../backend/src/db/db.config');
|
||||||
|
|
||||||
|
const env = process.env.NODE_ENV || 'development';
|
||||||
|
const dbConfig = config[env];
|
||||||
|
|
||||||
|
class Database {
|
||||||
|
constructor() {
|
||||||
|
this.client = new Client({
|
||||||
|
user: dbConfig.username,
|
||||||
|
password: dbConfig.password,
|
||||||
|
database: dbConfig.database,
|
||||||
|
host: dbConfig.host,
|
||||||
|
port: dbConfig.port
|
||||||
|
});
|
||||||
|
|
||||||
|
// Connect once, reuse the client
|
||||||
|
this.client.connect().catch(err => {
|
||||||
|
console.error('Error connecting to the database:', err);
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async executeSQL(query) {
|
||||||
|
try {
|
||||||
|
const result = await this.client.query(query);
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
rows: result.rows
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error executing query:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to fetch simple table/column info from 'information_schema'
|
||||||
|
// (You can expand this to handle constraints, indexes, etc.)
|
||||||
|
async getDBSchema(schemaName = 'public') {
|
||||||
|
try {
|
||||||
|
const tableQuery = `
|
||||||
|
SELECT table_name
|
||||||
|
FROM information_schema.tables
|
||||||
|
WHERE table_schema = $1
|
||||||
|
AND table_type = 'BASE TABLE'
|
||||||
|
ORDER BY table_name
|
||||||
|
`;
|
||||||
|
|
||||||
|
const columnQuery = `
|
||||||
|
SELECT table_name, column_name, data_type, is_nullable
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE table_schema = $1
|
||||||
|
ORDER BY table_name, ordinal_position
|
||||||
|
`;
|
||||||
|
|
||||||
|
const [tablesResult, columnsResult] = await Promise.all([
|
||||||
|
this.client.query(tableQuery, [schemaName]),
|
||||||
|
this.client.query(columnQuery, [schemaName]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Build a simple schema object:
|
||||||
|
const tables = tablesResult.rows.map(row => row.table_name);
|
||||||
|
const columnsByTable = {};
|
||||||
|
|
||||||
|
columnsResult.rows.forEach(row => {
|
||||||
|
const { table_name, column_name, data_type, is_nullable } = row;
|
||||||
|
if (!columnsByTable[table_name]) columnsByTable[table_name] = [];
|
||||||
|
columnsByTable[table_name].push({ column_name, data_type, is_nullable });
|
||||||
|
});
|
||||||
|
|
||||||
|
// Combine tables with their columns
|
||||||
|
return tables.map(table => ({
|
||||||
|
table,
|
||||||
|
columns: columnsByTable[table] || [],
|
||||||
|
}));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching schema:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async close() {
|
||||||
|
await this.client.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new Database();
|
||||||
1206
app-shell/src/services/executor.js
Normal file
1206
app-shell/src/services/executor.js
Normal file
File diff suppressed because it is too large
Load Diff
16
app-shell/src/services/notifications/errors/forbidden.js
Normal file
16
app-shell/src/services/notifications/errors/forbidden.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
const { getNotification, isNotification } = require('../helpers');
|
||||||
|
|
||||||
|
module.exports = class ForbiddenError extends Error {
|
||||||
|
constructor(messageCode) {
|
||||||
|
let message;
|
||||||
|
|
||||||
|
if (messageCode && isNotification(messageCode)) {
|
||||||
|
message = getNotification(messageCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
message = message || getNotification('errors.forbidden.message');
|
||||||
|
|
||||||
|
super(message);
|
||||||
|
this.code = 403;
|
||||||
|
}
|
||||||
|
};
|
||||||
16
app-shell/src/services/notifications/errors/validation.js
Normal file
16
app-shell/src/services/notifications/errors/validation.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
const { getNotification, isNotification } = require('../helpers');
|
||||||
|
|
||||||
|
module.exports = class ValidationError extends Error {
|
||||||
|
constructor(messageCode) {
|
||||||
|
let message;
|
||||||
|
|
||||||
|
if (messageCode && isNotification(messageCode)) {
|
||||||
|
message = getNotification(messageCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
message = message || getNotification('errors.validation.message');
|
||||||
|
|
||||||
|
super(message);
|
||||||
|
this.code = 400;
|
||||||
|
}
|
||||||
|
};
|
||||||
30
app-shell/src/services/notifications/helpers.js
Normal file
30
app-shell/src/services/notifications/helpers.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
const _get = require('lodash/get');
|
||||||
|
const errors = require('./list');
|
||||||
|
|
||||||
|
function format(message, args) {
|
||||||
|
if (!message) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return message.replace(/{(\d+)}/g, function (match, number) {
|
||||||
|
return typeof args[number] != 'undefined' ? args[number] : match;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const isNotification = (key) => {
|
||||||
|
const message = _get(errors, key);
|
||||||
|
return !!message;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getNotification = (key, ...args) => {
|
||||||
|
const message = _get(errors, key);
|
||||||
|
|
||||||
|
if (!message) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
return format(message, args);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.getNotification = getNotification;
|
||||||
|
exports.isNotification = isNotification;
|
||||||
100
app-shell/src/services/notifications/list.js
Normal file
100
app-shell/src/services/notifications/list.js
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
const errors = {
|
||||||
|
app: {
|
||||||
|
title: 'test',
|
||||||
|
},
|
||||||
|
|
||||||
|
auth: {
|
||||||
|
userDisabled: 'Your account is disabled',
|
||||||
|
forbidden: 'Forbidden',
|
||||||
|
unauthorized: 'Unauthorized',
|
||||||
|
userNotFound: `Sorry, we don't recognize your credentials`,
|
||||||
|
wrongPassword: `Sorry, we don't recognize your credentials`,
|
||||||
|
weakPassword: 'This password is too weak',
|
||||||
|
emailAlreadyInUse: 'Email is already in use',
|
||||||
|
invalidEmail: 'Please provide a valid email',
|
||||||
|
passwordReset: {
|
||||||
|
invalidToken: 'Password reset link is invalid or has expired',
|
||||||
|
error: `Email not recognized`,
|
||||||
|
},
|
||||||
|
passwordUpdate: {
|
||||||
|
samePassword: `You can't use the same password. Please create new password`,
|
||||||
|
},
|
||||||
|
userNotVerified: `Sorry, your email has not been verified yet`,
|
||||||
|
emailAddressVerificationEmail: {
|
||||||
|
invalidToken: 'Email verification link is invalid or has expired',
|
||||||
|
error: `Email not recognized`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
iam: {
|
||||||
|
errors: {
|
||||||
|
userAlreadyExists: 'User with this email already exists',
|
||||||
|
userNotFound: 'User not found',
|
||||||
|
disablingHimself: `You can't disable yourself`,
|
||||||
|
revokingOwnPermission: `You can't revoke your own owner permission`,
|
||||||
|
deletingHimself: `You can't delete yourself`,
|
||||||
|
emailRequired: 'Email is required',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
importer: {
|
||||||
|
errors: {
|
||||||
|
invalidFileEmpty: 'The file is empty',
|
||||||
|
invalidFileExcel: 'Only excel (.xlsx) files are allowed',
|
||||||
|
invalidFileUpload:
|
||||||
|
'Invalid file. Make sure you are using the last version of the template.',
|
||||||
|
importHashRequired: 'Import hash is required',
|
||||||
|
importHashExistent: 'Data has already been imported',
|
||||||
|
userEmailMissing: 'Some items in the CSV do not have an email',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
errors: {
|
||||||
|
forbidden: {
|
||||||
|
message: 'Forbidden',
|
||||||
|
},
|
||||||
|
validation: {
|
||||||
|
message: 'An error occurred',
|
||||||
|
},
|
||||||
|
searchQueryRequired: {
|
||||||
|
message: 'Search query is required',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
emails: {
|
||||||
|
invitation: {
|
||||||
|
subject: `You've been invited to {0}`,
|
||||||
|
body: `
|
||||||
|
<p>Hello,</p>
|
||||||
|
<p>You've been invited to {0} set password for your {1} account.</p>
|
||||||
|
<p><a href='{2}'>{2}</a></p>
|
||||||
|
<p>Thanks,</p>
|
||||||
|
<p>Your {0} team</p>
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
emailAddressVerification: {
|
||||||
|
subject: `Verify your email for {0}`,
|
||||||
|
body: `
|
||||||
|
<p>Hello,</p>
|
||||||
|
<p>Follow this link to verify your email address.</p>
|
||||||
|
<p><a href='{0}'>{0}</a></p>
|
||||||
|
<p>If you didn't ask to verify this address, you can ignore this email.</p>
|
||||||
|
<p>Thanks,</p>
|
||||||
|
<p>Your {1} team</p>
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
passwordReset: {
|
||||||
|
subject: `Reset your password for {0}`,
|
||||||
|
body: `
|
||||||
|
<p>Hello,</p>
|
||||||
|
<p>Follow this link to reset your {0} password for your {1} account.</p>
|
||||||
|
<p><a href='{2}'>{2}</a></p>
|
||||||
|
<p>If you didn't ask to reset your password, you can ignore this email.</p>
|
||||||
|
<p>Thanks,</p>
|
||||||
|
<p>Your {0} team</p>
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = errors;
|
||||||
67
app-shell/src/services/project-events.js
Normal file
67
app-shell/src/services/project-events.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
const axios = require('axios');
|
||||||
|
const config = require('../config.js');
|
||||||
|
|
||||||
|
class ProjectEventsService {
|
||||||
|
/**
|
||||||
|
* Sends a project event to the Rails backend
|
||||||
|
*
|
||||||
|
* @param {string} eventType - Type of the event
|
||||||
|
* @param {object} payload - Event payload data
|
||||||
|
* @param {object} options - Additional options
|
||||||
|
* @param {string} [options.conversationId] - Optional conversation ID
|
||||||
|
* @param {boolean} [options.isError=false] - Whether this is an error event
|
||||||
|
* @returns {Promise<object>} - Response from the webhook
|
||||||
|
*/
|
||||||
|
static async sendEvent(eventType, payload = {}, options = {}) {
|
||||||
|
try {
|
||||||
|
console.log(`[DEBUG] Sending project event: ${eventType}`);
|
||||||
|
|
||||||
|
const webhookUrl = `https://flatlogic.com/projects/events_webhook`;
|
||||||
|
|
||||||
|
// Prepare the event data
|
||||||
|
const eventData = {
|
||||||
|
project_uuid: config.project_uuid,
|
||||||
|
event_type: eventType,
|
||||||
|
payload: {
|
||||||
|
...payload,
|
||||||
|
message: `[APP] ${payload.message}`,
|
||||||
|
is_error: options.isError || false,
|
||||||
|
system_message: true,
|
||||||
|
is_command_info: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add conversation ID if provided
|
||||||
|
if (options.conversationId) {
|
||||||
|
eventData.conversation_id = options.conversationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'x-project-uuid': config.project_uuid
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(`[DEBUG] Event data: ${JSON.stringify(eventData)}`);
|
||||||
|
|
||||||
|
const response = await axios.post(webhookUrl, eventData, { headers });
|
||||||
|
|
||||||
|
console.log(`[DEBUG] Event sent successfully, status: ${response.status}`);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`[ERROR] Failed to send project event: ${error.message}`);
|
||||||
|
if (error.response) {
|
||||||
|
console.error(`[ERROR] Response status: ${error.response.status}`);
|
||||||
|
console.error(`[ERROR] Response data: ${JSON.stringify(error.response.data)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't throw the error, just return a failed status
|
||||||
|
// This prevents errors in the event service from breaking app functionality
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: error.message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ProjectEventsService;
|
||||||
1131
app-shell/src/services/vcs.js
Normal file
1131
app-shell/src/services/vcs.js
Normal file
File diff suppressed because it is too large
Load Diff
3044
app-shell/yarn.lock
Normal file
3044
app-shell/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
#Test Editor - template backend,
|
#Test Editor 100 - template backend,
|
||||||
|
|
||||||
#### Run App on local machine:
|
#### Run App on local machine:
|
||||||
|
|
||||||
@ -38,10 +38,10 @@
|
|||||||
|
|
||||||
- Type this command to creating a new database.
|
- Type this command to creating a new database.
|
||||||
|
|
||||||
- `postgres=> CREATE DATABASE db_test_editor;`
|
- `postgres=> CREATE DATABASE db_test_editor_100;`
|
||||||
|
|
||||||
- Then give that new user privileges to the new database then quit the `psql`.
|
- Then give that new user privileges to the new database then quit the `psql`.
|
||||||
- `postgres=> GRANT ALL PRIVILEGES ON DATABASE db_test_editor TO admin;`
|
- `postgres=> GRANT ALL PRIVILEGES ON DATABASE db_test_editor_100 TO admin;`
|
||||||
- `postgres=> \q`
|
- `postgres=> \q`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "testeditor",
|
"name": "testeditor100",
|
||||||
"description": "Test Editor - template backend",
|
"description": "Test Editor 100 - template backend",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "npm run db:migrate && npm run db:seed && npm run watch",
|
"start": "npm run db:migrate && npm run db:seed && npm run watch",
|
||||||
"db:migrate": "sequelize-cli db:migrate",
|
"db:migrate": "sequelize-cli db:migrate",
|
||||||
|
|||||||
@ -3,7 +3,7 @@ const os = require('os');
|
|||||||
const config = {
|
const config = {
|
||||||
gcloud: {
|
gcloud: {
|
||||||
bucket: 'fldemo-files',
|
bucket: 'fldemo-files',
|
||||||
hash: '3588e8c85bfe705b50eef814dd61e8f6',
|
hash: 'afeefb9d49f5b7977577876b99532ac7',
|
||||||
},
|
},
|
||||||
bcrypt: {
|
bcrypt: {
|
||||||
saltRounds: 12,
|
saltRounds: 12,
|
||||||
@ -36,7 +36,7 @@ const config = {
|
|||||||
},
|
},
|
||||||
uploadDir: os.tmpdir(),
|
uploadDir: os.tmpdir(),
|
||||||
email: {
|
email: {
|
||||||
from: 'Test Editor <app@flatlogic.app>',
|
from: 'Test Editor 100 <app@flatlogic.app>',
|
||||||
host: 'email-smtp.us-east-1.amazonaws.com',
|
host: 'email-smtp.us-east-1.amazonaws.com',
|
||||||
port: 587,
|
port: 587,
|
||||||
auth: {
|
auth: {
|
||||||
|
|||||||
@ -13,7 +13,7 @@ module.exports = {
|
|||||||
username: 'postgres',
|
username: 'postgres',
|
||||||
dialect: 'postgres',
|
dialect: 'postgres',
|
||||||
password: '',
|
password: '',
|
||||||
database: 'db_test_editor',
|
database: 'db_test_editor_100',
|
||||||
host: process.env.DB_HOST || 'localhost',
|
host: process.env.DB_HOST || 'localhost',
|
||||||
logging: console.log,
|
logging: console.log,
|
||||||
seederStorage: 'sequelize',
|
seederStorage: 'sequelize',
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const Users = db.users;
|
const Users = db.users;
|
||||||
|
|
||||||
const Employees = db.employees;
|
|
||||||
|
|
||||||
const Inventory = db.inventory;
|
const Inventory = db.inventory;
|
||||||
|
|
||||||
const Machinery = db.machinery;
|
const Machinery = db.machinery;
|
||||||
@ -21,44 +19,6 @@ const Staff = db.staff;
|
|||||||
|
|
||||||
const Clients = db.clients;
|
const Clients = db.clients;
|
||||||
|
|
||||||
const EmployeesData = [
|
|
||||||
{
|
|
||||||
employee_name: 'John Doe',
|
|
||||||
|
|
||||||
role: 'Operator',
|
|
||||||
|
|
||||||
shift: 'Day',
|
|
||||||
|
|
||||||
payroll: 45000,
|
|
||||||
|
|
||||||
// type code here for "relation_one" field
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
employee_name: 'Alice Smith',
|
|
||||||
|
|
||||||
role: 'Supervisor',
|
|
||||||
|
|
||||||
shift: 'Night',
|
|
||||||
|
|
||||||
payroll: 55000,
|
|
||||||
|
|
||||||
// type code here for "relation_one" field
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
employee_name: 'Bob White',
|
|
||||||
|
|
||||||
role: 'Technician',
|
|
||||||
|
|
||||||
shift: 'Day',
|
|
||||||
|
|
||||||
payroll: 48000,
|
|
||||||
|
|
||||||
// type code here for "relation_one" field
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const InventoryData = [
|
const InventoryData = [
|
||||||
{
|
{
|
||||||
item_name: 'Steel Beams',
|
item_name: 'Steel Beams',
|
||||||
@ -75,7 +35,7 @@ const InventoryData = [
|
|||||||
|
|
||||||
quantity: 75,
|
quantity: 75,
|
||||||
|
|
||||||
status: 'reserved',
|
status: 'returned',
|
||||||
|
|
||||||
// type code here for "relation_one" field
|
// type code here for "relation_one" field
|
||||||
},
|
},
|
||||||
@ -85,7 +45,7 @@ const InventoryData = [
|
|||||||
|
|
||||||
quantity: 200,
|
quantity: 200,
|
||||||
|
|
||||||
status: 'available',
|
status: 'returned',
|
||||||
|
|
||||||
// type code here for "relation_one" field
|
// type code here for "relation_one" field
|
||||||
},
|
},
|
||||||
@ -235,6 +195,8 @@ const WorkOrdersData = [
|
|||||||
{
|
{
|
||||||
order_number: 'WO-001',
|
order_number: 'WO-001',
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
// type code here for "relation_many" field
|
// type code here for "relation_many" field
|
||||||
|
|
||||||
// type code here for "relation_many" field
|
// type code here for "relation_many" field
|
||||||
@ -249,6 +211,8 @@ const WorkOrdersData = [
|
|||||||
{
|
{
|
||||||
order_number: 'WO-002',
|
order_number: 'WO-002',
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
// type code here for "relation_many" field
|
// type code here for "relation_many" field
|
||||||
|
|
||||||
// type code here for "relation_many" field
|
// type code here for "relation_many" field
|
||||||
@ -263,6 +227,8 @@ const WorkOrdersData = [
|
|||||||
{
|
{
|
||||||
order_number: 'WO-003',
|
order_number: 'WO-003',
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
// type code here for "relation_many" field
|
// type code here for "relation_many" field
|
||||||
|
|
||||||
// type code here for "relation_many" field
|
// type code here for "relation_many" field
|
||||||
@ -293,19 +259,19 @@ const StaffData = [
|
|||||||
{
|
{
|
||||||
// type code here for "relation_one" field
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
employee_name: 'Albrecht von Haller',
|
employee_name: 'Justus Liebig',
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
// type code here for "relation_one" field
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
employee_name: 'Alfred Binet',
|
employee_name: 'Lynn Margulis',
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
// type code here for "relation_one" field
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
employee_name: 'Jonas Salk',
|
employee_name: 'Neils Bohr',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -313,7 +279,7 @@ const ClientsData = [
|
|||||||
{
|
{
|
||||||
// type code here for "relation_one" field
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
client_name: 'Alfred Binet',
|
client_name: 'Isaac Newton',
|
||||||
|
|
||||||
date_registered: new Date(Date.now()),
|
date_registered: new Date(Date.now()),
|
||||||
|
|
||||||
@ -323,7 +289,7 @@ const ClientsData = [
|
|||||||
{
|
{
|
||||||
// type code here for "relation_one" field
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
client_name: 'Albert Einstein',
|
client_name: 'Noam Chomsky',
|
||||||
|
|
||||||
date_registered: new Date(Date.now()),
|
date_registered: new Date(Date.now()),
|
||||||
|
|
||||||
@ -333,7 +299,7 @@ const ClientsData = [
|
|||||||
{
|
{
|
||||||
// type code here for "relation_one" field
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
client_name: 'Arthur Eddington',
|
client_name: 'William Herschel',
|
||||||
|
|
||||||
date_registered: new Date(Date.now()),
|
date_registered: new Date(Date.now()),
|
||||||
|
|
||||||
@ -378,41 +344,6 @@ async function associateUserWithCompany() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function associateEmployeeWithCompany() {
|
|
||||||
const relatedCompany0 = await Companies.findOne({
|
|
||||||
offset: Math.floor(Math.random() * (await Companies.count())),
|
|
||||||
});
|
|
||||||
const Employee0 = await Employees.findOne({
|
|
||||||
order: [['id', 'ASC']],
|
|
||||||
offset: 0,
|
|
||||||
});
|
|
||||||
if (Employee0?.setCompany) {
|
|
||||||
await Employee0.setCompany(relatedCompany0);
|
|
||||||
}
|
|
||||||
|
|
||||||
const relatedCompany1 = await Companies.findOne({
|
|
||||||
offset: Math.floor(Math.random() * (await Companies.count())),
|
|
||||||
});
|
|
||||||
const Employee1 = await Employees.findOne({
|
|
||||||
order: [['id', 'ASC']],
|
|
||||||
offset: 1,
|
|
||||||
});
|
|
||||||
if (Employee1?.setCompany) {
|
|
||||||
await Employee1.setCompany(relatedCompany1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const relatedCompany2 = await Companies.findOne({
|
|
||||||
offset: Math.floor(Math.random() * (await Companies.count())),
|
|
||||||
});
|
|
||||||
const Employee2 = await Employees.findOne({
|
|
||||||
order: [['id', 'ASC']],
|
|
||||||
offset: 2,
|
|
||||||
});
|
|
||||||
if (Employee2?.setCompany) {
|
|
||||||
await Employee2.setCompany(relatedCompany2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function associateInventoryWithCompany() {
|
async function associateInventoryWithCompany() {
|
||||||
const relatedCompany0 = await Companies.findOne({
|
const relatedCompany0 = await Companies.findOne({
|
||||||
offset: Math.floor(Math.random() * (await Companies.count())),
|
offset: Math.floor(Math.random() * (await Companies.count())),
|
||||||
@ -625,6 +556,41 @@ async function associateSupplierWithCompany() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function associateWorkOrderWithProduction_manager() {
|
||||||
|
const relatedProduction_manager0 = await Users.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Users.count())),
|
||||||
|
});
|
||||||
|
const WorkOrder0 = await WorkOrders.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 0,
|
||||||
|
});
|
||||||
|
if (WorkOrder0?.setProduction_manager) {
|
||||||
|
await WorkOrder0.setProduction_manager(relatedProduction_manager0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedProduction_manager1 = await Users.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Users.count())),
|
||||||
|
});
|
||||||
|
const WorkOrder1 = await WorkOrders.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 1,
|
||||||
|
});
|
||||||
|
if (WorkOrder1?.setProduction_manager) {
|
||||||
|
await WorkOrder1.setProduction_manager(relatedProduction_manager1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedProduction_manager2 = await Users.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Users.count())),
|
||||||
|
});
|
||||||
|
const WorkOrder2 = await WorkOrders.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 2,
|
||||||
|
});
|
||||||
|
if (WorkOrder2?.setProduction_manager) {
|
||||||
|
await WorkOrder2.setProduction_manager(relatedProduction_manager2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Similar logic for "relation_many"
|
// Similar logic for "relation_many"
|
||||||
|
|
||||||
// Similar logic for "relation_many"
|
// Similar logic for "relation_many"
|
||||||
@ -771,8 +737,6 @@ async function associateClientWithClients_manager() {
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
up: async (queryInterface, Sequelize) => {
|
up: async (queryInterface, Sequelize) => {
|
||||||
await Employees.bulkCreate(EmployeesData);
|
|
||||||
|
|
||||||
await Inventory.bulkCreate(InventoryData);
|
await Inventory.bulkCreate(InventoryData);
|
||||||
|
|
||||||
await Machinery.bulkCreate(MachineryData);
|
await Machinery.bulkCreate(MachineryData);
|
||||||
@ -796,8 +760,6 @@ module.exports = {
|
|||||||
|
|
||||||
await associateUserWithCompany(),
|
await associateUserWithCompany(),
|
||||||
|
|
||||||
await associateEmployeeWithCompany(),
|
|
||||||
|
|
||||||
await associateInventoryWithCompany(),
|
await associateInventoryWithCompany(),
|
||||||
|
|
||||||
await associateMachineryWithCompany(),
|
await associateMachineryWithCompany(),
|
||||||
@ -812,6 +774,8 @@ module.exports = {
|
|||||||
|
|
||||||
await associateSupplierWithCompany(),
|
await associateSupplierWithCompany(),
|
||||||
|
|
||||||
|
await associateWorkOrderWithProduction_manager(),
|
||||||
|
|
||||||
// Similar logic for "relation_many"
|
// Similar logic for "relation_many"
|
||||||
|
|
||||||
// Similar logic for "relation_many"
|
// Similar logic for "relation_many"
|
||||||
@ -827,8 +791,6 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
down: async (queryInterface, Sequelize) => {
|
down: async (queryInterface, Sequelize) => {
|
||||||
await queryInterface.bulkDelete('employees', null, {});
|
|
||||||
|
|
||||||
await queryInterface.bulkDelete('inventory', null, {});
|
await queryInterface.bulkDelete('inventory', null, {});
|
||||||
|
|
||||||
await queryInterface.bulkDelete('machinery', null, {});
|
await queryInterface.bulkDelete('machinery', null, {});
|
||||||
|
|||||||
@ -23,8 +23,6 @@ const contactFormRoutes = require('./routes/contactForm');
|
|||||||
|
|
||||||
const usersRoutes = require('./routes/users');
|
const usersRoutes = require('./routes/users');
|
||||||
|
|
||||||
const employeesRoutes = require('./routes/employees');
|
|
||||||
|
|
||||||
const inventoryRoutes = require('./routes/inventory');
|
const inventoryRoutes = require('./routes/inventory');
|
||||||
|
|
||||||
const machineryRoutes = require('./routes/machinery');
|
const machineryRoutes = require('./routes/machinery');
|
||||||
@ -57,9 +55,9 @@ const options = {
|
|||||||
openapi: '3.0.0',
|
openapi: '3.0.0',
|
||||||
info: {
|
info: {
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
title: 'Test Editor',
|
title: 'Test Editor 100',
|
||||||
description:
|
description:
|
||||||
'Test Editor Online REST API for Testing and Prototyping application. You can perform all major operations with your entities - create, delete and etc.',
|
'Test Editor 100 Online REST API for Testing and Prototyping application. You can perform all major operations with your entities - create, delete and etc.',
|
||||||
},
|
},
|
||||||
servers: [
|
servers: [
|
||||||
{
|
{
|
||||||
@ -118,12 +116,6 @@ app.use(
|
|||||||
usersRoutes,
|
usersRoutes,
|
||||||
);
|
);
|
||||||
|
|
||||||
app.use(
|
|
||||||
'/api/employees',
|
|
||||||
passport.authenticate('jwt', { session: false }),
|
|
||||||
employeesRoutes,
|
|
||||||
);
|
|
||||||
|
|
||||||
app.use(
|
app.use(
|
||||||
'/api/inventory',
|
'/api/inventory',
|
||||||
passport.authenticate('jwt', { session: false }),
|
passport.authenticate('jwt', { session: false }),
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
const errors = {
|
const errors = {
|
||||||
app: {
|
app: {
|
||||||
title: 'Test Editor',
|
title: 'Test Editor 100',
|
||||||
},
|
},
|
||||||
|
|
||||||
auth: {
|
auth: {
|
||||||
|
|||||||
14
cloudbuild.yaml
Normal file
14
cloudbuild.yaml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
steps:
|
||||||
|
- name: 'gcr.io/cloud-builders/docker'
|
||||||
|
entrypoint: 'bash'
|
||||||
|
args: ['-c', 'docker pull gcr.io/fldemo-315215/test-editor-30652-dev:latest || exit 0']
|
||||||
|
- name: 'gcr.io/cloud-builders/docker'
|
||||||
|
args: [
|
||||||
|
'build',
|
||||||
|
'-t', 'gcr.io/fldemo-315215/test-editor-30652-dev:latest',
|
||||||
|
'--file', 'Dockerfile.dev',
|
||||||
|
'--cache-from', 'gcr.io/fldemo-315215/test-editor-30652-dev:latest',
|
||||||
|
'.'
|
||||||
|
]
|
||||||
|
images: ['gcr.io/fldemo-315215/test-editor-30652-dev:latest']
|
||||||
|
logsBucket: 'gs://fldemo-315215-cloudbuild-logs'
|
||||||
@ -15,7 +15,7 @@ services:
|
|||||||
- ./data/db:/var/lib/postgresql/data
|
- ./data/db:/var/lib/postgresql/data
|
||||||
environment:
|
environment:
|
||||||
- POSTGRES_HOST_AUTH_METHOD=trust
|
- POSTGRES_HOST_AUTH_METHOD=trust
|
||||||
- POSTGRES_DB=db_test_editor
|
- POSTGRES_DB=db_test_editor_100
|
||||||
ports:
|
ports:
|
||||||
- "5432:5432"
|
- "5432:5432"
|
||||||
backend:
|
backend:
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# Test Editor
|
# Test Editor 100
|
||||||
|
|
||||||
## This project was generated by Flatlogic Platform.
|
## This project was generated by Flatlogic Platform.
|
||||||
|
|
||||||
|
|||||||
1
frontend/json/runtimeError.json
Normal file
1
frontend/json/runtimeError.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
2
frontend/next-env.d.ts
vendored
2
frontend/next-env.d.ts
vendored
@ -2,4 +2,4 @@
|
|||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
|
||||||
|
|||||||
@ -75,7 +75,7 @@ export default function AsideMenuLayer({
|
|||||||
>
|
>
|
||||||
<div className='text-center flex-1 lg:text-left lg:pl-6 xl:text-center xl:pl-0'>
|
<div className='text-center flex-1 lg:text-left lg:pl-6 xl:text-center xl:pl-0'>
|
||||||
<Link href={'/home'}>
|
<Link href={'/home'}>
|
||||||
<b className='font-black'>Test Editor</b>
|
<b className='font-black'>Test Editor 100</b>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
{organizationName && <p>{organizationName}</p>}
|
{organizationName && <p>{organizationName}</p>}
|
||||||
|
|||||||
@ -18,9 +18,9 @@ export default function WebSiteFooter({
|
|||||||
const borders = useAppSelector((state) => state.style.borders);
|
const borders = useAppSelector((state) => state.style.borders);
|
||||||
const websiteHeder = useAppSelector((state) => state.style.websiteHeder);
|
const websiteHeder = useAppSelector((state) => state.style.websiteHeder);
|
||||||
|
|
||||||
const style = FooterStyle.WITH_PROJECT_NAME;
|
const style = FooterStyle.WITH_PAGES;
|
||||||
|
|
||||||
const design = FooterDesigns.DEFAULT_DESIGN;
|
const design = FooterDesigns.DESIGN_DIVERSITY;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -71,9 +71,9 @@ function MyApp({ Component, pageProps }: AppPropsWithLayout) {
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const title = 'Test Editor';
|
const title = 'Test Editor 100';
|
||||||
|
|
||||||
const description = 'Test Editor generated by Flatlogic';
|
const description = 'Test Editor 100 generated by Flatlogic';
|
||||||
|
|
||||||
const url = 'https://flatlogic.com/';
|
const url = 'https://flatlogic.com/';
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ import ContactFormSection from '../components/WebPageComponents/ContactFormCompo
|
|||||||
export default function WebSite() {
|
export default function WebSite() {
|
||||||
const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
|
const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
|
||||||
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
|
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
|
||||||
const projectName = 'Test Editor';
|
const projectName = 'Test Editor 100';
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const darkElement = document.querySelector('body .dark');
|
const darkElement = document.querySelector('body .dark');
|
||||||
@ -125,10 +125,10 @@ export default function WebSite() {
|
|||||||
content={`Discover our robust ERP solution tailored for the manufacturing industry. Streamline production, inventory, and workforce management with ease.`}
|
content={`Discover our robust ERP solution tailored for the manufacturing industry. Streamline production, inventory, and workforce management with ease.`}
|
||||||
/>
|
/>
|
||||||
</Head>
|
</Head>
|
||||||
<WebSiteHeader projectName={'Test Editor'} pages={pages} />
|
<WebSiteHeader projectName={'Test Editor 100'} pages={pages} />
|
||||||
<main className={`flex-grow bg-white rounded-none `}>
|
<main className={`flex-grow bg-white rounded-none `}>
|
||||||
<HeroSection
|
<HeroSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
image={['Modern factory with machinery']}
|
image={['Modern factory with machinery']}
|
||||||
mainText={`Revolutionize Manufacturing with ${projectName} ERP`}
|
mainText={`Revolutionize Manufacturing with ${projectName} ERP`}
|
||||||
subTitle={`Experience seamless production, inventory, and workforce management with ${projectName}. Our ERP solution is designed to simplify complexities and enhance efficiency in the manufacturing industry.`}
|
subTitle={`Experience seamless production, inventory, and workforce management with ${projectName}. Our ERP solution is designed to simplify complexities and enhance efficiency in the manufacturing industry.`}
|
||||||
@ -137,7 +137,7 @@ export default function WebSite() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<FeaturesSection
|
<FeaturesSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
image={['Dashboard showing ERP metrics']}
|
image={['Dashboard showing ERP metrics']}
|
||||||
withBg={1}
|
withBg={1}
|
||||||
features={features_points}
|
features={features_points}
|
||||||
@ -147,7 +147,7 @@ export default function WebSite() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<AboutUsSection
|
<AboutUsSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
image={['Team collaborating in modern office']}
|
image={['Team collaborating in modern office']}
|
||||||
mainText={`Empowering Manufacturing with ${projectName}`}
|
mainText={`Empowering Manufacturing with ${projectName}`}
|
||||||
subTitle={`At ${projectName}, we are dedicated to transforming the manufacturing industry with our innovative ERP solutions. Our mission is to simplify complex processes and enhance operational efficiency for businesses worldwide.`}
|
subTitle={`At ${projectName}, we are dedicated to transforming the manufacturing industry with our innovative ERP solutions. Our mission is to simplify complex processes and enhance operational efficiency for businesses worldwide.`}
|
||||||
@ -156,21 +156,21 @@ export default function WebSite() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<TestimonialsSection
|
<TestimonialsSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
design={TestimonialsDesigns.MULTI_CARD_DISPLAY || ''}
|
design={TestimonialsDesigns.MULTI_CARD_DISPLAY || ''}
|
||||||
testimonials={testimonials}
|
testimonials={testimonials}
|
||||||
mainText={`What Our Clients Say About ${projectName} `}
|
mainText={`What Our Clients Say About ${projectName} `}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ContactFormSection
|
<ContactFormSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
design={ContactFormDesigns.WITH_IMAGE || ''}
|
design={ContactFormDesigns.WITH_IMAGE || ''}
|
||||||
image={['Person typing on a laptop']}
|
image={['Person typing on a laptop']}
|
||||||
mainText={`Get in Touch with ${projectName} `}
|
mainText={`Get in Touch with ${projectName} `}
|
||||||
subTitle={`Reach out to us anytime for inquiries or support. Our team at ${projectName} is here to assist you promptly and efficiently.`}
|
subTitle={`Reach out to us anytime for inquiries or support. Our team at ${projectName} is here to assist you promptly and efficiently.`}
|
||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
<WebSiteFooter projectName={'Test Editor'} pages={pages} />
|
<WebSiteFooter projectName={'Test Editor 100'} pages={pages} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,7 +50,7 @@ export default function Login() {
|
|||||||
remember: true,
|
remember: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const title = 'Test Editor';
|
const title = 'Test Editor 100';
|
||||||
|
|
||||||
// Fetch Pexels image/video
|
// Fetch Pexels image/video
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -195,7 +195,7 @@ export default function Login() {
|
|||||||
<div className='flex items-center justify-center flex-col space-y-4 w-full lg:w-full'>
|
<div className='flex items-center justify-center flex-col space-y-4 w-full lg:w-full'>
|
||||||
<CardBox id='loginRoles' className='w-full md:w-3/5 lg:w-2/3'>
|
<CardBox id='loginRoles' className='w-full md:w-3/5 lg:w-2/3'>
|
||||||
<Link href={'/home'}>
|
<Link href={'/home'}>
|
||||||
<h2 className='text-4xl font-semibold my-4'> Test Editor</h2>
|
<h2 className='text-4xl font-semibold my-4'> {title}</h2>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<div className='flex flex-row text-gray-500 justify-between'>
|
<div className='flex flex-row text-gray-500 justify-between'>
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import LayoutGuest from '../layouts/Guest';
|
|||||||
import { getPageTitle } from '../config';
|
import { getPageTitle } from '../config';
|
||||||
|
|
||||||
export default function PrivacyPolicy() {
|
export default function PrivacyPolicy() {
|
||||||
const title = 'Test Editor';
|
const title = 'Test Editor 100';
|
||||||
const [projectUrl, setProjectUrl] = useState('');
|
const [projectUrl, setProjectUrl] = useState('');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import LayoutGuest from '../layouts/Guest';
|
|||||||
import { getPageTitle } from '../config';
|
import { getPageTitle } from '../config';
|
||||||
|
|
||||||
export default function PrivacyPolicy() {
|
export default function PrivacyPolicy() {
|
||||||
const title = 'Test Editor';
|
const title = 'Test Editor 100';
|
||||||
const [projectUrl, setProjectUrl] = useState('');
|
const [projectUrl, setProjectUrl] = useState('');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -24,7 +24,7 @@ import TestimonialsSection from '../../components/WebPageComponents/Testimonials
|
|||||||
export default function WebSite() {
|
export default function WebSite() {
|
||||||
const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
|
const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
|
||||||
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
|
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
|
||||||
const projectName = 'Test Editor';
|
const projectName = 'Test Editor 100';
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const darkElement = document.querySelector('body .dark');
|
const darkElement = document.querySelector('body .dark');
|
||||||
@ -122,10 +122,10 @@ export default function WebSite() {
|
|||||||
content={`Learn more about ${projectName}, our mission, values, and the innovative ERP solutions we offer to transform the manufacturing industry.`}
|
content={`Learn more about ${projectName}, our mission, values, and the innovative ERP solutions we offer to transform the manufacturing industry.`}
|
||||||
/>
|
/>
|
||||||
</Head>
|
</Head>
|
||||||
<WebSiteHeader projectName={'Test Editor'} pages={pages} />
|
<WebSiteHeader projectName={'Test Editor 100'} pages={pages} />
|
||||||
<main className={`flex-grow bg-white rounded-none `}>
|
<main className={`flex-grow bg-white rounded-none `}>
|
||||||
<HeroSection
|
<HeroSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
image={['Team collaborating in office']}
|
image={['Team collaborating in office']}
|
||||||
mainText={`Discover the Heart of ${projectName}`}
|
mainText={`Discover the Heart of ${projectName}`}
|
||||||
subTitle={`Dive into the story behind ${projectName}. Learn about our mission, values, and the innovative solutions we bring to the manufacturing industry.`}
|
subTitle={`Dive into the story behind ${projectName}. Learn about our mission, values, and the innovative solutions we bring to the manufacturing industry.`}
|
||||||
@ -134,7 +134,7 @@ export default function WebSite() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<AboutUsSection
|
<AboutUsSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
image={['Team brainstorming in conference room']}
|
image={['Team brainstorming in conference room']}
|
||||||
mainText={`Our Mission and Vision at ${projectName}`}
|
mainText={`Our Mission and Vision at ${projectName}`}
|
||||||
subTitle={`At ${projectName}, we are committed to revolutionizing the manufacturing industry with cutting-edge ERP solutions. Our vision is to empower businesses with tools that drive efficiency and innovation.`}
|
subTitle={`At ${projectName}, we are committed to revolutionizing the manufacturing industry with cutting-edge ERP solutions. Our vision is to empower businesses with tools that drive efficiency and innovation.`}
|
||||||
@ -143,9 +143,9 @@ export default function WebSite() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<FeaturesSection
|
<FeaturesSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
image={['ERP dashboard on a screen']}
|
image={['ERP dashboard on a screen']}
|
||||||
withBg={1}
|
withBg={0}
|
||||||
features={features_points}
|
features={features_points}
|
||||||
mainText={`Explore ${projectName} Core Features`}
|
mainText={`Explore ${projectName} Core Features`}
|
||||||
subTitle={`Discover the powerful features of ${projectName} that streamline your manufacturing operations and drive success.`}
|
subTitle={`Discover the powerful features of ${projectName} that streamline your manufacturing operations and drive success.`}
|
||||||
@ -153,13 +153,13 @@ export default function WebSite() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<TestimonialsSection
|
<TestimonialsSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
design={TestimonialsDesigns.HORIZONTAL_CAROUSEL_DIVERSITY || ''}
|
design={TestimonialsDesigns.HORIZONTAL_CAROUSEL_DIVERSITY || ''}
|
||||||
testimonials={testimonials}
|
testimonials={testimonials}
|
||||||
mainText={`Hear from Our Satisfied ${projectName} Clients `}
|
mainText={`Hear from Our Satisfied ${projectName} Clients `}
|
||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
<WebSiteFooter projectName={'Test Editor'} pages={pages} />
|
<WebSiteFooter projectName={'Test Editor 100'} pages={pages} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,7 @@ import ContactFormSection from '../../components/WebPageComponents/ContactFormCo
|
|||||||
export default function WebSite() {
|
export default function WebSite() {
|
||||||
const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
|
const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
|
||||||
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
|
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
|
||||||
const projectName = 'Test Editor';
|
const projectName = 'Test Editor 100';
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const darkElement = document.querySelector('body .dark');
|
const darkElement = document.querySelector('body .dark');
|
||||||
@ -62,10 +62,10 @@ export default function WebSite() {
|
|||||||
content={`Get in touch with ${projectName} for inquiries, support, or more information about our ERP solutions. Our team is here to assist you.`}
|
content={`Get in touch with ${projectName} for inquiries, support, or more information about our ERP solutions. Our team is here to assist you.`}
|
||||||
/>
|
/>
|
||||||
</Head>
|
</Head>
|
||||||
<WebSiteHeader projectName={'Test Editor'} pages={pages} />
|
<WebSiteHeader projectName={'Test Editor 100'} pages={pages} />
|
||||||
<main className={`flex-grow bg-white rounded-none `}>
|
<main className={`flex-grow bg-white rounded-none `}>
|
||||||
<HeroSection
|
<HeroSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
image={['Customer service representative smiling']}
|
image={['Customer service representative smiling']}
|
||||||
mainText={`Connect with ${projectName} Today`}
|
mainText={`Connect with ${projectName} Today`}
|
||||||
subTitle={`Have questions or need assistance? Reach out to the ${projectName} team for support and information about our ERP solutions. We're here to help you succeed.`}
|
subTitle={`Have questions or need assistance? Reach out to the ${projectName} team for support and information about our ERP solutions. We're here to help you succeed.`}
|
||||||
@ -74,14 +74,14 @@ export default function WebSite() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<ContactFormSection
|
<ContactFormSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
design={ContactFormDesigns.WITH_IMAGE || ''}
|
design={ContactFormDesigns.WITH_IMAGE || ''}
|
||||||
image={['Person typing on a laptop']}
|
image={['Person typing on a laptop']}
|
||||||
mainText={`Reach Out to ${projectName} `}
|
mainText={`Reach Out to ${projectName} `}
|
||||||
subTitle={`We're available to assist you with any inquiries or support needs. Contact ${projectName} and expect a prompt response from our dedicated team.`}
|
subTitle={`We're available to assist you with any inquiries or support needs. Contact ${projectName} and expect a prompt response from our dedicated team.`}
|
||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
<WebSiteFooter projectName={'Test Editor'} pages={pages} />
|
<WebSiteFooter projectName={'Test Editor 100'} pages={pages} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,7 @@ import FaqSection from '../../components/WebPageComponents/FaqComponent';
|
|||||||
export default function WebSite() {
|
export default function WebSite() {
|
||||||
const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
|
const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
|
||||||
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
|
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
|
||||||
const projectName = 'Test Editor';
|
const projectName = 'Test Editor 100';
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const darkElement = document.querySelector('body .dark');
|
const darkElement = document.querySelector('body .dark');
|
||||||
@ -100,10 +100,10 @@ export default function WebSite() {
|
|||||||
content={`Find answers to common questions about ${projectName} and our ERP solutions. Get the information you need to make the most of our services.`}
|
content={`Find answers to common questions about ${projectName} and our ERP solutions. Get the information you need to make the most of our services.`}
|
||||||
/>
|
/>
|
||||||
</Head>
|
</Head>
|
||||||
<WebSiteHeader projectName={'Test Editor'} pages={pages} />
|
<WebSiteHeader projectName={'Test Editor 100'} pages={pages} />
|
||||||
<main className={`flex-grow bg-white rounded-none `}>
|
<main className={`flex-grow bg-white rounded-none `}>
|
||||||
<HeroSection
|
<HeroSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
image={['Person reading a FAQ document']}
|
image={['Person reading a FAQ document']}
|
||||||
mainText={`Your Questions Answered with ${projectName}`}
|
mainText={`Your Questions Answered with ${projectName}`}
|
||||||
subTitle={`Explore our comprehensive FAQ section to find answers to your questions about ${projectName}. Get the insights you need to maximize the benefits of our ERP solutions.`}
|
subTitle={`Explore our comprehensive FAQ section to find answers to your questions about ${projectName}. Get the insights you need to maximize the benefits of our ERP solutions.`}
|
||||||
@ -112,13 +112,13 @@ export default function WebSite() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<FaqSection
|
<FaqSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
design={FaqDesigns.ACCORDION || ''}
|
design={FaqDesigns.ACCORDION || ''}
|
||||||
faqs={faqs}
|
faqs={faqs}
|
||||||
mainText={`Common Questions About ${projectName} `}
|
mainText={`Common Questions About ${projectName} `}
|
||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
<WebSiteFooter projectName={'Test Editor'} pages={pages} />
|
<WebSiteFooter projectName={'Test Editor 100'} pages={pages} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,7 +27,7 @@ import ContactFormSection from '../../components/WebPageComponents/ContactFormCo
|
|||||||
export default function WebSite() {
|
export default function WebSite() {
|
||||||
const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
|
const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
|
||||||
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
|
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
|
||||||
const projectName = 'Test Editor';
|
const projectName = 'Test Editor 100';
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const darkElement = document.querySelector('body .dark');
|
const darkElement = document.querySelector('body .dark');
|
||||||
@ -125,10 +125,10 @@ export default function WebSite() {
|
|||||||
content={`Discover our robust ERP solution tailored for the manufacturing industry. Streamline production, inventory, and workforce management with ease.`}
|
content={`Discover our robust ERP solution tailored for the manufacturing industry. Streamline production, inventory, and workforce management with ease.`}
|
||||||
/>
|
/>
|
||||||
</Head>
|
</Head>
|
||||||
<WebSiteHeader projectName={'Test Editor'} pages={pages} />
|
<WebSiteHeader projectName={'Test Editor 100'} pages={pages} />
|
||||||
<main className={`flex-grow bg-white rounded-none `}>
|
<main className={`flex-grow bg-white rounded-none `}>
|
||||||
<HeroSection
|
<HeroSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
image={['Modern factory with machinery']}
|
image={['Modern factory with machinery']}
|
||||||
mainText={`Revolutionize Manufacturing with ${projectName} ERP`}
|
mainText={`Revolutionize Manufacturing with ${projectName} ERP`}
|
||||||
subTitle={`Experience seamless production, inventory, and workforce management with ${projectName}. Our ERP solution is designed to simplify complexities and enhance efficiency in the manufacturing industry.`}
|
subTitle={`Experience seamless production, inventory, and workforce management with ${projectName}. Our ERP solution is designed to simplify complexities and enhance efficiency in the manufacturing industry.`}
|
||||||
@ -137,9 +137,9 @@ export default function WebSite() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<FeaturesSection
|
<FeaturesSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
image={['Dashboard showing ERP metrics']}
|
image={['Dashboard showing ERP metrics']}
|
||||||
withBg={0}
|
withBg={1}
|
||||||
features={features_points}
|
features={features_points}
|
||||||
mainText={`Unlock Efficiency with ${projectName} Features`}
|
mainText={`Unlock Efficiency with ${projectName} Features`}
|
||||||
subTitle={`Explore the powerful features of ${projectName} designed to streamline your manufacturing operations and boost productivity.`}
|
subTitle={`Explore the powerful features of ${projectName} designed to streamline your manufacturing operations and boost productivity.`}
|
||||||
@ -147,7 +147,7 @@ export default function WebSite() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<AboutUsSection
|
<AboutUsSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
image={['Team collaborating in modern office']}
|
image={['Team collaborating in modern office']}
|
||||||
mainText={`Empowering Manufacturing with ${projectName}`}
|
mainText={`Empowering Manufacturing with ${projectName}`}
|
||||||
subTitle={`At ${projectName}, we are dedicated to transforming the manufacturing industry with our innovative ERP solutions. Our mission is to simplify complex processes and enhance operational efficiency for businesses worldwide.`}
|
subTitle={`At ${projectName}, we are dedicated to transforming the manufacturing industry with our innovative ERP solutions. Our mission is to simplify complex processes and enhance operational efficiency for businesses worldwide.`}
|
||||||
@ -156,21 +156,21 @@ export default function WebSite() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<TestimonialsSection
|
<TestimonialsSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
design={TestimonialsDesigns.MULTI_CARD_DISPLAY || ''}
|
design={TestimonialsDesigns.MULTI_CARD_DISPLAY || ''}
|
||||||
testimonials={testimonials}
|
testimonials={testimonials}
|
||||||
mainText={`What Our Clients Say About ${projectName} `}
|
mainText={`What Our Clients Say About ${projectName} `}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ContactFormSection
|
<ContactFormSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
design={ContactFormDesigns.WITH_IMAGE || ''}
|
design={ContactFormDesigns.WITH_IMAGE || ''}
|
||||||
image={['Person typing on a laptop']}
|
image={['Person typing on a laptop']}
|
||||||
mainText={`Get in Touch with ${projectName} `}
|
mainText={`Get in Touch with ${projectName} `}
|
||||||
subTitle={`Reach out to us anytime for inquiries or support. Our team at ${projectName} is here to assist you promptly and efficiently.`}
|
subTitle={`Reach out to us anytime for inquiries or support. Our team at ${projectName} is here to assist you promptly and efficiently.`}
|
||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
<WebSiteFooter projectName={'Test Editor'} pages={pages} />
|
<WebSiteFooter projectName={'Test Editor 100'} pages={pages} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import TestimonialsSection from '../../components/WebPageComponents/Testimonials
|
|||||||
export default function WebSite() {
|
export default function WebSite() {
|
||||||
const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
|
const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
|
||||||
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
|
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
|
||||||
const projectName = 'Test Editor';
|
const projectName = 'Test Editor 100';
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const darkElement = document.querySelector('body .dark');
|
const darkElement = document.querySelector('body .dark');
|
||||||
@ -137,10 +137,10 @@ export default function WebSite() {
|
|||||||
content={`Explore the comprehensive services offered by ${projectName} to enhance your manufacturing operations. Discover how our ERP solutions can streamline processes and drive success.`}
|
content={`Explore the comprehensive services offered by ${projectName} to enhance your manufacturing operations. Discover how our ERP solutions can streamline processes and drive success.`}
|
||||||
/>
|
/>
|
||||||
</Head>
|
</Head>
|
||||||
<WebSiteHeader projectName={'Test Editor'} pages={pages} />
|
<WebSiteHeader projectName={'Test Editor 100'} pages={pages} />
|
||||||
<main className={`flex-grow bg-white rounded-none `}>
|
<main className={`flex-grow bg-white rounded-none `}>
|
||||||
<HeroSection
|
<HeroSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
image={['Factory floor with machinery']}
|
image={['Factory floor with machinery']}
|
||||||
mainText={`Transform Your Operations with ${projectName}`}
|
mainText={`Transform Your Operations with ${projectName}`}
|
||||||
subTitle={`Discover the range of services offered by ${projectName} to streamline your manufacturing processes. Our ERP solutions are designed to enhance efficiency and drive growth.`}
|
subTitle={`Discover the range of services offered by ${projectName} to streamline your manufacturing processes. Our ERP solutions are designed to enhance efficiency and drive growth.`}
|
||||||
@ -149,9 +149,9 @@ export default function WebSite() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<FeaturesSection
|
<FeaturesSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
image={['ERP system interface on screen']}
|
image={['ERP system interface on screen']}
|
||||||
withBg={0}
|
withBg={1}
|
||||||
features={features_points}
|
features={features_points}
|
||||||
mainText={`Unleash the Power of ${projectName} Services`}
|
mainText={`Unleash the Power of ${projectName} Services`}
|
||||||
subTitle={`Explore the key features of ${projectName} that are designed to optimize your manufacturing operations and drive success.`}
|
subTitle={`Explore the key features of ${projectName} that are designed to optimize your manufacturing operations and drive success.`}
|
||||||
@ -159,13 +159,13 @@ export default function WebSite() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<TestimonialsSection
|
<TestimonialsSection
|
||||||
projectName={'Test Editor'}
|
projectName={'Test Editor 100'}
|
||||||
design={TestimonialsDesigns.MULTI_CARD_DISPLAY || ''}
|
design={TestimonialsDesigns.MULTI_CARD_DISPLAY || ''}
|
||||||
testimonials={testimonials}
|
testimonials={testimonials}
|
||||||
mainText={`What Our Clients Say About ${projectName} `}
|
mainText={`What Our Clients Say About ${projectName} `}
|
||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
<WebSiteFooter projectName={'Test Editor'} pages={pages} />
|
<WebSiteFooter projectName={'Test Editor 100'} pages={pages} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
1
pids/backend.pid
Normal file
1
pids/backend.pid
Normal file
@ -0,0 +1 @@
|
|||||||
|
4
|
||||||
1
pids/frontend.pid
Normal file
1
pids/frontend.pid
Normal file
@ -0,0 +1 @@
|
|||||||
|
3
|
||||||
Loading…
x
Reference in New Issue
Block a user