diff --git a/.DS_Store b/.DS_Store index 9532a00..0730525 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/app/.DS_Store b/app/.DS_Store index a6a5969..344d73c 100644 Binary files a/app/.DS_Store and b/app/.DS_Store differ diff --git a/app/controllers/route-path.controller.js b/app/controllers/route-path.controller.js index f6c4f0d..f7198b5 100644 --- a/app/controllers/route-path.controller.js +++ b/app/controllers/route-path.controller.js @@ -167,7 +167,14 @@ exports.updateRouteInProgress = (req, res) => { finalCustomerList.push(cust); } } - const finalBody = Object.assign({}, routeBody, {route_customer_list: finalCustomerList}) + let finalBody = {}; + if (finalCustomerList?.length > 0) { + finalBody = Object.assign({}, routeBody, {route_customer_list: finalCustomerList}) + } else { + const newBody = Object.assign({}, routeBody); + delete newBody.route_customer_list; + finalBody = Object.assign({}, newBody) + } RoutePath.findByIdAndUpdate(currentRoute.id, finalBody, { useFindAndModify: false }) .then(data => { // console.log('success', data.id); diff --git a/app/controllers/upload.controller.js b/app/controllers/upload.controller.js index 8acb0cc..bed76af 100644 --- a/app/controllers/upload.controller.js +++ b/app/controllers/upload.controller.js @@ -1,10 +1,19 @@ const upload = require("../middlewares/upload"); +// const uploadPhysical = require("../middlewares/upload_physical"); const dbConfig = require("../config/db.config"); const MongoClient = require("mongodb").MongoClient; const GridFSBucket = require("mongodb").GridFSBucket; +const util = require("util"); +var fs = require('fs'); +var multer = require('multer'); +const path = require("path"); const url = dbConfig.url; const baseUrl = dbConfig.fileUrl; const mongoClient = new MongoClient(url); + +const readdir = util.promisify(fs.readdir); +const stat = util.promisify(fs.stat); + const uploadFiles = async (req, res) => { try { await upload(req, res); @@ -63,8 +72,91 @@ const deleteFile = async (req, res) => { } }; +const uploadPhysicalFile = async (req, res) => { + try { + // Destination and file name would be adjusted to be the same with original file system + const {objectId, name, fileType, model} = req.query; + const uploadedFile = req.file; + if (!uploadedFile) { + return res.status(400).send({ + message: 'No file uploaded.' + }) + } + return res.status(200).send({ + message: `File ${fileType} Uploaded Successfully for ${model} ${objectId}-${name}` + }) + + } catch (error) { + return res.status(500).send({ + message: error.message, + }); + } +} + +const getFilesByType = async (req, res) => { + try { + const {objectId, fileType, name, model} = req.params; + + if (!objectId || !name || !fileType || !model) { + return res.status(400).send({message: 'Required fields missed'}); + } + + const BASE_UPLOAD_DIR = `/www/wwwroot/upload/`; + const filesDir = `${BASE_UPLOAD_DIR}${model}/${objectId}/${fileType}/`; + + if (!fs.existsSync(filesDir)) { + return res.status(200).send({ + data: { + objectId, + model, + fileType, + name, + files: [], + count: 0 + } + }) + } + + const fileEntries = await readdir(filesDir, { withFileTypes: true}); + + const filePromises = fileEntries.filter(entry => entry.isFile()).map(async (entry) => { + const filePath = path.join(filesDir, entry.name); + const stats = await stat(filePath); + + const fileUrl = `/files/${model}/${objectId}/${fileType}/${entry.name}`; + return { + name: entry.name, + url: fileUrl, + size: stats.size, + extension: path.extname(entry.name), + createdAt: stats.birthtime, + modifiedAt: stats.mtime + } + }); + const files = await Promise.all(filePromises); + return res.status(200).json({ + data: { + objectId, + fileType, + name, + files, + count: files.length + } + }) + + } catch(err) { + return res.status(500).send({ + message: err.message + }) + } +} + + + module.exports = { uploadFiles, getFile, - deleteFile + deleteFile, + uploadPhysicalFile, + getFilesByType }; \ No newline at end of file diff --git a/app/controllers/vehicle.controller.js b/app/controllers/vehicle.controller.js index 864e019..4b8dec3 100644 --- a/app/controllers/vehicle.controller.js +++ b/app/controllers/vehicle.controller.js @@ -21,7 +21,15 @@ exports.createVehicle = (req, res) => { year: req.body.year || '', checklist: req.body.checklist || '', status: 'active', - site + site, + has_lift_equip: req.body.has_lift_equip, + vin: req.body.vin || '', + note: req.body.note || '', + insurance_expire_on: req.body.insurance_expire_on, + title_registration_on: req.body.title_registration_on, + emission_test_on: req.body.emission_test_on, + oil_change_mileage: req.body.oil_change_mileage, + oil_change_date: req.body.oil_change_date }); // Save Vehicle in the database diff --git a/app/middlewares/index.js b/app/middlewares/index.js index 05728e4..33bc1b6 100644 --- a/app/middlewares/index.js +++ b/app/middlewares/index.js @@ -1,6 +1,8 @@ const authJwt = require("./authJwt"); const splitSite = require("./splitSite"); +const uploadPhysicalFile = require("./upload_physical"); module.exports = { authJwt, - splitSite + splitSite, + uploadPhysicalFile }; \ No newline at end of file diff --git a/app/middlewares/upload_physical.js b/app/middlewares/upload_physical.js new file mode 100644 index 0000000..4c2c40d --- /dev/null +++ b/app/middlewares/upload_physical.js @@ -0,0 +1,93 @@ +var fs = require('fs'); +var multer = require('multer'); +const path = require("path"); + +const BASE_UPLOAD_DIR = `/www/wwwroot/upload/`; + +// try { +// if (!fs.existsSync(BASE_UPLOAD_DIR)) { +// fs.mkdirSync(BASE_UPLOAD_DIR, {recursive: true}); +// console.log (`Created upload directory: ${BASE_UPLOAD_DIR}`); +// } +// } catch(err) { +// console.error(`Error creating directory ${BASE_UPLOAD_DIR}`) +// } + + +const storage = multer.diskStorage({ + destination: (req, file, cb) => { + const { objectId, fileType, name, model } = req.query; + if (!objectId || !name || !fileType || !model) { + return res.status(400).send({message: 'Required fields missed'}); + } + const uploadDir = `${BASE_UPLOAD_DIR}${model}/${objectId}/${fileType}/`; + if (!fs.existsSync(uploadDir)) { + fs.mkdirSync(uploadDir, {recursive: true}); + console.log (`Created upload directory: ${uploadDir}/`); + } + cb(null, uploadDir); + }, + filename: (req, file, cb) => { + const { objectId, fileType, name, date} = req.query; + const uniqueSuffix = date || Date.now(); + const payload = req.body; + console.log('is the payload', payload); + cb(null, `${name.replaceAll(' ', '_')}_${objectId}_${fileType}_${uniqueSuffix}${path.extname(file.originalname)}`) + } +}) +const uploadPhysicalFile = multer({ + storage: storage, + limits: {fileSize: 10 * 1024* 1024}, + fileFilter: (req, file, cb) => cb(null, true) +}).single('file'); + +// const memoryStorage = multer.memoryStorage(); + +// const upload = multer({ +// storage: memoryStorage, +// limits: { fileSize: 10 * 1024* 1024} +// }); + +// const uploadPhysicalFile = (req, res, next) => { +// upload.single('file')(req, res, async (err) => { +// if (err) { +// return res.status(400).send({message: `Uplodad Error: ${err}`}); +// } + +// if (!req.file) { +// return res.status(400).send({message: 'No File uploaded'}); +// } + +// try { +// const {objectId, name, fileType} = req.body; +// if (!objectId || !name || fileType) { +// return res.status(400).send({message: 'Required fields missed'}); +// } +// const uploadDir = `${BASE_UPLOAD_DIR}${objectId}/${fileType}/`; +// if (!fs.existsSync(uploadDir)) { +// fs.mkdirSync(uploadDir, {recursive: true}); +// console.log (`Created upload directory: ${uploadDir}`); +// } +// const uniqueSuffix = Date.now(); +// const fileExension = path.extname(req.file.originalname); +// const fileName = `${name.replaceAll(' ', '_')}_${objectId}_${fileType}_${uniqueSuffix}${fileExension}`; +// const filePath = path.join(uploadDir, fileName); + +// fs.writeFileSync(filePath, req.file.buffer); + +// req.fileInfo = { +// filename: fileName, +// path: filePath, +// originalname: req.file.originalname, +// size: req.file.size +// }; +// next(); + +// } catch (err) { +// return res.status(500).send({message: `Upload Parsing error: ${err}`}); +// } +// }) +// } + + +module.exports = uploadPhysicalFile; \ No newline at end of file diff --git a/app/models/employee.model.js b/app/models/employee.model.js index 398679e..400a41f 100644 --- a/app/models/employee.model.js +++ b/app/models/employee.model.js @@ -1,4 +1,3 @@ -const uniqueValidator = require('mongoose-unique-validator'); module.exports = mongoose => { var schema = mongoose.Schema( { diff --git a/app/models/vehicle.model.js b/app/models/vehicle.model.js index b64a94c..fe2ba84 100644 --- a/app/models/vehicle.model.js +++ b/app/models/vehicle.model.js @@ -25,7 +25,15 @@ module.exports = mongoose => { type: String }], status: String, - site: Number + site: Number, + vin: String, + has_lift_equip: Boolean, + insurance_expire_on: String, + title_registration_on: String, + emission_test_on: String, + oil_change_mileage: Number, + oil_change_date: String, + note: String }, { collection: 'vehicle', timestamps: true } ); diff --git a/app/routes/upload.routes.js b/app/routes/upload.routes.js index 20c4f59..f46165f 100644 --- a/app/routes/upload.routes.js +++ b/app/routes/upload.routes.js @@ -1,8 +1,12 @@ +const {uploadPhysicalFile} = require("../middlewares"); + module.exports = app => { const upload = require("../controllers/upload.controller.js"); var router = require("express").Router(); router.get("/:name", upload.getFile); router.post("/upload/:filename", upload.uploadFiles); + router.post("/upload-physical", [uploadPhysicalFile], upload.uploadPhysicalFile); router.post("/delete", upload.deleteFile); + router.get("/uploadedDocs/:model/:objectId/type/:fileType/name/:name", upload.getFilesByType); app.use('/api/files', router); }; \ No newline at end of file diff --git a/app/views/asset-manifest.json b/app/views/asset-manifest.json index 68703f7..1232e5c 100644 --- a/app/views/asset-manifest.json +++ b/app/views/asset-manifest.json @@ -1,16 +1,16 @@ { "files": { - "main.css": "/static/css/main.2fa2d232.css", - "main.js": "/static/js/main.da419ea1.js", + "main.css": "/static/css/main.e5412702.css", + "main.js": "/static/js/main.26b7d753.js", "static/js/787.c4e7f8f9.chunk.js": "/static/js/787.c4e7f8f9.chunk.js", "static/media/landing.png": "/static/media/landing.d4c6072db7a67dff6a78.png", "index.html": "/index.html", - "main.2fa2d232.css.map": "/static/css/main.2fa2d232.css.map", - "main.da419ea1.js.map": "/static/js/main.da419ea1.js.map", + "main.e5412702.css.map": "/static/css/main.e5412702.css.map", + "main.26b7d753.js.map": "/static/js/main.26b7d753.js.map", "787.c4e7f8f9.chunk.js.map": "/static/js/787.c4e7f8f9.chunk.js.map" }, "entrypoints": [ - "static/css/main.2fa2d232.css", - "static/js/main.da419ea1.js" + "static/css/main.e5412702.css", + "static/js/main.26b7d753.js" ] } \ No newline at end of file diff --git a/app/views/index.html b/app/views/index.html index f6ea37a..c47c2a0 100644 --- a/app/views/index.html +++ b/app/views/index.html @@ -1 +1 @@ -
`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\n\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n\n// Abbreviations\n//\n// 1. Duplicate behavior to the data-bs-* attribute for our tooltip plugin\n// 2. Add the correct text decoration in Chrome, Edge, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Prevent the text-decoration to be skipped.\n\nabbr[title],\nabbr[data-bs-original-title] { // 1\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n text-decoration-skip-ink: none; // 4\n}\n\n\n// Address\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\n\n// Lists\n\nol,\nul {\n padding-left: 2rem;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\n// 1. Undo browser default\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // 1\n}\n\n\n// Blockquote\n\nblockquote {\n margin: 0 0 1rem;\n}\n\n\n// Strong\n//\n// Add the correct font weight in Chrome, Edge, and Safari\n\nb,\nstrong {\n font-weight: $font-weight-bolder;\n}\n\n\n// Small\n//\n// Add the correct font size in all browsers\n\nsmall {\n @include font-size($small-font-size);\n}\n\n\n// Mark\n\nmark {\n padding: $mark-padding;\n background-color: $mark-bg;\n}\n\n\n// Sub and Sup\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n\nsub,\nsup {\n position: relative;\n @include font-size($sub-sup-font-size);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n// Links\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n\n &:hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([class]) {\n &,\n &:hover {\n color: inherit;\n text-decoration: none;\n }\n}\n\n\n// Code\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-code;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n direction: ltr #{\"/* rtl:ignore */\"};\n unicode-bidi: bidi-override;\n}\n\n// 1. Remove browser default top margin\n// 2. Reset browser default of `1em` to use `rem`s\n// 3. Don't allow content to break outside\n\npre {\n display: block;\n margin-top: 0; // 1\n margin-bottom: 1rem; // 2\n overflow: auto; // 3\n @include font-size($code-font-size);\n color: $pre-color;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n @include font-size(inherit);\n color: inherit;\n word-break: normal;\n }\n}\n\ncode {\n @include font-size($code-font-size);\n color: $code-color;\n word-wrap: break-word;\n\n // Streamline the style when inside anchors to avoid broken underline and more\n a > & {\n color: inherit;\n }\n}\n\nkbd {\n padding: $kbd-padding-y $kbd-padding-x;\n @include font-size($kbd-font-size);\n color: $kbd-color;\n background-color: $kbd-bg;\n @include border-radius($border-radius-sm);\n\n kbd {\n padding: 0;\n @include font-size(1em);\n font-weight: $nested-kbd-font-weight;\n }\n}\n\n\n// Figures\n//\n// Apply a consistent margin strategy (matches our type styles).\n\nfigure {\n margin: 0 0 1rem;\n}\n\n\n// Images and content\n\nimg,\nsvg {\n vertical-align: middle;\n}\n\n\n// Tables\n//\n// Prevent double borders\n\ntable {\n caption-side: bottom;\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: $table-cell-padding-y;\n padding-bottom: $table-cell-padding-y;\n color: $table-caption-color;\n text-align: left;\n}\n\n// 1. Removes font-weight bold by inheriting\n// 2. Matches default `