Merge branch 'main' into transaction
# Conflicts: # config/.env # package-lock.json # package.json # setup/routerEndpoints.js
This commit is contained in:
@@ -1,14 +1,19 @@
|
||||
const mongoose = require('mongoose')
|
||||
const ObjectID = mongoose.Schema.Types.ObjectId
|
||||
const AutoIncrement = require('mongoose-sequence')(mongoose)
|
||||
const { getMultipleSignedUrls, getSignedUrl } = require('../file/fileService')
|
||||
|
||||
const belongingSchema = new mongoose.Schema(
|
||||
{
|
||||
belongingCode: {
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
},
|
||||
belongingCode: {
|
||||
type: Number,
|
||||
unique: true,
|
||||
},
|
||||
category: {
|
||||
type: ObjectID,
|
||||
ref: 'Category',
|
||||
@@ -23,29 +28,33 @@ const belongingSchema = new mongoose.Schema(
|
||||
type: {
|
||||
type: String,
|
||||
enum: ['Point'], // GeoJSON type
|
||||
required: true,
|
||||
required: false,
|
||||
},
|
||||
coordinates: {
|
||||
type: [Number], // Array of numbers: [longitude, latitude]
|
||||
required: true,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
documentNames: [String],
|
||||
documentUrls: [String],
|
||||
imageNames: [String],
|
||||
imageUrls: [String],
|
||||
mainImageNames: [String],
|
||||
mainImageUrl: String,
|
||||
mainImageName: String,
|
||||
numId: {
|
||||
type: Number,
|
||||
unique: true,
|
||||
},
|
||||
tags: [String],
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
select: false,
|
||||
},
|
||||
features: [
|
||||
{
|
||||
definition: {
|
||||
type: ObjectID,
|
||||
ref: 'Feature',
|
||||
required: true,
|
||||
},
|
||||
value: mongoose.Schema.Types.Mixed,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
toJSON: { virtuals: true },
|
||||
@@ -54,7 +63,19 @@ const belongingSchema = new mongoose.Schema(
|
||||
}
|
||||
)
|
||||
|
||||
belongingSchema.plugin(AutoIncrement, { inc_field: 'numId' })
|
||||
belongingSchema.plugin(AutoIncrement, { inc_field: 'belongingCode' })
|
||||
|
||||
belongingSchema.methods.getDocumentsSignedUrls = function () {
|
||||
return getMultipleSignedUrls(this.documentNames, 'belonging-documents')
|
||||
}
|
||||
|
||||
belongingSchema.methods.getImagesSignedUrls = function () {
|
||||
return getMultipleSignedUrls(this.imageNames, 'belonging-images')
|
||||
}
|
||||
|
||||
belongingSchema.methods.getMainImagedSignedUrl = function () {
|
||||
return getMultipleSignedUrls(this.mainImageNames, 'belonging-images')
|
||||
}
|
||||
|
||||
belongingSchema.index({ location: '2dsphere' }) // Enable geospatial queries
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ router.post('/admin/index-all', perm.requires('indexbelongings', belongingContro
|
||||
|
||||
router.get('/admin/get-one/:belongingId', perm.requires('getabelonging'), belongingController.getBelonging)
|
||||
|
||||
router.patch('/admin/update/:belongingId', perm.requires('updateabelonging'), belongingController.updateBelonging)
|
||||
router.put('/admin/update/:belongingId', perm.requires('updateabelonging'), belongingController.updateBelonging)
|
||||
|
||||
router.delete('/admin/delete/:belongingId', perm.requires('deleteabelonging'), belongingController.deleteBelonging)
|
||||
|
||||
|
||||
@@ -4,20 +4,32 @@ const { client } = require('../../setup/typesense')
|
||||
const TsApiFeatures = require("../../utils/TsApiFeatures");
|
||||
|
||||
const getAllBelongings = async () => {
|
||||
return Belonging.find({}, null, null)
|
||||
return Belonging.find({}, null, null).populate('category')
|
||||
}
|
||||
|
||||
const createBelonging = async (data) => {
|
||||
console.log(data)
|
||||
return Belonging.create(data, null)
|
||||
}
|
||||
|
||||
const getBelonging = async (belongingId) => {
|
||||
const belonging = await Belonging.findById(belongingId, null, null)
|
||||
let belonging = await Belonging.findById(belongingId, null, null)
|
||||
|
||||
if (!belonging) {
|
||||
throw new AppError('NoBelongingFound', 404, {})
|
||||
}
|
||||
|
||||
const documentUrls = await belonging.getDocumentsSignedUrls()
|
||||
const imageUrls = await belonging.getImagesSignedUrls()
|
||||
const mainImageUrls = await belonging.getMainImagedSignedUrl()
|
||||
|
||||
belonging = JSON.parse(JSON.stringify(belonging))
|
||||
|
||||
belonging.signedDocumentUrls = documentUrls
|
||||
belonging.signedImageUrls = imageUrls
|
||||
belonging.signedMainImageUrls = mainImageUrls
|
||||
|
||||
|
||||
return belonging
|
||||
}
|
||||
|
||||
@@ -120,4 +132,4 @@ const getTypeSenseSchema = () => {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {indexAllBelongings, getBelonging, getAllBelongings, createBelonging, deleteBelonging, searchBelongings}
|
||||
module.exports = {updateBelonging, indexAllBelongings, getBelonging, getAllBelongings, createBelonging, deleteBelonging, searchBelongings}
|
||||
@@ -12,10 +12,6 @@ const categorySchema = new mongoose.Schema(
|
||||
required: true,
|
||||
unique: true,
|
||||
},
|
||||
parentId: {
|
||||
type: ObjectID,
|
||||
ref: 'Category',
|
||||
},
|
||||
},
|
||||
{
|
||||
toJSON: { virtuals: true },
|
||||
@@ -24,5 +20,11 @@ const categorySchema = new mongoose.Schema(
|
||||
}
|
||||
)
|
||||
|
||||
categorySchema.virtual('features', {
|
||||
ref: 'Feature',
|
||||
localField: '_id',
|
||||
foreignField: 'category',
|
||||
})
|
||||
|
||||
const Category = mongoose.model('Category', categorySchema)
|
||||
module.exports = Category
|
||||
|
||||
@@ -1,67 +1,12 @@
|
||||
const Category = require('./categoryModel')
|
||||
const AppError = require('../../globalErrorHandler/AppError')
|
||||
|
||||
module.exports.getCategoryTree = async () => {
|
||||
const nodes = await Category.find({})
|
||||
let tree = []
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
if (!nodes[i].parentId) {
|
||||
const label = nodes[i].nativeName
|
||||
const children = []
|
||||
const key = nodes[i]._id.toString()
|
||||
const href = '/categories/admin/update/' + nodes[i]._id
|
||||
const a_attr = { href }
|
||||
const root = { label, children, key, a_attr }
|
||||
tree.push(root)
|
||||
}
|
||||
}
|
||||
|
||||
tree = recursiveFunction(tree, nodes)
|
||||
return tree
|
||||
}
|
||||
|
||||
const recursiveFunction = (tree, categories) => {
|
||||
if (tree.length > 0) {
|
||||
for (let i = 0; i < tree.length; i++) {
|
||||
let subTree = []
|
||||
for (let j = 0; j < categories.length; j++) {
|
||||
if (tree[i].key === categories[j].parentId?.toString()) {
|
||||
const label = categories[j].nativeName.toString()
|
||||
const children = []
|
||||
const key = categories[j]._id.toString()
|
||||
const href = '/categories/admin/update/' + categories[j]._id
|
||||
const a_attr = { href }
|
||||
subTree.push({ label, children, key, a_attr })
|
||||
}
|
||||
let index = findCategoryIndex(tree, tree[i].label)
|
||||
tree[index].children = subTree
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < tree.length; i++) {
|
||||
let index = findCategoryIndex(tree, tree[i].label)
|
||||
recursiveFunction(tree[index].children, categories)
|
||||
}
|
||||
}
|
||||
return tree
|
||||
}
|
||||
|
||||
function findCategoryIndex(array, label) {
|
||||
let index
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
if (array[i].label === label) {
|
||||
index = i
|
||||
return index
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.getAllCategories = async () => {
|
||||
return Category.find().populate('parentId')
|
||||
return Category.find().populate('features')
|
||||
}
|
||||
|
||||
module.exports.createCategory = async (data) => {
|
||||
const category = Category.create(data, null)
|
||||
return category
|
||||
return Category.create(data, null)
|
||||
}
|
||||
|
||||
module.exports.getCategory = async (categoryId) => {
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
const catchAsync = require('../../globalErrorHandler/catchAsync')
|
||||
const AppError = require('../../globalErrorHandler/AppError')
|
||||
const featureService = require('./featureService')
|
||||
|
||||
exports.getAllCategoryFeatures = catchAsync(async (req, res, next) => {
|
||||
const features = await featureService.getAllCategoryFeatures()
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
results: features.length,
|
||||
data: features,
|
||||
})
|
||||
})
|
||||
|
||||
exports.getFeatureByCategory = catchAsync(async (req, res, next) => {
|
||||
const features = await featureService.getFeatureByCategory(req.params.categoryId)
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
results: features.length,
|
||||
data: features,
|
||||
})
|
||||
})
|
||||
|
||||
exports.getAllFeatures = catchAsync(async (req, res, next) => {
|
||||
const features = await featureService.getAllFeatures()
|
||||
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
results: features.length,
|
||||
data: features,
|
||||
})
|
||||
})
|
||||
|
||||
exports.createFeature = catchAsync(async (req, res, next) => {
|
||||
const feature = await featureService.createFeatures(req.body)
|
||||
|
||||
res.status(201).json({
|
||||
status: 'success',
|
||||
data: feature,
|
||||
})
|
||||
})
|
||||
|
||||
exports.getFeature = catchAsync(async (req, res, next) => {
|
||||
const feature = await featureService.getFeatures(req.params.id)
|
||||
|
||||
if (!feature) {
|
||||
throw AppError('NoGroupFound', 404, {})
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
data: feature,
|
||||
})
|
||||
})
|
||||
|
||||
exports.updateFeature = catchAsync(async (req, res, next) => {
|
||||
const updatedFeature = await featureService.updateFeatures(req.params.groupId, req.body)
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
data: updatedFeature,
|
||||
})
|
||||
})
|
||||
|
||||
exports.deleteFeature = catchAsync(async (req, res, next) => {
|
||||
await featureService.deleteFeatures(req.params.groupId)
|
||||
|
||||
res.status(204).json({
|
||||
status: 'success',
|
||||
data: null,
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,46 @@
|
||||
const mongoose = require('mongoose')
|
||||
const ObjectID = mongoose.Schema.Types.ObjectId
|
||||
|
||||
const featureSchema = new mongoose.Schema({
|
||||
nativeName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
englishName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
category: {
|
||||
type: ObjectID,
|
||||
ref: 'Category',
|
||||
required: true,
|
||||
},
|
||||
predefinedValues: [String],
|
||||
unit: String,
|
||||
isFilterable: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
featureType: {
|
||||
type: String,
|
||||
enum: ['string', 'boolean', 'number', 'date'],
|
||||
default: 'string',
|
||||
},
|
||||
filterType: {
|
||||
type: String,
|
||||
enum: ['exact', 'range', 'multi', 'bool'],
|
||||
default: 'exact',
|
||||
},
|
||||
tag: String,
|
||||
priority: Number,
|
||||
}, {
|
||||
toJSON: { virtuals: true },
|
||||
toObject: { virtuals: true },
|
||||
timestamps: true,
|
||||
})
|
||||
|
||||
featureSchema.index({ englishName: 1, category: 1 }, { unique: true })
|
||||
|
||||
const Feature = mongoose.model('Feature', featureSchema)
|
||||
|
||||
module.exports = Feature
|
||||
@@ -0,0 +1,25 @@
|
||||
const express = require('express')
|
||||
const router = new express.Router()
|
||||
const FeatureDefinition = require('./featureModel')
|
||||
const featureController = require('./featureController')
|
||||
const perm = require('../../middlewares/permissionMiddleware')
|
||||
const loginCheck = require('../../middlewares/loginCheck')
|
||||
const permission = require('../../middlewares/permissionMiddleware')
|
||||
|
||||
router.use(loginCheck.loginProtect)
|
||||
|
||||
router.get('/admin/get-all-category', perm.requires('getallfeatures'), featureController.getAllCategoryFeatures)
|
||||
|
||||
router.get('/admin/get-by-category/:groupId', perm.requires('getallfeatures'), featureController.getFeatureByCategory)
|
||||
|
||||
router.get('/admin/get-all', perm.requires('getallfeatures'), featureController.getAllFeatures)
|
||||
|
||||
router.post('/admin/create', perm.requires('createfeature'), featureController.createFeature)
|
||||
|
||||
router.get('/admin/get-one/:featureId', perm.requires('getafeature'), featureController.getFeature)
|
||||
|
||||
router.put('/admin/update/:featureId', perm.requires('updateafeature'), featureController.updateFeature)
|
||||
|
||||
router.delete('/admin/delete/:featureId', perm.requires('deleteafeature'), featureController.deleteFeature)
|
||||
|
||||
module.exports = router
|
||||
@@ -0,0 +1,837 @@
|
||||
const Feature = require('./featureModel')
|
||||
const chalk = require('chalk')
|
||||
|
||||
const runSeeder = async () => {
|
||||
const features2 = [
|
||||
{
|
||||
_id: '669d533e90cf9da0fdfabdcb',
|
||||
nativeName: 'مدل پردازنده',
|
||||
englishName: 'lcpu',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
predefinedValues: [
|
||||
'12450H',
|
||||
'13500H',
|
||||
'13620H',
|
||||
'13700H',
|
||||
'13900H',
|
||||
'13500HX',
|
||||
'13500HX',
|
||||
'13650HX',
|
||||
'13700HX',
|
||||
'13900HX',
|
||||
'13950HX',
|
||||
'13980HX',
|
||||
'7735H',
|
||||
'7940H',
|
||||
'7840H',
|
||||
'7745HX',
|
||||
'7845HX',
|
||||
'7940HX',
|
||||
'7945HX',
|
||||
'125U',
|
||||
'135U',
|
||||
'155U',
|
||||
'165U',
|
||||
'125H',
|
||||
'135H',
|
||||
'155H',
|
||||
'165H',
|
||||
'134U',
|
||||
'164U',
|
||||
'185H',
|
||||
'14500HX',
|
||||
'14700HX',
|
||||
'14900HX',
|
||||
'8945H',
|
||||
'8845H',
|
||||
'8840H',
|
||||
'X1E-84-100',
|
||||
'X1E-80-100',
|
||||
'X1E-78-100',
|
||||
'X1P-64-100',
|
||||
],
|
||||
isFilterable: true,
|
||||
filterType: 'exact',
|
||||
tag: 'پردازنده',
|
||||
priority: 50,
|
||||
},
|
||||
{
|
||||
_id: '669d533e90cf9da0fdfabdcc',
|
||||
nativeName: 'برند پردازنده',
|
||||
englishName: 'lcpubrand',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
predefinedValues: ['Intel', 'AMD'],
|
||||
isFilterable: true,
|
||||
filterType: 'exact',
|
||||
tag: 'پردازنده',
|
||||
priority: 30,
|
||||
},
|
||||
{
|
||||
_id: '669d533e90cf9da0fdfabdcd',
|
||||
nativeName: 'برند کارت گرافیک',
|
||||
englishName: 'lgpubrand',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
predefinedValues: ['Nvidia', 'AMD', 'Intel'],
|
||||
isFilterable: true,
|
||||
filterType: 'exact',
|
||||
tag: 'کارت گرافیک',
|
||||
},
|
||||
{
|
||||
_id: '669d533e90cf9da0fdfabdce',
|
||||
nativeName: 'مدل کارت گرافیک',
|
||||
englishName: 'lgpumodel',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
predefinedValues: ['NVIDIA GeForce GTX 4060', 'AMD Radeon RX 7600M XT'],
|
||||
isFilterable: true,
|
||||
filterType: 'exact',
|
||||
tag: 'کارت گرافیک',
|
||||
},
|
||||
{
|
||||
_id: '669d533e90cf9da0fdfabdcf',
|
||||
nativeName: 'رزولوشن صفحه نمایش',
|
||||
englishName: 'ldisres',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
predefinedValues: ['Full HD', '2.5K', '3.2K', '4K'],
|
||||
isFilterable: true,
|
||||
filterType: 'exact',
|
||||
tag: 'کارت گرافیک',
|
||||
},
|
||||
{
|
||||
_id: '669d533e90cf9da0fdfabdd0',
|
||||
nativeName: 'رم',
|
||||
englishName: 'lramcap',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
predefinedValues: [8, 16, 32],
|
||||
unit: 'GB',
|
||||
isFilterable: true,
|
||||
filterType: 'exact',
|
||||
tag: 'رم',
|
||||
},
|
||||
{
|
||||
_id: '669d533e90cf9da0fdfabdd1',
|
||||
nativeName: 'نوع رم',
|
||||
englishName: 'lramtype',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
predefinedValues: ['DDR4', 'DDR5', 'LPDDR5X'],
|
||||
isFilterable: true,
|
||||
filterType: 'exact',
|
||||
tag: 'رم',
|
||||
},
|
||||
{
|
||||
_id: '669d533e90cf9da0fdfabdd2',
|
||||
nativeName: 'فرکانس رم',
|
||||
englishName: 'lramfreq',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
predefinedValues: [3200, 4800, 5200, 6400],
|
||||
unit: 'Mhz',
|
||||
isFilterable: true,
|
||||
filterType: 'exact',
|
||||
tag: 'رم',
|
||||
},
|
||||
{
|
||||
_id: '669d533e90cf9da0fdfabdd3',
|
||||
nativeName: 'حافظه HDD',
|
||||
englishName: 'lhdd',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
predefinedValues: ['دارد', 'ندارد'],
|
||||
isFilterable: false,
|
||||
filterType: 'bool',
|
||||
tag: 'حافظه',
|
||||
},
|
||||
{
|
||||
_id: '669d533e90cf9da0fdfabdd4',
|
||||
nativeName: 'حافظه SSD',
|
||||
englishName: 'lssd',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
predefinedValues: ['دارد', 'ندارد'],
|
||||
isFilterable: false,
|
||||
filterType: 'bool',
|
||||
tag: 'حافظه',
|
||||
},
|
||||
{
|
||||
_id: '669d533e90cf9da0fdfabdd5',
|
||||
nativeName: 'حجم حافظه SSD',
|
||||
englishName: 'lssdcap',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
predefinedValues: [128, 256, 512, 1024, 2048],
|
||||
isFilterable: true,
|
||||
unit: 'GB',
|
||||
filterType: 'exact',
|
||||
tag: 'حافظه',
|
||||
},
|
||||
]
|
||||
|
||||
const features = [
|
||||
{
|
||||
_id: '63839aed70a51325208b0584',
|
||||
fullNativeName: 'ابعاد (میلی متر) مشخصات فیزیکی لپتاپ',
|
||||
nativeName: 'ابعاد (میلی متر)',
|
||||
englishName: 'ldim',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'مشخصات فیزیکی',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63839f834c94732a541ce1fd',
|
||||
fullNativeName: 'وزن (کیلوگرم) مشخصات فیزیکی لپتاپ',
|
||||
nativeName: 'وزن (کیلوگرم)',
|
||||
englishName: 'lwe',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'مشخصات فیزیکی',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f22c7d358e3427d4428214',
|
||||
fullNativeName: 'جنس بدنه مشخصات فیزیکی لپتاپ',
|
||||
nativeName: 'جنس بدنه',
|
||||
englishName: 'lbmat',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'مشخصات فیزیکی',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '659e2ba341b67ad77d249b17',
|
||||
fullNativeName: 'سیستم کولینگ و خنک کنندگی مشخصات فیزیکی لپتاپ',
|
||||
nativeName: 'سیستم کولینگ و خنک کنندگی',
|
||||
englishName: 'lcooling',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'مشخصات فیزیکی',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63846e760df5e6a52824d2dc',
|
||||
fullNativeName: 'ابعاد (اینچ) صفحه نمایش لپتاپ',
|
||||
nativeName: 'ابعاد (اینچ)',
|
||||
englishName: 'ldisdim',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'صفحه نمایش',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63846e7d0df5e6a52824d2e4',
|
||||
fullNativeName: 'وضوح صفحه نمایش لپتاپ',
|
||||
nativeName: 'وضوح',
|
||||
englishName: 'ldisqua',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'صفحه نمایش',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63846e7f0df5e6a52824d2ec',
|
||||
fullNativeName: 'رفرش ریت (نرخ نوسازی) صفحه نمایش لپتاپ',
|
||||
nativeName: 'رفرش ریت (نرخ نوسازی)',
|
||||
englishName: 'ldisref',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'صفحه نمایش',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63846e840df5e6a52824d2f4',
|
||||
fullNativeName: 'میزان روشنایی (نیت) صفحه نمایش لپتاپ',
|
||||
nativeName: 'میزان روشنایی (نیت)',
|
||||
englishName: 'ldisbri',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'صفحه نمایش',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f22c65358e3427d44281ec',
|
||||
fullNativeName: 'گستره رنگی صفحه نمایش لپتاپ',
|
||||
nativeName: 'گستره رنگی',
|
||||
englishName: 'ldiscol',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'صفحه نمایش',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f22c71358e3427d4428200',
|
||||
fullNativeName: 'نوع پنل صفحه نمایش لپتاپ',
|
||||
nativeName: 'نوع پنل',
|
||||
englishName: 'ldispan',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'صفحه نمایش',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '644002e3be9b64da57f3f23b',
|
||||
fullNativeName: 'رزولوشن صفحه نمایش لپتاپ',
|
||||
nativeName: 'رزولوشن',
|
||||
englishName: 'ldisres',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'صفحه نمایش',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce668d74a30bf0da051d90',
|
||||
fullNativeName: 'نسبت تصویر صفحه نمایش لپتاپ',
|
||||
nativeName: 'نسبت تصویر',
|
||||
englishName: 'ldisasp',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'صفحه نمایش',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '65d59ff54497f0662ddcad44',
|
||||
fullNativeName: 'عمق رنگ(Color depth) صفحه نمایش لپتاپ',
|
||||
nativeName: 'عمق رنگ(Color depth)',
|
||||
englishName: 'ldisdep',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'صفحه نمایش',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63846ec40df5e6a52824d30a',
|
||||
fullNativeName: 'شرکت سازنده پردازنده لپتاپ',
|
||||
nativeName: 'شرکت سازنده',
|
||||
englishName: 'lcpubrand',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'پردازنده',
|
||||
priority: 0,
|
||||
},
|
||||
|
||||
{
|
||||
_id: '63846ec70df5e6a52824d313',
|
||||
fullNativeName: 'سری پردازنده پردازنده لپتاپ',
|
||||
nativeName: 'سری پردازنده',
|
||||
englishName: 'lcpuser',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'پردازنده',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63846eca0df5e6a52824d31c',
|
||||
fullNativeName: 'مدل پردازنده پردازنده لپتاپ',
|
||||
nativeName: 'مدل پردازنده',
|
||||
englishName: 'lcpumodel',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'پردازنده',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f22c57358e3427d44281d8',
|
||||
fullNativeName: 'قدرت پردازنده پردازنده لپتاپ',
|
||||
nativeName: 'قدرت پردازنده ',
|
||||
englishName: 'lcpupow',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'پردازنده',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63868a7f042e7c1f4e5a88cc',
|
||||
fullNativeName: 'شرکت سازنده کارت گرافیک لپتاپ',
|
||||
nativeName: 'شرکت سازنده',
|
||||
englishName: 'lgpubrand',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'کارت گرافیک',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '639325b39ba61a7bcaf25e87',
|
||||
fullNativeName: 'مدل کارت گرافیک کارت گرافیک لپتاپ',
|
||||
nativeName: 'مدل کارت گرافیک',
|
||||
englishName: 'lgpumodel',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'کارت گرافیک',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f22c8f358e3427d4428228',
|
||||
fullNativeName: 'توان گرافیک کارت گرافیک لپتاپ',
|
||||
nativeName: 'توان گرافیک',
|
||||
englishName: 'lgpuw',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'کارت گرافیک',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f22ccc358e3427d4428264',
|
||||
fullNativeName: 'مقدار حافظه گرافیک کارت گرافیک لپتاپ',
|
||||
nativeName: 'مقدار حافظه گرافیک',
|
||||
englishName: 'lgpuvram',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'کارت گرافیک',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f22cb4358e3427d442824f',
|
||||
fullNativeName: 'مقدار حافظه حافظه و رم لپتاپ',
|
||||
nativeName: 'مقدار حافظه',
|
||||
englishName: 'lssd',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'حافظه و رم',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f22cdb358e3427d4428279',
|
||||
fullNativeName: 'نوع حافظه حافظه و رم لپتاپ',
|
||||
nativeName: 'نوع حافظه',
|
||||
englishName: 'lssdtype',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'حافظه و رم',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f22ce4358e3427d442828e',
|
||||
fullNativeName: 'مقدار رم حافظه و رم لپتاپ',
|
||||
nativeName: 'مقدار رم',
|
||||
englishName: 'lramcap',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'حافظه و رم',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f22ced358e3427d44282a3',
|
||||
fullNativeName: 'نوع رم حافظه و رم لپتاپ',
|
||||
nativeName: 'نوع رم',
|
||||
englishName: 'lramtype',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'حافظه و رم',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f22cf5358e3427d44282b8',
|
||||
fullNativeName: 'سرعت رم حافظه و رم لپتاپ',
|
||||
nativeName: 'سرعت رم',
|
||||
englishName: 'lramspeed',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'حافظه و رم',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce6d0274a30bf0da052796',
|
||||
fullNativeName: 'ارتقا پذیری رم حافظه و رم لپتاپ',
|
||||
nativeName: 'ارتقا پذیری رم',
|
||||
englishName: 'lramupgr',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'حافظه و رم',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce6d1774a30bf0da0527b3',
|
||||
fullNativeName: 'ارتقا پذیری هارد حافظه و رم لپتاپ',
|
||||
nativeName: 'ارتقا پذیری هارد',
|
||||
englishName: 'lssdupgr',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'حافظه و رم',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f22d3c358e3427d44282e1',
|
||||
fullNativeName: 'توان باتری (Wh) باتری و انرژی لپتاپ',
|
||||
nativeName: 'توان باتری (Wh)',
|
||||
englishName: 'lbattwh',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'باتری و انرژی',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f22d3e358e3427d44282f7',
|
||||
fullNativeName: 'خروجی آداپتور (W) باتری و انرژی لپتاپ',
|
||||
nativeName: 'خروجی آداپتور (W)',
|
||||
englishName: 'ladapw',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'باتری و انرژی',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f22d54358e3427d4428323',
|
||||
fullNativeName: 'نوع باتری باتری و انرژی لپتاپ',
|
||||
nativeName: 'نوع باتری',
|
||||
englishName: 'lbattype',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'باتری و انرژی',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f4b0e817976077a6f30a12',
|
||||
fullNativeName: 'نام محصول مشخصات تولید لپتاپ',
|
||||
nativeName: 'نام محصول',
|
||||
englishName: 'lname',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'مشخصات تولید',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f4b0f817976077a6f30a29',
|
||||
fullNativeName: 'کد محصول مشخصات تولید لپتاپ',
|
||||
nativeName: 'کد محصول',
|
||||
englishName: 'lcode',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'مشخصات تولید',
|
||||
priority: 0,
|
||||
},
|
||||
|
||||
{
|
||||
_id: '64bbf4ec05f1a17c78c7d77f',
|
||||
fullNativeName: 'برند مشخصات تولید لپتاپ',
|
||||
nativeName: 'برند',
|
||||
englishName: 'lbrand',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'مشخصات تولید',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce70a474a30bf0da0530e6',
|
||||
fullNativeName: 'گارانتی کمپانی سازنده مشخصات تولید لپتاپ',
|
||||
nativeName: 'گارانتی کمپانی سازنده',
|
||||
englishName: 'lgur',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'مشخصات تولید',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce754b74a30bf0da05399c',
|
||||
fullNativeName: 'لایسنس ویندوز اورجینال مشخصات تولید لپتاپ',
|
||||
nativeName: 'لایسنس ویندوز اورجینال',
|
||||
englishName: 'lwlic',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'مشخصات تولید',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '6580df72f565d67d75dacdf2',
|
||||
fullNativeName: 'سال (نسل) معرفی مدل مشخصات تولید لپتاپ',
|
||||
nativeName: 'سال (نسل) معرفی مدل',
|
||||
englishName: 'lgen',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'مشخصات تولید',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce6ba874a30bf0da0526a4',
|
||||
fullNativeName: 'Wifi ارتباطات و شبکه لپتاپ',
|
||||
nativeName: 'Wifi',
|
||||
englishName: 'lwifi',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'ارتباطات و شبکه',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce6bb374a30bf0da0526c1',
|
||||
fullNativeName: 'Bluetooth ارتباطات و شبکه لپتاپ',
|
||||
nativeName: 'Bluetooth',
|
||||
englishName: 'lblu',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'ارتباطات و شبکه',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce6fd374a30bf0da052fb5',
|
||||
fullNativeName: 'وبکم ارتباطات و شبکه لپتاپ',
|
||||
nativeName: 'وبکم',
|
||||
englishName: 'lcam',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'ارتباطات و شبکه',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce6fe374a30bf0da052fe4',
|
||||
fullNativeName: 'کیفیت وبکم ارتباطات و شبکه لپتاپ',
|
||||
nativeName: 'کیفیت وبکم',
|
||||
englishName: 'lcamqu',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'ارتباطات و شبکه',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce67c374a30bf0da051f8e',
|
||||
fullNativeName: 'تاندربولت پورت ها لپتاپ',
|
||||
nativeName: 'تاندربولت',
|
||||
englishName: 'ltb',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'پورت ها',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce69bd74a30bf0da05229b',
|
||||
fullNativeName: 'Type C پورت ها لپتاپ',
|
||||
nativeName: 'Type C',
|
||||
englishName: 'ltypc',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'پورت ها',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce69d674a30bf0da052305',
|
||||
fullNativeName: 'PD پورت ها لپتاپ',
|
||||
nativeName: 'PD',
|
||||
englishName: 'lpd',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'پورت ها',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce6a5174a30bf0da052400',
|
||||
fullNativeName: 'HDMI 2.0 پورت ها لپتاپ',
|
||||
nativeName: 'HDMI 2.0',
|
||||
englishName: 'lhdm2',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'پورت ها',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce6a9774a30bf0da0524a5',
|
||||
fullNativeName: 'HDMI 2.1 پورت ها لپتاپ',
|
||||
nativeName: 'HDMI 2.1',
|
||||
englishName: 'lhdm21',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'پورت ها',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce6b5374a30bf0da05258e',
|
||||
fullNativeName: 'USB 2.0 پورت ها لپتاپ',
|
||||
nativeName: 'USB 2.0',
|
||||
englishName: 'lusb2',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'پورت ها',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce6b5c74a30bf0da0525ab',
|
||||
fullNativeName: 'USB 3.0 پورت ها لپتاپ',
|
||||
nativeName: 'USB 3.0',
|
||||
englishName: 'lusb3',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'پورت ها',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce721674a30bf0da053390',
|
||||
fullNativeName: 'USB 3.2 پورت ها لپتاپ',
|
||||
nativeName: 'USB 3.2',
|
||||
englishName: 'lusb32',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'پورت ها',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64ce721674a30bf0da053392',
|
||||
fullNativeName: 'RJ45 پورت ها لپتاپ',
|
||||
nativeName: 'RJ45',
|
||||
englishName: 'lrj45',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'پورت ها',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '65a0071b0c1fc5615d7a8237',
|
||||
fullNativeName: 'Jack 3.5 پورت ها لپتاپ',
|
||||
nativeName: 'Jack 3.5',
|
||||
englishName: 'ljack',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'پورت ها',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '65a0076a0c1fc5615d7a82f2',
|
||||
fullNativeName: 'Sd Card Reader پورت ها لپتاپ',
|
||||
nativeName: 'Sd Card Reader',
|
||||
englishName: 'lsdreader',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'پورت ها',
|
||||
priority: 0,
|
||||
},
|
||||
|
||||
{
|
||||
_id: '65a52fb77b78648044177ec2',
|
||||
fullNativeName: 'USB-C 4 پورت ها لپتاپ',
|
||||
nativeName: 'USB-C 4',
|
||||
englishName: 'lusbc4',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'پورت ها',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '668a564f55b0c17771f0eeb9',
|
||||
fullNativeName: 'Mini DisplayPort پورت ها لپتاپ',
|
||||
nativeName: 'Mini DisplayPort',
|
||||
englishName: 'lminidp',
|
||||
group: '63822b8fa964fe72ec7be6a0',
|
||||
isFilterable: true,
|
||||
tag: 'پورت ها',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63d578a58678085f9874e016',
|
||||
fullNativeName: 'وزن مشخصات فیزیکی کوله پشتی',
|
||||
nativeName: 'وزن',
|
||||
englishName: 'bpweight',
|
||||
group: '63d3e9119a1819889d6d00b9',
|
||||
isFilterable: true,
|
||||
tag: 'مشخصات فیزیکی',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f4c48e17976077a6f3113b',
|
||||
fullNativeName: 'ابعاد مشخصات فیزیکی کوله پشتی',
|
||||
nativeName: 'ابعاد',
|
||||
englishName: 'bpdim',
|
||||
group: '63d3e9119a1819889d6d00b9',
|
||||
isFilterable: true,
|
||||
tag: 'مشخصات فیزیکی',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f4c49517976077a6f3114c',
|
||||
fullNativeName: 'جنس مشخصات فیزیکی کوله پشتی',
|
||||
nativeName: 'جنس',
|
||||
englishName: 'bpmat',
|
||||
group: '63d3e9119a1819889d6d00b9',
|
||||
isFilterable: true,
|
||||
tag: 'مشخصات فیزیکی',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f4c53b17976077a6f311c7',
|
||||
fullNativeName: 'مناسب تا سایز مشخصات فیزیکی کوله پشتی',
|
||||
nativeName: 'مناسب تا سایز',
|
||||
englishName: 'bpsize',
|
||||
group: '63d3e9119a1819889d6d00b9',
|
||||
isFilterable: true,
|
||||
tag: 'مشخصات فیزیکی',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f4c55117976077a6f311d9',
|
||||
fullNativeName: 'رنگ مشخصات فیزیکی کوله پشتی',
|
||||
nativeName: 'رنگ',
|
||||
englishName: 'bpcolor',
|
||||
group: '63d3e9119a1819889d6d00b9',
|
||||
isFilterable: true,
|
||||
tag: 'مشخصات فیزیکی',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f4c4ed17976077a6f3116d',
|
||||
fullNativeName: 'ضد آب قابلیت ها کوله پشتی',
|
||||
nativeName: 'ضد آب',
|
||||
englishName: 'bpwatpf',
|
||||
group: '63d3e9119a1819889d6d00b9',
|
||||
isFilterable: true,
|
||||
tag: 'قابلیت ها',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f4c4f417976077a6f3117f',
|
||||
fullNativeName: 'ضد رطوبت قابلیت ها کوله پشتی',
|
||||
nativeName: 'ضد رطوبت',
|
||||
englishName: 'bpmoprf',
|
||||
group: '63d3e9119a1819889d6d00b9',
|
||||
isFilterable: true,
|
||||
tag: 'قابلیت ها',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f4c4fe17976077a6f31191',
|
||||
fullNativeName: 'ضد ضربه قابلیت ها کوله پشتی',
|
||||
nativeName: 'ضد ضربه',
|
||||
englishName: 'bpdmgprf',
|
||||
group: '63d3e9119a1819889d6d00b9',
|
||||
isFilterable: true,
|
||||
tag: 'قابلیت ها',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f4c51217976077a6f311a3',
|
||||
fullNativeName: 'پورت USB قابلیت ها کوله پشتی',
|
||||
nativeName: 'پورت USB',
|
||||
englishName: 'bpusb',
|
||||
group: '63d3e9119a1819889d6d00b9',
|
||||
isFilterable: true,
|
||||
tag: 'قابلیت ها',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '63f4c52c17976077a6f311b5',
|
||||
fullNativeName: 'محفظه لپتاپ قابلیت ها کوله پشتی',
|
||||
nativeName: 'محفظه لپتاپ',
|
||||
englishName: 'bplap',
|
||||
group: '63d3e9119a1819889d6d00b9',
|
||||
isFilterable: true,
|
||||
tag: 'قابلیت ها',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64bbf55f05f1a17c78c7d8d6',
|
||||
fullNativeName: 'نام اختصاصی کد محصول کوله پشتی',
|
||||
nativeName: 'نام اختصاصی',
|
||||
englishName: 'bpspname',
|
||||
group: '63d3e9119a1819889d6d00b9',
|
||||
isFilterable: true,
|
||||
tag: 'کد محصول',
|
||||
priority: 0,
|
||||
},
|
||||
{
|
||||
_id: '64bbf56405f1a17c78c7d8ed',
|
||||
fullNativeName: 'برند کد محصول کوله پشتی',
|
||||
nativeName: 'برند',
|
||||
englishName: 'bpbrand',
|
||||
group: '63d3e9119a1819889d6d00b9',
|
||||
isFilterable: true,
|
||||
tag: 'کد محصول',
|
||||
priority: 0,
|
||||
},
|
||||
]
|
||||
|
||||
await Feature.deleteMany({})
|
||||
console.log(chalk.red('Deleted all feature records.'))
|
||||
|
||||
await Feature.insertMany(features, null)
|
||||
console.log(chalk.green.bold(`FEATURES: Created ${features.length} feature(s)`))
|
||||
}
|
||||
|
||||
module.exports = { runSeeder }
|
||||
@@ -0,0 +1,53 @@
|
||||
const Feature = require('./featureModel')
|
||||
const AppError = require('../../globalErrorHandler/AppError')
|
||||
const categoryService = require('../category/categoryService')
|
||||
|
||||
exports.getAllCategoryFeatures = async () => {
|
||||
const groups = JSON.parse(JSON.stringify(await categoryService.getAllCategories()))
|
||||
for (let group of groups) {
|
||||
group.features = await Feature.find({ category: category._id })
|
||||
}
|
||||
return groups
|
||||
}
|
||||
|
||||
module.exports.getFeatureByCategory = async (categoryId) => {
|
||||
return Feature.find({category: categoryId}, null, null)
|
||||
}
|
||||
|
||||
module.exports.getAllFeatures = async (query) => {
|
||||
return Feature.find(query, null, null)
|
||||
}
|
||||
|
||||
module.exports.createFeatures = async (data) => {
|
||||
return Feature.create(data, null)
|
||||
}
|
||||
|
||||
module.exports.getFeatures = async (featureId) => {
|
||||
const group = await Feature.findById(featureId)
|
||||
|
||||
if (!group) {
|
||||
throw new AppError('NoGroupFound', 404, {})
|
||||
}
|
||||
|
||||
return group
|
||||
}
|
||||
|
||||
module.exports.updateFeatures = async (featureId, data) => {
|
||||
const group = await Feature.findOneAndUpdate({ _id: featureId }, data)
|
||||
|
||||
if (!group) {
|
||||
throw new AppError('NoGroupFound', 404, {})
|
||||
}
|
||||
|
||||
return group
|
||||
}
|
||||
|
||||
module.exports.deleteFeatures = async (featureId) => {
|
||||
const group = await Feature.findOneAndUpdate({ _id: featureId }, { isActive: false })
|
||||
|
||||
if (!group) {
|
||||
throw new AppError('NoGroupFound', 404, {})
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
const catchAsync = require('../../globalErrorHandler/catchAsync')
|
||||
const fileService = require('./fileService')
|
||||
|
||||
exports.bucketSingleUpload = catchAsync(async (req, res, next) => {
|
||||
const fileData = await fileService.bucketSingleUpload(req.file, req.params.bucketName)
|
||||
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
data: fileData,
|
||||
})
|
||||
})
|
||||
|
||||
exports.userUploadOrderDocument = catchAsync(async (req, res, next) => {
|
||||
const files = await fileService.userUploadOrderDocument(req.files)
|
||||
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
results: files.length,
|
||||
data: files,
|
||||
})
|
||||
})
|
||||
|
||||
exports.bucketMultiUpload = catchAsync(async (req, res, next) => {
|
||||
const files = await fileService.bucketMultiUpload(req.files, req.params.bucketName)
|
||||
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
results: files.length,
|
||||
data: files,
|
||||
})
|
||||
})
|
||||
|
||||
exports.bucketGetFiles = catchAsync(async (req, res, next) => {
|
||||
const files = await fileService.bucketGetFiles()
|
||||
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
results: files.length,
|
||||
data: files,
|
||||
})
|
||||
})
|
||||
|
||||
exports.getSignedUrl = catchAsync(async (req, res, next) => {
|
||||
const url = await fileService.getSignedUrl(req.body.fileName)
|
||||
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
data: url,
|
||||
})
|
||||
})
|
||||
|
||||
exports.bucketDeleteFile = catchAsync(async (req, res, next) => {
|
||||
await fileService.bucketDeleteFile(req.body, req.params.bucketName)
|
||||
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
})
|
||||
})
|
||||
|
||||
exports.getAllFiles = catchAsync(async (req, res, next) => {
|
||||
const files = await fileService.getAllFiles()
|
||||
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
results: files.length,
|
||||
data: files,
|
||||
})
|
||||
})
|
||||
|
||||
exports.getFile = catchAsync(async (req, res, next) => {
|
||||
const file = await fileService.getFile(req.body.id)
|
||||
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
data: file,
|
||||
})
|
||||
})
|
||||
|
||||
exports.createFile = catchAsync(async (req, res, next) => {
|
||||
const file = await fileService.createFile(req.body)
|
||||
|
||||
res.status(201).json({
|
||||
status: 'success',
|
||||
data: file,
|
||||
})
|
||||
})
|
||||
|
||||
exports.updateFile = catchAsync(async (req, res, next) => {
|
||||
const file = await fileService.updateFile(req.body)
|
||||
res.status(200).json({
|
||||
status: 'success',
|
||||
data: file,
|
||||
})
|
||||
})
|
||||
|
||||
exports.deleteFile = catchAsync(async (req, res, next) => {
|
||||
await fileService.deleteFile(req.body.id)
|
||||
|
||||
res.status(204).json({
|
||||
status: 'success',
|
||||
data: null,
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,32 @@
|
||||
const mongoose = require('mongoose')
|
||||
const ObjectID = mongoose.Schema.Types.ObjectId
|
||||
|
||||
const fileSchema = new mongoose.Schema(
|
||||
{
|
||||
fileName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
owner: {
|
||||
type: ObjectID,
|
||||
ref: 'User',
|
||||
},
|
||||
fileEndpoint: String,
|
||||
bucketName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
toJSON: { virtuals: true },
|
||||
toObject: { virtuals: true },
|
||||
},
|
||||
{ timestamps: true }
|
||||
)
|
||||
|
||||
fileSchema.virtual('publicUrl').get(function () {
|
||||
return this.fileEndpoint + '/' + this.bucketName + '/' + this.fileName
|
||||
})
|
||||
|
||||
const File = mongoose.model('file', fileSchema)
|
||||
module.exports = File
|
||||
@@ -0,0 +1,50 @@
|
||||
const express = require('express')
|
||||
const fileController = require('./fileController')
|
||||
const perm = require('../../middlewares/permissionMiddleware')
|
||||
const loginCheck = require('../../middlewares/loginCheck')
|
||||
const upload = require('../../middlewares/multerMiddleware')
|
||||
|
||||
const router = new express.Router()
|
||||
|
||||
router.use(loginCheck.loginProtect)
|
||||
|
||||
router.post(
|
||||
'/bucket/upload-single/:bucketName/',
|
||||
perm.requires('uploadsinglefile'),
|
||||
upload.single('image'),
|
||||
fileController.bucketSingleUpload
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/bucket/upload-single-filepond/:bucketName',
|
||||
perm.requires('uploadsinglefile'),
|
||||
upload.single('filepond-image'),
|
||||
fileController.bucketSingleUpload
|
||||
)
|
||||
|
||||
router.post('/bucket/upload-multi', perm.requires('uploadmultifile'), upload.array('image', 100), fileController.bucketMultiUpload)
|
||||
|
||||
router.post(
|
||||
'/bucket/upload-multi-filepond/:bucketName',
|
||||
perm.requires('uploadmultifile'),
|
||||
upload.array('filepond-image', 100),
|
||||
fileController.bucketMultiUpload
|
||||
)
|
||||
|
||||
router.get('/bucket/get-files', perm.requires('getbucketfiles'), fileController.bucketGetFiles)
|
||||
|
||||
router.get('/bucket/get-signed', perm.requires('getbucketfiles'), fileController.getSignedUrl)
|
||||
|
||||
router.delete('/bucket/delete-file/:bucketName', perm.requires('deletebucketfiles'), fileController.bucketDeleteFile)
|
||||
|
||||
router.get('/admin/get-all', perm.requires('getallfiles'), fileController.getAllFiles)
|
||||
|
||||
router.post('/admin/create', perm.requires('createfile'), fileController.createFile)
|
||||
|
||||
router.get('/admin/get-one/:fileId', perm.requires('getfile'), fileController.getFile)
|
||||
|
||||
router.put('/admin/update/:fileId', perm.requires('updatefile'), fileController.updateFile)
|
||||
|
||||
router.delete('/admin/delete/:fileId', perm.requires('deletefile'), fileController.deleteFile)
|
||||
|
||||
module.exports = router
|
||||
@@ -0,0 +1,136 @@
|
||||
const File = require('./fileModel')
|
||||
const AppError = require('../../globalErrorHandler/AppError')
|
||||
const util = require('util')
|
||||
const fs = require('fs')
|
||||
const {
|
||||
uploadObject,
|
||||
deleteObject,
|
||||
listOfObjects,
|
||||
signedUrl,
|
||||
copyObject,
|
||||
removeObject,
|
||||
} = require('../../utils/upload/bucket')
|
||||
|
||||
const deleteTempFile = util.promisify(fs.unlink)
|
||||
|
||||
const bucketSingleUpload = async (file, bucketName) => {
|
||||
const fileData = {
|
||||
originalName: file.originalname,
|
||||
filename: file.filename,
|
||||
path: file.path,
|
||||
}
|
||||
|
||||
const result = await uploadObject(fileData, bucketName)
|
||||
|
||||
const data = {
|
||||
fileURL: result.fileURL,
|
||||
fileName: result.fileName,
|
||||
fileEndpoint: result.fileEndpoint,
|
||||
bucketName,
|
||||
}
|
||||
|
||||
// Delete file from uploads folder
|
||||
await deleteTempFile(file.path)
|
||||
|
||||
const fileRecord = await createFile(data)
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
fileRecord,
|
||||
}
|
||||
}
|
||||
|
||||
const bucketMultiUpload = async (files, bucketName) => {
|
||||
const results = []
|
||||
|
||||
for (let file of files) {
|
||||
const result = await bucketSingleUpload(file, bucketName)
|
||||
results.push(result)
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
const bucketDeleteFile = async (fileName, bucketName) => {
|
||||
await deleteObject(fileName, bucketName)
|
||||
await deleteFile(fileName)
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
const getAllFiles = async () => {
|
||||
return File.find({}, null, null)
|
||||
}
|
||||
|
||||
const getFile = async (fileId) => {
|
||||
const file = await File.findById(fileId, null, null)
|
||||
|
||||
if (!file) {
|
||||
throw new AppError('NoFileFound', 404, {})
|
||||
}
|
||||
|
||||
return file
|
||||
}
|
||||
|
||||
const createFile = async (data) => {
|
||||
return File.create(data, null)
|
||||
}
|
||||
|
||||
const updateFile = async (fileId, data) => {
|
||||
const file = await File.findOneAndUpdate({ _id: fileId }, data, null)
|
||||
|
||||
if (!file) {
|
||||
throw AppError('NoFileFound', 404, {})
|
||||
}
|
||||
|
||||
return file
|
||||
}
|
||||
|
||||
const deleteFile = async (fileName) => {
|
||||
await File.findOneAndDelete({ fileName }, null)
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
const bucketGetFiles = async (bucketName) => {
|
||||
return listOfObjects(bucketName)
|
||||
}
|
||||
|
||||
const getSignedUrl = async (fileName, bucketName) => {
|
||||
if (!fileName) {
|
||||
return
|
||||
}
|
||||
return signedUrl(bucketName, fileName)
|
||||
}
|
||||
|
||||
const getMultipleSignedUrls = async (fileNameArray, bucketName) => {
|
||||
const urls = []
|
||||
for (let fileName of fileNameArray) {
|
||||
urls.push({ url: await getSignedUrl(fileName, bucketName), fileName: fileName})
|
||||
}
|
||||
return urls
|
||||
}
|
||||
|
||||
const moveFromTempToMain = async (files, targetBucket) => {
|
||||
const tempBucket = 'temp'
|
||||
|
||||
for (const file of files) {
|
||||
await copyObject(targetBucket, file, `${tempBucket}/${file}`)
|
||||
|
||||
await removeObject(tempBucket, file)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
moveFromTempToMain,
|
||||
getMultipleSignedUrls,
|
||||
getSignedUrl,
|
||||
createFile,
|
||||
updateFile,
|
||||
deleteFile,
|
||||
getAllFiles,
|
||||
getFile,
|
||||
bucketSingleUpload,
|
||||
bucketMultiUpload,
|
||||
bucketDeleteFile,
|
||||
bucketGetFiles,
|
||||
}
|
||||
Reference in New Issue
Block a user