-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add exports, OTable pagination and columns search
- Loading branch information
1 parent
b164646
commit 28c52a4
Showing
24 changed files
with
839 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
export const columnNames = { | ||
firstname: "Prénom", | ||
lastname: "Nom", | ||
email: "Email", | ||
name: "Nom", | ||
description: "Description", | ||
gender: "Genre", | ||
createdAt: "Date de création", | ||
role: "Rôle", | ||
disabled: "Statut", | ||
id: "ID", | ||
passwordUpdatedAt: "Date de modification du mot de passe", | ||
passwordResetToken: "Token de réinitialisation du mot de passe", | ||
birthdate: "Date de naissance", | ||
address: "Adresse", | ||
postalCode: "Code postal", | ||
city: "Ville", | ||
phone: "Téléphone", | ||
loginAttempts: "Nombre de tentatives de connexion", | ||
blockedAt: "Date de blocage", | ||
isValidate: "E-mail confirmé", | ||
authentificationToken: "Token d'authentification", | ||
updatedAt: "Date de modification", | ||
price: "Prix", | ||
vat: "TVA", | ||
quantity: "Qté", | ||
size: "Taille", | ||
color: "Couleur", | ||
status: "Statut", | ||
userId: "ID utilisateur", | ||
deliveryAddress: "Adresse de livraison", | ||
products: "Produits", | ||
user: "ID utilisateur", | ||
sku: "SKU", | ||
discount: "Réduction", | ||
alertQuantity: "Qté. avant alerte", | ||
deletedAt: "Date de suppression", | ||
modelId: "ID modèle", | ||
productImage: "Image", | ||
productImages: "Images", | ||
model: "Modèle", | ||
models: "Modèles", | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { createObjectCsvStringifier } from "csv-writer"; | ||
|
||
export const dataToCSV = async function (data) { | ||
const header = []; | ||
for (const colName of Object.keys(data[0])) { | ||
header.push({ | ||
id: colName, | ||
title: colName, | ||
}); | ||
} | ||
|
||
const csvStringifier = createObjectCsvStringifier({ | ||
header, | ||
fieldDelimiter: ";", | ||
}); | ||
|
||
for (let i = 0; i < data.length; i++) { | ||
for (const key in data[i]) { | ||
if (!data[i][key]) continue; | ||
if (typeof data[i][key] !== "string") continue; | ||
data[i][key] = data[i][key].replaceAll(/\n/g, " | "); | ||
} | ||
} | ||
|
||
const csvData = | ||
csvStringifier.getHeaderString() + | ||
csvStringifier.stringifyRecords(data); | ||
|
||
return Buffer.from(csvData, "utf8"); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import mongoose from "mongoose"; | ||
|
||
const exportSchema = new mongoose.Schema( | ||
{ | ||
dataScope: { | ||
type: String, | ||
required: true, | ||
}, | ||
fileName: { | ||
type: String, | ||
required: true, | ||
}, | ||
}, | ||
{ timestamps: true } | ||
); | ||
|
||
const Export = mongoose.model("Export", exportSchema); | ||
|
||
export default Export; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import express from "express"; | ||
import exportsRoutes from "../routes/exportsRoutes.js"; | ||
import Export from "../models/mongodb-export.js"; | ||
import { exportData } from "../services/exports.service.js"; | ||
import { dataToCSV } from "../lib/dataToCSV.js"; | ||
import path from "path"; | ||
import fs from "fs"; | ||
const { requestExport, getExports, getExport, removeExport } = exportsRoutes( | ||
exportData, | ||
Export, | ||
dataToCSV, | ||
path, | ||
fs | ||
); | ||
|
||
const router = express.Router(); | ||
|
||
router.get("/", getExports); | ||
router.get("/:id", getExport); | ||
router.post("/", requestExport); | ||
router.delete("/:id", removeExport); | ||
|
||
export default router; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
export default (exportData, Export, dataToCSV, path, fs) => ({ | ||
requestExport: async (req, res) => { | ||
try { | ||
const dataScope = req.body.dataScope; | ||
const data = await exportData(dataScope); | ||
const csv = await dataToCSV(data); | ||
|
||
const currentModuleFile = new URL(import.meta.url).pathname; | ||
const currentModuleDirectory = path.dirname(currentModuleFile); | ||
|
||
const fileName = `${dataScope}-${new Date() | ||
.toLocaleDateString("fr-FR") | ||
.replaceAll("/", "-")}-${Math.random() | ||
.toString(36) | ||
.slice(2)}.csv`; | ||
const filePath = path.join( | ||
currentModuleDirectory, | ||
"../../uploads/exports", | ||
fileName | ||
); | ||
fs.writeFileSync(filePath, csv); | ||
await Export.create({ | ||
dataScope, | ||
fileName, | ||
}); | ||
console.log(`Exported ${dataScope} successfully`); | ||
return res.json({ fileName }); | ||
} catch (err) { | ||
console.error(err); | ||
return res.sendStatus(500); | ||
} | ||
}, | ||
getExports: async (req, res) => { | ||
try { | ||
const exports = await Export.find(); | ||
return res.status(200).json(exports); | ||
} catch (err) { | ||
console.error(err); | ||
return res | ||
.status(500) | ||
.json(`Error while getting exports: ${err.message}`); | ||
} | ||
}, | ||
getExport: async (req, res) => { | ||
try { | ||
const exportToFind = await Export.findById(req.params.id); | ||
return res.status(200).json(exportToFind); | ||
} catch (err) { | ||
console.error(err); | ||
return res.sendStatus(500); | ||
} | ||
}, | ||
removeExport: async (req, res) => { | ||
try { | ||
const exportToRemove = await Export.findById(req.params.id); | ||
await Export.deleteOne({ _id: req.params.id }); | ||
|
||
const currentModuleFile = new URL(import.meta.url).pathname; | ||
const currentModuleDirectory = path.dirname(currentModuleFile); | ||
|
||
const filePath = path.join( | ||
currentModuleDirectory, | ||
"../../uploads/exports", | ||
exportToRemove.fileName | ||
); | ||
if (fs.existsSync(filePath)) { | ||
fs.unlink(filePath, (err) => { | ||
if (err) { | ||
console.error( | ||
`Error deleting ${filePath}: ${err.message}` | ||
); | ||
} else { | ||
console.log(`Deleted ${filePath}`); | ||
} | ||
}); | ||
} else { | ||
console.log(`${filePath} does not exist.`); | ||
} | ||
|
||
return res.sendStatus(200); | ||
} catch (err) { | ||
console.error(err); | ||
return res.sendStatus(500); | ||
} | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import User from "../models/postgres-user.js"; | ||
import Product from "../models/postgres-product.js"; | ||
import Model from "../models/postgres-model.js"; | ||
import Brand from "../models/postgres-brand.js"; | ||
import Category from "../models/postgres-category.js"; | ||
import Order from "../models/postgres-order.js"; | ||
import { columnNames } from "../lib/columnsNames.js"; | ||
|
||
export const exportData = async (dataScope) => { | ||
let data; | ||
switch (dataScope) { | ||
case "users": | ||
const users = await User.findAll({ | ||
attributes: { | ||
exclude: [ | ||
"password", | ||
"passwordResetToken", | ||
"encryptionKey", | ||
"authentificationToken", | ||
], | ||
}, | ||
}); | ||
data = users.map((user) => user.dataValues); | ||
break; | ||
case "products": | ||
const products = await Product.findAll(); | ||
data = products.map((product) => product.dataValues); | ||
break; | ||
case "models": | ||
const models = await Model.findAll(); | ||
data = models.map((model) => model.dataValues); | ||
break; | ||
case "brands": | ||
const brands = await Brand.findAll(); | ||
data = brands.map((brand) => brand.dataValues); | ||
break; | ||
case "categories": | ||
const categories = await Category.findAll(); | ||
data = categories.map((category) => category.dataValues); | ||
break; | ||
case "orders": | ||
const orders = await Order.findAll(); | ||
data = orders.map((order) => order.dataValues); | ||
break; | ||
default: | ||
data = []; | ||
console.log("dataScope not found"); | ||
break; | ||
} | ||
data = data.map((item) => { | ||
const formattedItem = {}; | ||
|
||
for (const key in item) { | ||
if (Object.prototype.hasOwnProperty.call(item, key)) { | ||
const formattedKey = columnNames[key] || key; | ||
|
||
if (item[key] instanceof Date) { | ||
formattedItem[formattedKey] = | ||
item[key].toLocaleString("fr-FR"); | ||
} else { | ||
formattedItem[formattedKey] = item[key]; | ||
} | ||
} | ||
} | ||
|
||
return formattedItem; | ||
}); | ||
|
||
return data; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.