feat(Moderation): implement moderation reports feature
All checks were successful
Deploy to production / deploy (push) Successful in 2m1s
All checks were successful
Deploy to production / deploy (push) Successful in 2m1s
- Added moderationRouter to handle moderation-related API routes. - Introduced new methods in AdminController for fetching all regions, region types, and creating regions. - Enhanced adminRouter with routes for moderation reports and status updates. - Updated navigationController to include moderation reports in the admin menu. - Implemented frontend components for reporting messages in the forum and managing moderation reports. - Added internationalization support for moderation-related texts in multiple languages.
This commit is contained in:
@@ -22,6 +22,10 @@ import RegionData from "../models/falukant/data/region.js";
|
||||
import RegionType from "../models/falukant/type/region.js";
|
||||
import BranchType from "../models/falukant/type/branch.js";
|
||||
import RegionDistance from "../models/falukant/data/region_distance.js";
|
||||
import ProductType from "../models/falukant/type/product.js";
|
||||
import TownProductWorth from "../models/falukant/data/town_product_worth.js";
|
||||
import Weather from "../models/falukant/data/weather.js";
|
||||
import WeatherType from "../models/falukant/type/weather.js";
|
||||
import Room from '../models/chat/room.js';
|
||||
import UserParam from '../models/community/user_param.js';
|
||||
import Image from '../models/community/image.js';
|
||||
@@ -753,6 +757,129 @@ class AdminService {
|
||||
return regions;
|
||||
}
|
||||
|
||||
async getFalukantAllRegions(userId) {
|
||||
if (!(await this.hasUserAccess(userId, 'falukantusers'))) {
|
||||
throw new Error('noaccess');
|
||||
}
|
||||
|
||||
const regions = await RegionData.findAll({
|
||||
attributes: ['id', 'name', 'map', 'regionTypeId', 'parentId'],
|
||||
include: [
|
||||
{
|
||||
model: RegionType,
|
||||
as: 'regionType',
|
||||
attributes: ['id', 'labelTr', 'parentId'],
|
||||
},
|
||||
],
|
||||
order: [['name', 'ASC']],
|
||||
});
|
||||
|
||||
return regions;
|
||||
}
|
||||
|
||||
async getFalukantRegionTypes(userId) {
|
||||
if (!(await this.hasUserAccess(userId, 'falukantusers'))) {
|
||||
throw new Error('noaccess');
|
||||
}
|
||||
|
||||
const types = await RegionType.findAll({
|
||||
attributes: ['id', 'labelTr', 'parentId'],
|
||||
order: [['labelTr', 'ASC']],
|
||||
});
|
||||
return types;
|
||||
}
|
||||
|
||||
async createFalukantRegion(userId, { name, regionTypeId, parentId } = {}) {
|
||||
if (!(await this.hasUserAccess(userId, 'falukantusers'))) {
|
||||
throw new Error('noaccess');
|
||||
}
|
||||
|
||||
const regionName = String(name || '').trim();
|
||||
const typeId = Number(regionTypeId);
|
||||
const parentRegionId = parentId == null || parentId === '' ? null : Number(parentId);
|
||||
|
||||
if (!regionName) {
|
||||
throw new Error('missingName');
|
||||
}
|
||||
if (!Number.isInteger(typeId) || typeId <= 0) {
|
||||
throw new Error('missingRegionType');
|
||||
}
|
||||
if (parentRegionId != null && (!Number.isInteger(parentRegionId) || parentRegionId <= 0)) {
|
||||
throw new Error('invalidParent');
|
||||
}
|
||||
|
||||
const regionType = await RegionType.findByPk(typeId, { attributes: ['id', 'labelTr', 'parentId'] });
|
||||
if (!regionType) {
|
||||
throw new Error('regionTypeNotFound');
|
||||
}
|
||||
|
||||
let parentRegion = null;
|
||||
if (parentRegionId != null) {
|
||||
parentRegion = await RegionData.findByPk(parentRegionId, { attributes: ['id', 'regionTypeId'] });
|
||||
if (!parentRegion) {
|
||||
throw new Error('parentRegionNotFound');
|
||||
}
|
||||
}
|
||||
|
||||
if (regionType.parentId != null) {
|
||||
if (parentRegionId == null) {
|
||||
throw new Error('missingParent');
|
||||
}
|
||||
if (!parentRegion || parentRegion.regionTypeId !== regionType.parentId) {
|
||||
throw new Error('invalidParentRegionType');
|
||||
}
|
||||
} else if (parentRegionId != null) {
|
||||
throw new Error('parentNotAllowedForType');
|
||||
}
|
||||
|
||||
const randomWorthPercent = () => Math.floor(Math.random() * 31) + 55; // 55–85
|
||||
|
||||
const createdId = await sequelize.transaction(async (t) => {
|
||||
const region = await RegionData.create(
|
||||
{
|
||||
name: regionName,
|
||||
regionTypeId: regionType.id,
|
||||
parentId: parentRegionId,
|
||||
map: {},
|
||||
},
|
||||
{ transaction: t }
|
||||
);
|
||||
|
||||
const products = await ProductType.findAll({ attributes: ['id'], transaction: t });
|
||||
if (products.length > 0) {
|
||||
await TownProductWorth.bulkCreate(
|
||||
products.map((p) => ({
|
||||
productId: p.id,
|
||||
regionId: region.id,
|
||||
worthPercent: randomWorthPercent(),
|
||||
})),
|
||||
{ transaction: t, ignoreDuplicates: true }
|
||||
);
|
||||
}
|
||||
|
||||
if (regionType.labelTr === 'city') {
|
||||
const weatherTypes = await WeatherType.findAll({ attributes: ['id'], transaction: t });
|
||||
if (weatherTypes.length > 0) {
|
||||
const randomWeatherType = weatherTypes[Math.floor(Math.random() * weatherTypes.length)];
|
||||
await Weather.findOrCreate({
|
||||
where: { regionId: region.id },
|
||||
defaults: { weatherTypeId: randomWeatherType.id },
|
||||
transaction: t,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return region.id;
|
||||
});
|
||||
|
||||
const created = await RegionData.findByPk(createdId, {
|
||||
attributes: ['id', 'name', 'map', 'regionTypeId', 'parentId'],
|
||||
include: [{ model: RegionType, as: 'regionType', attributes: ['id', 'labelTr', 'parentId'] }],
|
||||
});
|
||||
|
||||
return created;
|
||||
}
|
||||
|
||||
async getTitlesOfNobility(userId) {
|
||||
if (!(await this.hasUserAccess(userId, 'falukantusers'))) {
|
||||
throw new Error('noaccess');
|
||||
|
||||
Reference in New Issue
Block a user