1316 lines
37 KiB
JavaScript
1316 lines
37 KiB
JavaScript
const Category = require("../models/Category");
|
|
const Content = require("../models/Content");
|
|
const { body, validationResult } = require("express-validator");
|
|
const { _sr } = require("../plugins/serverResponses");
|
|
const {
|
|
res404,
|
|
res500,
|
|
checkValidations,
|
|
} = require("../plugins/controllersHelperFunctions");
|
|
const News = require("../models/News");
|
|
const sharp = require("sharp");
|
|
const fs = require("fs");
|
|
const { extname } = require("path");
|
|
|
|
// variables
|
|
const titleFilterRegex = new RegExp("/", "g");
|
|
const noCover = "/img/no-cover.jpg";
|
|
const coverNewsWidth = 400;
|
|
const coverNewsHeight = 400;
|
|
const coverQuality = 100;
|
|
////////////////// functions
|
|
const _customTitle = async (categories) => {
|
|
try {
|
|
const newCatArr = [];
|
|
for (const item of categories) {
|
|
const title = [];
|
|
const treeCat = item.treeCat;
|
|
|
|
for (let i = treeCat.length - 1; i >= 0; i--) {
|
|
title.push(treeCat[i].title);
|
|
}
|
|
|
|
title.push(item.title);
|
|
|
|
item.title = title.join(" >> ");
|
|
|
|
newCatArr.push(item);
|
|
}
|
|
|
|
return newCatArr;
|
|
} catch (error) {
|
|
console.log(error);
|
|
return [];
|
|
}
|
|
};
|
|
|
|
/** یک آرایه داریم که خونه اول رو میگیریم و میریزیم داخل آرایه جدید بعد داخل فور دوم کل آرایه رو طی میکنیم
|
|
* و اونایی که قسمتی از تایتل دیتای پوش شده داخل آرایه جدید رو دارن داخل این آرایه جدید پوش میکنیم
|
|
*/
|
|
|
|
// todo this is peace of shit please change it in future
|
|
const _sortedCategory = async (categories) => {
|
|
try {
|
|
let sortedArr = [];
|
|
|
|
// let clone = JSON.parse(JSON.stringify(categories));
|
|
//
|
|
// for (const cat of clone) {
|
|
// if (cat.parent){
|
|
// let getParent = categories.find(item => item._id === cat.parent._id)
|
|
// }
|
|
// }
|
|
|
|
for (let i = 0; i < categories.length; i++) {
|
|
if (!sortedArr.includes(categories[i]) && !categories[i].parent) {
|
|
sortedArr.push(categories[i]);
|
|
}
|
|
for (let j = 0; j < categories.length; j++) {
|
|
if (
|
|
categories[i].childs.includes(categories[j]._id) &&
|
|
!sortedArr.includes(categories[j])
|
|
) {
|
|
sortedArr.push(categories[j]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (sortedArr.length !== categories.length) {
|
|
for (const cat of categories) {
|
|
if (!sortedArr.includes(cat)) {
|
|
sortedArr.push(cat);
|
|
}
|
|
}
|
|
}
|
|
|
|
return sortedArr;
|
|
} catch (error) {
|
|
console.log(error);
|
|
return [];
|
|
}
|
|
};
|
|
|
|
const _checkSpecPermission = async (req, category) => {
|
|
return (
|
|
!req.user.specialPermissions.includes(category._id) && //check parent id exist in special permissions or not
|
|
!req.user.specialPermissions.some((item) =>
|
|
category?.treeCat?.join().includes(item)
|
|
)
|
|
);
|
|
};
|
|
/////////////////////////////////////////////////////////////////////// admin
|
|
module.exports.addCategory = [
|
|
[
|
|
body("title")
|
|
.notEmpty()
|
|
.withMessage(_sr["fa"].required.title)
|
|
.custom((value, { req }) => {
|
|
return Category.findOne({
|
|
title: value,
|
|
}).then((category) => {
|
|
if (category) return Promise.reject(_sr["fa"].duplicated.title);
|
|
else return true;
|
|
});
|
|
}),
|
|
|
|
body("parent")
|
|
.optional()
|
|
.isString()
|
|
.withMessage(`parent ${_sr["fa"].optional.string}`),
|
|
|
|
// body('showInMenu')
|
|
// .isBoolean().withMessage(_sr['fa'].format.boolean),
|
|
|
|
body("navIndex")
|
|
.optional()
|
|
.isNumeric()
|
|
.withMessage(_sr["fa"].format.number),
|
|
|
|
body("priority").isNumeric().withMessage(_sr["fa"].format.number),
|
|
|
|
// body('showInSectionOne')
|
|
// .optional().isBoolean().withMessage(_sr['fa'].format.boolean),
|
|
//
|
|
// body('showInSectionTwo')
|
|
// .optional().isBoolean().withMessage(_sr['fa'].format.boolean),
|
|
//
|
|
// body('showInSectionThree')
|
|
// .optional().isBoolean().withMessage(_sr['fa'].format.boolean),
|
|
|
|
body("siteMap").isBoolean().withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("special").isBoolean().withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("url")
|
|
.optional()
|
|
.isString()
|
|
.withMessage(`url ${_sr["fa"].optional.string}`),
|
|
|
|
body("pageContent")
|
|
.optional()
|
|
.isString()
|
|
.withMessage(`pageContent ${_sr["fa"].optional.string}`),
|
|
|
|
body("news").optional().isBoolean().withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("child").optional().isBoolean().withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasNewsTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasContentTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasMediaTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasSubMenusTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasTermsTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasNotificationsTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasSpecNewsTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasNazarTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasNewsFileTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("modelType").custom((value, { req }) => {
|
|
if (req.user.portals.join() === portal.join()) {
|
|
if (!portal.includes(value)) {
|
|
return Promise.reject(_sr["fa"].required.field);
|
|
} else {
|
|
return true;
|
|
}
|
|
} else {
|
|
return true;
|
|
}
|
|
}),
|
|
],
|
|
checkValidations(validationResult),
|
|
async (req, res) => {
|
|
try {
|
|
let {
|
|
title,
|
|
parent,
|
|
// showInMenu,
|
|
navIndex,
|
|
priority,
|
|
// showInSectionOne,
|
|
// showInSectionTwo,
|
|
// showInSectionThree,
|
|
siteMap,
|
|
special,
|
|
modelType,
|
|
showInFooter,
|
|
url,
|
|
pageContent,
|
|
news,
|
|
child,
|
|
hasNewsTab,
|
|
hasContentTab,
|
|
hasMediaTab,
|
|
hasSubMenusTab,
|
|
hasTermsTab,
|
|
hasNotificationsTab,
|
|
hasSpecNewsTab,
|
|
hasNazarTab,
|
|
hasNewsFileTab,
|
|
defaultPageType,
|
|
hasManagerInfo,
|
|
managerName,
|
|
managerDescription,
|
|
} = req.body;
|
|
|
|
///////////// permissions
|
|
if (req.user.specialPermissions.length && _.isEmpty(parent)) {
|
|
return res.status(403).json({
|
|
message: `شما مجاز به اضافه کردن دسته بندی اصلی نیستید`,
|
|
});
|
|
}
|
|
|
|
// if (req.user.specialPermissions.length && !_.isEmpty(parent) && !req.user.permissions.includes('categories-add')){
|
|
// return res.status(403).json(`شما اجازه اضافه کردن یک دسته بندی جدید را ندارید`);
|
|
// }
|
|
|
|
/** set portals */
|
|
modelType =
|
|
req.user.portals.join() === portal.join()
|
|
? modelType
|
|
: req.user.portals[0];
|
|
|
|
/** only one category can be in to the section one and two */
|
|
// if (showInSectionOne === true) {
|
|
// await _checkOtherSection('one');
|
|
// }
|
|
//
|
|
// if (showInSectionTwo === true) {
|
|
// await _checkOtherSection('two');
|
|
// }
|
|
|
|
const catData = {
|
|
title: title.trim().replace(titleFilterRegex, "-"),
|
|
priority: priority,
|
|
parent: parent || null,
|
|
// showInMenu: showInMenu,
|
|
navIndex: navIndex,
|
|
siteMap: siteMap,
|
|
special: special,
|
|
showInFooter,
|
|
url,
|
|
// showInSectionOne,
|
|
// showInSectionTwo,
|
|
// showInSectionThree,
|
|
pageContent,
|
|
modelType,
|
|
news,
|
|
child,
|
|
hasNewsTab,
|
|
hasContentTab,
|
|
hasMediaTab,
|
|
hasSubMenusTab,
|
|
hasTermsTab,
|
|
hasNotificationsTab,
|
|
hasSpecNewsTab,
|
|
hasNazarTab,
|
|
hasNewsFileTab,
|
|
defaultPageType,
|
|
hasManagerInfo,
|
|
managerName,
|
|
managerDescription,
|
|
_creator: req.user._id,
|
|
_updatedBy: req.user._id,
|
|
};
|
|
|
|
let getParent;
|
|
|
|
if (parent) {
|
|
/**
|
|
* check parent exist or not
|
|
*/
|
|
getParent = await Category.findById(parent);
|
|
// .populate({
|
|
// path: 'parent',
|
|
// populate: {
|
|
// path: 'parent',
|
|
// model: 'Category'
|
|
// }
|
|
// });
|
|
|
|
/**
|
|
* if not found show error
|
|
*/
|
|
if (!getParent) return res404(res, `دسته بندی پدر پیدا نشد`);
|
|
|
|
////// start permissions
|
|
/** check special permission */
|
|
if (
|
|
req.user.specialPermissions.length &&
|
|
(await _checkSpecPermission(req, getParent))
|
|
) {
|
|
return res.status(403).json({
|
|
message: `شما اجازه اضافه کردن فرزند جدید برای این دسته بندی را ندارید`,
|
|
});
|
|
}
|
|
|
|
/** check can add child */
|
|
if (!getParent.child)
|
|
return res
|
|
.status(403)
|
|
.json({ message: `این دسته بندی نمی تواند زیرمجموعه داشته باشد` });
|
|
|
|
/** check access portal */
|
|
if (!req.user.portals.includes(getParent.modelType))
|
|
return res.status(403).json({
|
|
message: `شما اجازه انتخاب این دسته بندی را ندارید`,
|
|
});
|
|
|
|
/** check type */
|
|
if (getParent.modelType !== modelType)
|
|
return res500(
|
|
res,
|
|
`شما اجازه استفاده این دسته بندی به عنوان سردسته را ندارید`
|
|
);
|
|
////// end permissions
|
|
|
|
/**
|
|
* add level of new category
|
|
*/
|
|
catData.level = Number(getParent.level) + 1;
|
|
|
|
/** add tree cat */
|
|
// catData.treeCat = await _makeTreeCat(getParent);
|
|
const treeCatClone = JSON.parse(JSON.stringify(getParent.treeCat));
|
|
treeCatClone.push(getParent._id);
|
|
catData.treeCat = treeCatClone;
|
|
catData.rootParent = getParent.rootParent || getParent._id;
|
|
}
|
|
|
|
/**
|
|
* add new category
|
|
*/
|
|
const create = await Category.create(catData);
|
|
/**
|
|
* check added or not
|
|
*/
|
|
if (!create)
|
|
return res500(
|
|
res,
|
|
`مشکلی در ثبت اطلاعات پیش آمده لطفا دوباره تلاش کنید`
|
|
);
|
|
|
|
/**
|
|
* if have parent should added new category in child of parent category
|
|
* and set level for new category
|
|
*/
|
|
if (getParent) {
|
|
/**
|
|
* add new category for parent
|
|
*/
|
|
getParent.childs.push(create._id);
|
|
await getParent.save();
|
|
}
|
|
|
|
if (req.files?.managerCover) {
|
|
const image = req.files.managerCover;
|
|
if (!_sr.supportedImageFormats.includes(image.mimetype.split("/")[1])) {
|
|
return res.status(422).json({
|
|
validation: {
|
|
cover: {
|
|
msg: _sr["fa"].format.image,
|
|
},
|
|
},
|
|
});
|
|
}
|
|
const imageName = `manager_${Date.now()}_${create._id}.${
|
|
image.mimetype.split("/")[1]
|
|
}`;
|
|
try {
|
|
const target = sharp(image.data);
|
|
await target
|
|
.resize(coverNewsWidth, coverNewsHeight, { fit: "cover" })
|
|
.jpeg({ quality: coverQuality })
|
|
.toFile(`./static/uploads/images/category/${imageName}`);
|
|
|
|
/**
|
|
* if exist old pic delete it from file
|
|
*/
|
|
// if (targetNews.cover !== noCover && !targetNews.imported) {
|
|
// let oldPic = `./static${targetNews.cover}`;
|
|
//
|
|
// if (await fs.existsSync(oldPic)) {
|
|
// fs.unlink(oldPic, (err) => {
|
|
// if (err) return res500(res, err?.message);
|
|
// });
|
|
// }
|
|
// }
|
|
|
|
// if (targetNews.thumbCover !== noCover && !targetNews.imported) {
|
|
// let oldPic = `./static${targetNews.thumbCover}`;
|
|
//
|
|
// if (await fs.existsSync(oldPic)) {
|
|
// fs.unlink(oldPic, (err) => {
|
|
// if (err) return res500(res, err?.message);
|
|
// });
|
|
// }
|
|
// }
|
|
|
|
create.managerCover = imageName;
|
|
await create.save();
|
|
} catch (e) {
|
|
return res500(res, e?.message);
|
|
}
|
|
}
|
|
|
|
if (req.files?.icon) {
|
|
const image = req.files.icon;
|
|
if (!_sr.supportedImageFormats.includes(image.mimetype.split("/")[1])) {
|
|
return res.status(422).json({
|
|
validation: {
|
|
cover: {
|
|
msg: _sr["fa"].format.image,
|
|
},
|
|
},
|
|
});
|
|
}
|
|
const ext = extname(image.name)
|
|
const imageName = `shafafiat_icon_${Date.now()}_${targetCategory._id}.${ext}`;
|
|
try {
|
|
await image.mv(
|
|
`${process.cwd()}/static/uploads/images/category/shafafiat/${imageName}`
|
|
);
|
|
|
|
|
|
/**
|
|
* if exist old pic delete it from file
|
|
*/
|
|
// if (targetNews.cover !== noCover && !targetNews.imported) {
|
|
// let oldPic = `./static${targetNews.cover}`;
|
|
//
|
|
// if (await fs.existsSync(oldPic)) {
|
|
// fs.unlink(oldPic, (err) => {
|
|
// if (err) return res500(res, err?.message);
|
|
// });
|
|
// }
|
|
// }
|
|
|
|
// if (targetNews.thumbCover !== noCover && !targetNews.imported) {
|
|
// let oldPic = `./static${targetNews.thumbCover}`;
|
|
//
|
|
// if (await fs.existsSync(oldPic)) {
|
|
// fs.unlink(oldPic, (err) => {
|
|
// if (err) return res500(res, err?.message);
|
|
// });
|
|
// }
|
|
// }
|
|
|
|
create.icon = imageName;
|
|
await create.save();
|
|
} catch (e) {
|
|
return res500(res, e?.message);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* show result
|
|
*/
|
|
return res.json(create);
|
|
} catch (error) {
|
|
console.log(error);
|
|
/**
|
|
* if we got unkown error show to client
|
|
*/
|
|
res500(res, error.message);
|
|
}
|
|
},
|
|
];
|
|
|
|
module.exports.updateCategory = [
|
|
[
|
|
body("title").notEmpty().withMessage(_sr["fa"].required.title),
|
|
|
|
// body('parent')
|
|
// .optional().isString().withMessage(`parent ${_sr['fa'].optional.string}`),
|
|
|
|
// body('showInMenu')
|
|
// .isBoolean().withMessage(_sr['fa'].format.boolean),
|
|
|
|
body("navIndex").isNumeric().withMessage(_sr["fa"].format.number),
|
|
|
|
body("priority").isNumeric().withMessage(_sr["fa"].format.number),
|
|
|
|
// body('showInSectionOne')
|
|
// .optional().isBoolean().withMessage(_sr['fa'].format.boolean),
|
|
|
|
// body('showInSectionTwo')
|
|
// .optional().isBoolean().withMessage(_sr['fa'].format.boolean),
|
|
|
|
// body('showInSectionThree')
|
|
// .optional().isBoolean().withMessage(_sr['fa'].format.boolean),
|
|
|
|
body("siteMap").isBoolean().withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("special").isBoolean().withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("showInFooter")
|
|
.isNumeric()
|
|
.withMessage(_sr["fa"].format.number)
|
|
.bail()
|
|
.isIn([0, 1, 2, 3])
|
|
.withMessage(`از بین اعداد 1و2و3 یک عدد ارسال کنید`),
|
|
|
|
body("url")
|
|
.optional()
|
|
.isString()
|
|
.withMessage(`url ${_sr["fa"].optional.string}`),
|
|
|
|
body("pageContent")
|
|
.optional()
|
|
.isString()
|
|
.withMessage(`pageContent ${_sr["fa"].optional.string}`),
|
|
|
|
body("news").optional().isBoolean().withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("child").optional().isBoolean().withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasNewsTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasContentTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasMediaTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasSubMenusTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasTermsTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasNotificationsTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasSpecNewsTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasNazarTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
|
|
body("hasNewsFileTab")
|
|
.optional()
|
|
.isBoolean()
|
|
.withMessage(_sr["fa"].format.boolean),
|
|
],
|
|
checkValidations(validationResult),
|
|
async (req, res) => {
|
|
try {
|
|
/**
|
|
* get data from input
|
|
*/
|
|
let {
|
|
title,
|
|
parent,
|
|
// showInMenu,
|
|
navIndex,
|
|
priority,
|
|
// showInSectionOne,
|
|
// showInSectionTwo,
|
|
// showInSectionThree,
|
|
siteMap,
|
|
special,
|
|
showInFooter,
|
|
url,
|
|
pageContent,
|
|
news,
|
|
child,
|
|
hasNewsTab,
|
|
hasContentTab,
|
|
hasMediaTab,
|
|
hasSubMenusTab,
|
|
hasTermsTab,
|
|
hasNotificationsTab,
|
|
hasSpecNewsTab,
|
|
hasNazarTab,
|
|
hasNewsFileTab,
|
|
defaultPageType,
|
|
hasManagerInfo,
|
|
managerName,
|
|
managerDescription,
|
|
} = req.body;
|
|
|
|
/**
|
|
* get id
|
|
*/
|
|
const catId = req.params.id;
|
|
|
|
////////// permissions
|
|
// if (req.user.specialPermissions.length && !req.user.permissions.includes('categories-update')){
|
|
// return res.status(403).json(`شما اجازه بروزرسانی این دسته بندی را ندارید`);
|
|
// }
|
|
|
|
/**
|
|
* check category exist or not
|
|
*/
|
|
const targetCategory = await Category.findOne({
|
|
_id: catId,
|
|
});
|
|
|
|
if (!targetCategory) return res404(res, `دسته بندی مورد نظر پیدا نشد`);
|
|
|
|
/** check special permission */
|
|
if (
|
|
req.user.specialPermissions.length &&
|
|
(await _checkSpecPermission(req, targetCategory))
|
|
) {
|
|
return res.status(403).json({
|
|
message: `شما اجازه بروزرسانی این دسته بندی را ندارید`,
|
|
});
|
|
}
|
|
|
|
/** check access portal */
|
|
if (!req.user.portals.includes(targetCategory.modelType)) {
|
|
return res.status(403).json({
|
|
message: `شما اجازه آپدیت این دسته بندی را ندارید`,
|
|
});
|
|
}
|
|
|
|
/** only one category can be in to the section one and two */
|
|
// if (showInSectionOne === 'true') {
|
|
// targetCategory.showInSectionOne = await _checkOtherSection('one');
|
|
// }
|
|
|
|
// if (showInSectionTwo === 'true') {
|
|
// targetCategory.showInSectionTwo = await _checkOtherSection('two');
|
|
// }
|
|
|
|
if (targetCategory.title !== title) {
|
|
const checkDuppTitle = await Category.findOne({
|
|
title: title,
|
|
});
|
|
|
|
if (checkDuppTitle) {
|
|
return res
|
|
.status(422)
|
|
.json({
|
|
validation: { title: { msg: _sr["fa"].duplicated.title } },
|
|
});
|
|
}
|
|
}
|
|
|
|
// if(parent != null && targetCategory.parent != null && parent != targetCategory.parent) {
|
|
|
|
// /** check have news or not */
|
|
// var checkHaveNews = await News.find({allCat : [targetCategory._id]});
|
|
|
|
// if(checkHaveNews.length){
|
|
// return res.status(403).json({message :`این دسته بندی دارای اخبار می باشد و شما نمیتوانید دسته بندی والد آن را تغییر دهید لطفا ابتدا اخبار را حذف کرده سپس این کار را انجام دهید`});
|
|
// }
|
|
|
|
// /**
|
|
// * check new parent
|
|
// */
|
|
// var newParentCategory = await Category.findOne({_id : parent});
|
|
|
|
// if(!newParentCategory){
|
|
// return res404(res,`دسته بندی انتخاب شده پیدا نشد`);
|
|
// };
|
|
|
|
// if(newParentCategory.treeCat.includes(targetCategory._id)){
|
|
// return res.status(422).json({validation : {parent : {msg : ``}}})
|
|
// }
|
|
|
|
// /**
|
|
// * get category parent
|
|
// */
|
|
// if(targetCategory.parent){
|
|
// var parentCategory = await Category.findOne({_id : targetCategory.parent});
|
|
|
|
// if(parentCategory){
|
|
// /**
|
|
// * delete catId from old category
|
|
// */
|
|
// const index = parentCategory.childs.indexOf(targetCategory._id);
|
|
// if (index > -1) {
|
|
// parentCategory.childs.splice(index, 1);
|
|
|
|
// await parentCategory.save();
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// if(!newParentCategory.child){
|
|
// return res.status(403).json({message :`این دسته بندی اجازه داشتن زیرمجموعه ندارد`});
|
|
// }
|
|
|
|
// /** check access portal */
|
|
// if(!req.user.portals.includes(newParentCategory.modelType)){
|
|
// return res.status(403).json({message :`شما اجازه انتخاب این دسته بندی را ندارید`});
|
|
// }
|
|
|
|
// /** check type */
|
|
// if(newParentCategory.modelType != modelType){
|
|
// return res.status(403).json({message :`شما اجازه استفاده این دسته بندی به عنوان سردسته را ندارید`});
|
|
// }
|
|
|
|
// /**
|
|
// * add catId for new parnet
|
|
// */
|
|
// newParentCategory.childs.push(targetCategory._id);
|
|
// await newParentCategory.save();
|
|
|
|
// /**
|
|
// * update level
|
|
// */
|
|
// targetCategory.level = newParentCategory.level + 1;
|
|
// }
|
|
|
|
/**
|
|
* make update object
|
|
*/
|
|
targetCategory.title = title.trim().replace(titleFilterRegex, "-");
|
|
// targetCategory.showInMenu = showInMenu;
|
|
targetCategory.navIndex = navIndex;
|
|
targetCategory.priority = priority;
|
|
// targetCategory.showInSectionOne = showInSectionOne;
|
|
// targetCategory.showInSectionTwo = showInSectionTwo;
|
|
// targetCategory.showInSectionThree = showInSectionThree;
|
|
targetCategory.siteMap = siteMap;
|
|
targetCategory.special = special;
|
|
targetCategory._creator = req.user._id;
|
|
targetCategory._updatedBy = req.user._id;
|
|
targetCategory.showInFooter = showInFooter;
|
|
targetCategory.pageContent = pageContent;
|
|
targetCategory.child = child;
|
|
targetCategory.url = url;
|
|
targetCategory.news = news;
|
|
targetCategory.hasNewsTab = hasNewsTab;
|
|
targetCategory.hasContentTab = hasContentTab;
|
|
targetCategory.hasMediaTab = hasMediaTab;
|
|
targetCategory.hasSubMenusTab = hasSubMenusTab;
|
|
targetCategory.hasTermsTab = hasTermsTab;
|
|
targetCategory.hasNotificationsTab = hasNotificationsTab;
|
|
targetCategory.hasSpecNewsTab = hasSpecNewsTab;
|
|
targetCategory.hasNazarTab = hasNazarTab;
|
|
targetCategory.hasNewsFileTab = hasNewsFileTab;
|
|
targetCategory.defaultPageType = defaultPageType;
|
|
|
|
targetCategory.hasManagerInfo = hasManagerInfo;
|
|
targetCategory.managerName = managerName;
|
|
targetCategory.managerDescription = managerDescription;
|
|
|
|
if (req.files?.managerCover) {
|
|
const image = req.files.managerCover;
|
|
if (!_sr.supportedImageFormats.includes(image.mimetype.split("/")[1])) {
|
|
return res.status(422).json({
|
|
validation: {
|
|
cover: {
|
|
msg: _sr["fa"].format.image,
|
|
},
|
|
},
|
|
});
|
|
}
|
|
const imageName = `manager_${Date.now()}_${targetCategory._id}.${
|
|
image.mimetype.split("/")[1]
|
|
}`;
|
|
try {
|
|
const target = sharp(image.data);
|
|
await target
|
|
.resize(coverNewsWidth, coverNewsHeight, { fit: "cover" })
|
|
.jpeg({ quality: coverQuality })
|
|
.toFile(`./static/uploads/images/category/${imageName}`);
|
|
|
|
/**
|
|
* if exist old pic delete it from file
|
|
*/
|
|
if (targetCategory.managerCover !== noCover) {
|
|
let oldPic = `./static${targetCategory.managerCover}`;
|
|
|
|
if (await fs.existsSync(oldPic)) {
|
|
fs.unlink(oldPic, (err) => {
|
|
if (err) return res500(res, err?.message);
|
|
});
|
|
}
|
|
}
|
|
|
|
targetCategory.managerCover = imageName;
|
|
} catch (e) {
|
|
return res500(res, e?.message);
|
|
}
|
|
}
|
|
|
|
if (req.files?.icon) {
|
|
const image = req.files.icon;
|
|
console.log(image);
|
|
if (!_sr.supportedImageFormats.includes(image.mimetype.split("/")[1])) {
|
|
return res.status(422).json({
|
|
validation: {
|
|
cover: {
|
|
msg: _sr["fa"].format.image,
|
|
},
|
|
},
|
|
});
|
|
}
|
|
const ext = extname(image.name)
|
|
const imageName = `shafafiat_icon_${Date.now()}_${targetCategory._id}.${ext}`;
|
|
try {
|
|
await image.mv(
|
|
`${process.cwd()}/static/uploads/images/category/shafafiat/${imageName}`
|
|
);
|
|
// const target = sharp(image.data)
|
|
// await target
|
|
// .resize(coverNewsWidth, coverNewsHeight, {fit: 'cover'})
|
|
// .jpeg({quality: coverQuality})
|
|
// .toFile(`./static/uploads/images/category/shafafiat/${imageName}`);
|
|
|
|
/**
|
|
* if exist old pic delete it from file
|
|
*/
|
|
if (targetCategory.icon !== noCover) {
|
|
let oldPic = `./static${targetCategory.icon}`;
|
|
|
|
if (await fs.existsSync(oldPic)) {
|
|
fs.unlink(oldPic, (err) => {
|
|
if (err) return res500(res, err?.message);
|
|
});
|
|
}
|
|
}
|
|
|
|
targetCategory.icon = imageName;
|
|
console.log(targetCategory);
|
|
} catch (e) {
|
|
return res500(res, e?.message);
|
|
}
|
|
}
|
|
|
|
await targetCategory.save();
|
|
|
|
/**
|
|
* show result
|
|
*/
|
|
return res.json(targetCategory);
|
|
} catch (error) {
|
|
return res500(res, error.message);
|
|
}
|
|
},
|
|
];
|
|
|
|
module.exports.deletOneCategory = [
|
|
async (req, res) => {
|
|
try {
|
|
const catId = req.params.id;
|
|
|
|
/**
|
|
* check category
|
|
*/
|
|
const targetCategory = await Category.findOne({
|
|
_id: catId,
|
|
});
|
|
|
|
if (!targetCategory) {
|
|
return res404(res, `دسته بندی مورد نظر پیدا نشد`);
|
|
}
|
|
|
|
/** check special permission */
|
|
if (
|
|
req.user.specialPermissions.length &&
|
|
(await _checkSpecPermission(req, targetCategory))
|
|
) {
|
|
return res.status(403).json({
|
|
message: `شما اجازه حذف این دسته بندی را ندارید`,
|
|
});
|
|
}
|
|
|
|
/** check access portal */
|
|
if (!req.user.portals.includes(targetCategory.modelType)) {
|
|
return res.status(403).json({
|
|
message: `شما اجازه حذف این دسته بندی را ندارید`,
|
|
});
|
|
}
|
|
|
|
/** check special permissions */
|
|
if (
|
|
req.user.specialPermissions.includes(targetCategory._id) &&
|
|
!targetCategory.parent
|
|
) {
|
|
return res.status(403).json({
|
|
message: `شما اجازه حذف این دسته بندی را ندارید`,
|
|
});
|
|
}
|
|
|
|
/** check owner ship */
|
|
if (
|
|
req.user.specialPermissions.includes(targetCategory._id) &&
|
|
targetCategory.parent !== req.user._id
|
|
) {
|
|
return res.status(403).json({
|
|
message: `شما اجازه حذف این دسته بندی را ندارید`,
|
|
});
|
|
}
|
|
|
|
const checkHaveNews = await News.find({
|
|
allCat: [targetCategory._id],
|
|
});
|
|
|
|
if (checkHaveNews.length) {
|
|
return res.status(403).json({
|
|
message: `دسته بندی شما دارای خبر می باشد و قبل از حذف آن باید اخبار مربوط به این دسته بندی را حذف کنید`,
|
|
});
|
|
}
|
|
|
|
if (targetCategory.childs.length) {
|
|
return res.status(403).json({
|
|
message: `دسته بندی مورد نظر دارای زیرمجموعه می باشد ابتدا زیرمجوعه ها را حذف کنید`,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* get category parent
|
|
*/
|
|
if (targetCategory.parent) {
|
|
const categoryParent = await Category.findOne({
|
|
_id: targetCategory.parent,
|
|
});
|
|
|
|
if (categoryParent) {
|
|
/**
|
|
* delete catId from category parent
|
|
*/
|
|
const index = categoryParent.childs.indexOf(targetCategory._id);
|
|
if (index > -1) {
|
|
categoryParent.childs.splice(index, 1);
|
|
|
|
await categoryParent.save();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* delete category
|
|
*/
|
|
targetCategory.delete();
|
|
|
|
/**
|
|
* show result
|
|
*/
|
|
return res.json(targetCategory);
|
|
} catch (error) {
|
|
/**
|
|
* if we got unkown error show to client
|
|
*/
|
|
res500(res, error);
|
|
}
|
|
},
|
|
];
|
|
|
|
module.exports.deleteAllCategory = [
|
|
async (req, res) => {
|
|
try {
|
|
} catch (error) {
|
|
/**
|
|
* if we got unkown error show to client
|
|
*/
|
|
res500(res, error);
|
|
}
|
|
},
|
|
];
|
|
|
|
module.exports.getOneCategory = [
|
|
async (req, res) => {
|
|
try {
|
|
const catId = req.params.id;
|
|
|
|
/**
|
|
* get category
|
|
*/
|
|
const targetCategory = await Category.findOne({
|
|
_id: catId,
|
|
});
|
|
|
|
/**
|
|
* if not exist
|
|
*/
|
|
if (!targetCategory) {
|
|
return res404(res, `دسته بندی مورد نظر پیدا نشد`);
|
|
}
|
|
|
|
/** check access portal */
|
|
if (!req.user.portals.includes(targetCategory.modelType)) {
|
|
return res.status(403).json({
|
|
message: `شما اجازه دسترسی به اطلاعات این دسته بندی را ندارید`,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* show result
|
|
*/
|
|
return res.json(targetCategory);
|
|
} catch (error) {
|
|
/**
|
|
* if we got unkown error show to client
|
|
*/
|
|
res500(res, error);
|
|
}
|
|
},
|
|
];
|
|
|
|
module.exports.getAll = [
|
|
async (req, res) => {
|
|
try {
|
|
const findQuery = {};
|
|
let populate = {};
|
|
|
|
if (req.user.specialPermissions.length) {
|
|
findQuery._id = { $in: req.user.specialPermissions };
|
|
} else {
|
|
findQuery.parent = null;
|
|
// populate = {
|
|
// path: 'childs',
|
|
// populate: {
|
|
// path: 'childs'
|
|
// }
|
|
// };
|
|
}
|
|
|
|
if (req.user.portals.join() !== portal.join()) {
|
|
findQuery.modelType = req.user.portals[0];
|
|
}
|
|
|
|
/**
|
|
* get all category
|
|
*/
|
|
const getAll = await Category.find(findQuery).populate("").sort({
|
|
navIndex: 1,
|
|
});
|
|
|
|
/**
|
|
* این قسمت ابجکت های تکراری را از بین میبره
|
|
*/
|
|
// if (req.user.specialPermissions.length) {
|
|
// /** جدا کردن دسته بندی های اصلی */
|
|
// const parents = getAll.filter((item) => !item.parent);
|
|
// /** جدا کردن دسته بندی های غیر اصلی */
|
|
// const nonParents = getAll.filter((item) => item.parent);
|
|
//
|
|
// /** با یک لوپ تو در تو اگر دسته بندی غیر اصلی در فرزندان دسته بندی اصلی وجود داشت حذف میشه */
|
|
// for (let i = 0; i < nonParents.length; i++) {
|
|
// for (let j = 0; j < parents.length; j++) {
|
|
// if (nonParents[i].treeCat.includes(parents[j]._id)) {
|
|
// getAll.splice(getAll.findIndex(item => item._id === nonParents[i]._id), 1);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
/**
|
|
* show result
|
|
*/
|
|
return res.json(getAll);
|
|
} catch (error) {
|
|
return res500(res, error.message);
|
|
}
|
|
},
|
|
];
|
|
|
|
module.exports.search = [
|
|
async (req, res) => {
|
|
try {
|
|
const term = req.body?.term?.toString().trim() || "";
|
|
|
|
/**
|
|
* search
|
|
*/
|
|
const search = await Category.find({
|
|
title: {
|
|
$regex: ".*" + term + ".*",
|
|
$options: "i",
|
|
},
|
|
modelType: "normal",
|
|
type: "category",
|
|
});
|
|
|
|
/**
|
|
* show result
|
|
*/
|
|
return res.json(search);
|
|
} catch (error) {
|
|
return res500(res, error.message);
|
|
}
|
|
},
|
|
];
|
|
|
|
module.exports.permissions = [
|
|
async (req, res) => {
|
|
try {
|
|
const type = req.query.type;
|
|
|
|
const findQuery = type
|
|
? {
|
|
modelType: type,
|
|
}
|
|
: {};
|
|
|
|
const categories = await Category.find(findQuery)
|
|
.populate("treeCat")
|
|
.sort({ navIndex: 1 })
|
|
.lean();
|
|
|
|
let changeTitles = await _customTitle(categories);
|
|
|
|
let sortedCats = await _sortedCategory(changeTitles);
|
|
|
|
return res.json(sortedCats);
|
|
} catch (error) {
|
|
res500(res, error?.message);
|
|
}
|
|
},
|
|
];
|
|
|
|
module.exports.getParent = [
|
|
async (req, res) => {
|
|
try {
|
|
const findQuery = {};
|
|
|
|
const type = req.query.type;
|
|
|
|
// findQuery.parent = null;
|
|
|
|
if (req.user.specialPermissions.length) {
|
|
findQuery.$or = [
|
|
{
|
|
_id: {
|
|
$in: req.user.specialPermissions,
|
|
},
|
|
},
|
|
];
|
|
}
|
|
|
|
if (req.user.portals.length) {
|
|
findQuery.modelType = {
|
|
$in: req.user.portals,
|
|
};
|
|
}
|
|
|
|
if (type && type === "news") {
|
|
findQuery.news = true;
|
|
}
|
|
|
|
if (type && type === "child") {
|
|
findQuery.child = true;
|
|
}
|
|
|
|
/**
|
|
* get all category
|
|
*/
|
|
const getAll = await Category.find(findQuery)
|
|
.populate("parent")
|
|
.populate("treeCat")
|
|
.sort({ navIndex: 1 });
|
|
|
|
let changeTitles = await _customTitle(getAll);
|
|
|
|
let sortedCats = await _sortedCategory(changeTitles);
|
|
|
|
/**
|
|
* show result
|
|
*/
|
|
return res.json(sortedCats);
|
|
} catch (error) {
|
|
return res500(res, error?.message);
|
|
}
|
|
},
|
|
];
|
|
|
|
//////////// add attachment file to category
|
|
module.exports.addTermsFileToCategory = [
|
|
[body("termsTitle").notEmpty().withMessage(_sr["fa"].required.title)],
|
|
checkValidations(validationResult),
|
|
(req, res) => {
|
|
if (!req.files?.file)
|
|
return res
|
|
.status(422)
|
|
.json({ validation: { file: { msg: _sr["fa"].required.file } } });
|
|
if (req.files?.file.mimetype.split("/")[1] !== "pdf")
|
|
return res
|
|
.status(422)
|
|
.json({ validation: { file: { msg: "فقط فرمت PDF قابل قبول است" } } });
|
|
|
|
const data = { title: req.body.termsTitle };
|
|
const file = req.files.file;
|
|
const fileName =
|
|
req.body.termsTitle.replace(titleFilterRegex, "-") +
|
|
"_" +
|
|
Date.now() +
|
|
".pdf";
|
|
file.mv(`./static/uploads/files/terms/${fileName}`);
|
|
data.file = fileName;
|
|
|
|
Category.findById(req.params.categoryId, (err, category) => {
|
|
if (err || !category) return res404(res, err);
|
|
category.terms.push(data);
|
|
category.save((err) => {
|
|
if (err) return res500(res, err);
|
|
else return res.json({ message: _sr["fa"].response.success_save });
|
|
});
|
|
});
|
|
},
|
|
];
|
|
|
|
module.exports.removeTermsFileFromCategory = [
|
|
(req, res) => {
|
|
Category.findOne({ "terms._id": req.params.fileId }, (err, category) => {
|
|
if (err || !category) return res404(res, err);
|
|
const file = category.terms.id(req.params.fileId);
|
|
if (!file) return res404(res, "not found");
|
|
file.remove();
|
|
fs.unlink(`./static/${file.file}`, (err) => {
|
|
if (err) console.log(err);
|
|
});
|
|
category.save((err) => {
|
|
if (err) return res500(res, err);
|
|
else return res.json({ message: _sr["fa"].response.success_remove });
|
|
});
|
|
});
|
|
},
|
|
];
|
|
|
|
/////////////////////////////////////////////////////////////////////// public
|
|
module.exports.getMenu = [
|
|
async (req, res) => {
|
|
try {
|
|
const portal = req.query?.portal || "ostandari";
|
|
|
|
const findQuery = {
|
|
parent: null,
|
|
// showInMenu: true,
|
|
modelType: portal,
|
|
};
|
|
let result = {};
|
|
/**
|
|
* get all category
|
|
*/
|
|
const getAll = await Category.find(findQuery)
|
|
.populate("treeCat")
|
|
.sort({
|
|
navIndex: 1,
|
|
// created_at: 1
|
|
})
|
|
.select("title childs navIndex url modelType treeCat defaultPageType");
|
|
|
|
/// get all page content
|
|
const getContent = await Content.find({ showInMenu: true });
|
|
|
|
result.categories = getAll;
|
|
result.staticContents = !!getContent.length;
|
|
|
|
/**
|
|
* show result
|
|
*/
|
|
return res.json(result);
|
|
} catch (error) {
|
|
return res500(res, error.message);
|
|
}
|
|
},
|
|
];
|