Compare commits

...

1 Commits

Author SHA1 Message Date
Flatlogic Bot
dc86c7ef25 Updated via schema editor on 2026-03-23 10:42 2026-03-23 10:43:17 +00:00
9 changed files with 5935 additions and 7772 deletions

View File

@ -0,0 +1,36 @@
module.exports = {
/**
* @param {QueryInterface} queryInterface
* @param {Sequelize} Sequelize
* @returns {Promise<void>}
*/
async up(queryInterface, Sequelize) {
/**
* @type {Transaction}
*/
const transaction = await queryInterface.sequelize.transaction();
try {
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
/**
* @param {QueryInterface} queryInterface
* @param {Sequelize} Sequelize
* @returns {Promise<void>}
*/
async down(queryInterface, Sequelize) {
/**
* @type {Transaction}
*/
const transaction = await queryInterface.sequelize.transaction();
try {
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,3 @@
const express = require('express');
const cors = require('cors');
const app = express();
@ -14,15 +13,10 @@ const swaggerJsDoc = require('swagger-jsdoc');
const authRoutes = require('./routes/auth');
const fileRoutes = require('./routes/file');
const searchRoutes = require('./routes/search');
const sqlRoutes = require('./routes/sql');
const pexelsRoutes = require('./routes/pexels');
const openaiRoutes = require('./routes/openai');
const usersRoutes = require('./routes/users');
const rolesRoutes = require('./routes/roles');
const permissionsRoutes = require('./routes/permissions');
@ -59,6 +53,7 @@ const pricing_plansRoutes = require('./routes/pricing_plans');
const plan_featuresRoutes = require('./routes/plan_features');
const usersRoutes = require('./routes/users');
const getBaseUrl = (url) => {
if (!url) return '';
@ -67,17 +62,18 @@ const getBaseUrl = (url) => {
const options = {
definition: {
openapi: "3.0.0",
info: {
version: "1.0.0",
title: "Course LMS",
description: "Course LMS Online REST API for Testing and Prototyping application. You can perform all major operations with your entities - create, delete and etc.",
},
openapi: '3.0.0',
info: {
version: '1.0.0',
title: 'Course LMS',
description:
'Course LMS Online REST API for Testing and Prototyping application. You can perform all major operations with your entities - create, delete and etc.',
},
servers: [
{
url: getBaseUrl(process.env.NEXT_PUBLIC_BACK_API) || config.swaggerUrl,
description: "Development server",
}
description: 'Development server',
},
],
components: {
securitySchemes: {
@ -85,28 +81,36 @@ const options = {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
}
},
},
responses: {
UnauthorizedError: {
description: "Access token is missing or invalid"
}
}
description: 'Access token is missing or invalid',
},
},
},
security: [{
bearerAuth: []
}]
security: [
{
bearerAuth: [],
},
],
},
apis: ["./src/routes/*.js"],
apis: ['./src/routes/*.js'],
};
const specs = swaggerJsDoc(options);
app.use('/api-docs', function (req, res, next) {
swaggerUI.host = getBaseUrl(process.env.NEXT_PUBLIC_BACK_API) || req.get('host');
next()
}, swaggerUI.serve, swaggerUI.setup(specs))
app.use(
'/api-docs',
function (req, res, next) {
swaggerUI.host =
getBaseUrl(process.env.NEXT_PUBLIC_BACK_API) || req.get('host');
next();
},
swaggerUI.serve,
swaggerUI.setup(specs),
);
app.use(cors({origin: true}));
app.use(cors({ origin: true }));
require('./auth/auth');
app.use(bodyParser.json());
@ -116,85 +120,148 @@ app.use('/api/file', fileRoutes);
app.use('/api/pexels', pexelsRoutes);
app.enable('trust proxy');
app.use('/api/users', passport.authenticate('jwt', {session: false}), usersRoutes);
app.use('/api/roles', passport.authenticate('jwt', {session: false}), rolesRoutes);
app.use('/api/permissions', passport.authenticate('jwt', {session: false}), permissionsRoutes);
app.use('/api/courses', passport.authenticate('jwt', {session: false}), coursesRoutes);
app.use('/api/course_sections', passport.authenticate('jwt', {session: false}), course_sectionsRoutes);
app.use('/api/lessons', passport.authenticate('jwt', {session: false}), lessonsRoutes);
app.use('/api/enrollments', passport.authenticate('jwt', {session: false}), enrollmentsRoutes);
app.use('/api/lesson_progress', passport.authenticate('jwt', {session: false}), lesson_progressRoutes);
app.use('/api/course_reviews', passport.authenticate('jwt', {session: false}), course_reviewsRoutes);
app.use('/api/course_announcements', passport.authenticate('jwt', {session: false}), course_announcementsRoutes);
app.use('/api/quizzes', passport.authenticate('jwt', {session: false}), quizzesRoutes);
app.use('/api/quiz_questions', passport.authenticate('jwt', {session: false}), quiz_questionsRoutes);
app.use('/api/quiz_options', passport.authenticate('jwt', {session: false}), quiz_optionsRoutes);
app.use('/api/quiz_attempts', passport.authenticate('jwt', {session: false}), quiz_attemptsRoutes);
app.use('/api/assignment_submissions', passport.authenticate('jwt', {session: false}), assignment_submissionsRoutes);
app.use('/api/marketing_pages', passport.authenticate('jwt', {session: false}), marketing_pagesRoutes);
app.use('/api/contact_messages', passport.authenticate('jwt', {session: false}), contact_messagesRoutes);
app.use('/api/pricing_plans', passport.authenticate('jwt', {session: false}), pricing_plansRoutes);
app.use('/api/plan_features', passport.authenticate('jwt', {session: false}), plan_featuresRoutes);
app.use(
'/api/openai',
passport.authenticate('jwt', { session: false }),
openaiRoutes,
'/api/roles',
passport.authenticate('jwt', { session: false }),
rolesRoutes,
);
app.use(
'/api/ai',
passport.authenticate('jwt', { session: false }),
openaiRoutes,
'/api/permissions',
passport.authenticate('jwt', { session: false }),
permissionsRoutes,
);
app.use(
'/api/courses',
passport.authenticate('jwt', { session: false }),
coursesRoutes,
);
app.use(
'/api/course_sections',
passport.authenticate('jwt', { session: false }),
course_sectionsRoutes,
);
app.use(
'/api/lessons',
passport.authenticate('jwt', { session: false }),
lessonsRoutes,
);
app.use(
'/api/enrollments',
passport.authenticate('jwt', { session: false }),
enrollmentsRoutes,
);
app.use(
'/api/lesson_progress',
passport.authenticate('jwt', { session: false }),
lesson_progressRoutes,
);
app.use(
'/api/course_reviews',
passport.authenticate('jwt', { session: false }),
course_reviewsRoutes,
);
app.use(
'/api/course_announcements',
passport.authenticate('jwt', { session: false }),
course_announcementsRoutes,
);
app.use(
'/api/quizzes',
passport.authenticate('jwt', { session: false }),
quizzesRoutes,
);
app.use(
'/api/quiz_questions',
passport.authenticate('jwt', { session: false }),
quiz_questionsRoutes,
);
app.use(
'/api/quiz_options',
passport.authenticate('jwt', { session: false }),
quiz_optionsRoutes,
);
app.use(
'/api/quiz_attempts',
passport.authenticate('jwt', { session: false }),
quiz_attemptsRoutes,
);
app.use(
'/api/assignment_submissions',
passport.authenticate('jwt', { session: false }),
assignment_submissionsRoutes,
);
app.use(
'/api/marketing_pages',
passport.authenticate('jwt', { session: false }),
marketing_pagesRoutes,
);
app.use(
'/api/contact_messages',
passport.authenticate('jwt', { session: false }),
contact_messagesRoutes,
);
app.use(
'/api/pricing_plans',
passport.authenticate('jwt', { session: false }),
pricing_plansRoutes,
);
app.use(
'/api/plan_features',
passport.authenticate('jwt', { session: false }),
plan_featuresRoutes,
);
app.use(
'/api/users',
passport.authenticate('jwt', { session: false }),
usersRoutes,
);
app.use(
'/api/openai',
passport.authenticate('jwt', { session: false }),
openaiRoutes,
);
app.use(
'/api/search',
passport.authenticate('jwt', { session: false }),
searchRoutes);
app.use(
'/api/sql',
passport.authenticate('jwt', { session: false }),
sqlRoutes);
const publicDir = path.join(
__dirname,
'../public',
searchRoutes,
);
const publicDir = path.join(__dirname, '../public');
if (fs.existsSync(publicDir)) {
app.use('/', express.static(publicDir));
app.get('*', function(request, response) {
response.sendFile(
path.resolve(publicDir, 'index.html'),
);
app.get('*', function (request, response) {
response.sendFile(path.resolve(publicDir, 'index.html'));
});
}
const PORT = process.env.NODE_ENV === 'dev_stage' ? 3000 : 8080;
db.sequelize.sync().then(function () {
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}`);
});
});
module.exports = app;

View File

@ -9,7 +9,6 @@ const Op = Sequelize.Op;
* @param {object} currentUser
*/
async function checkPermissions(permission, currentUser) {
if (!currentUser) {
throw new ValidationError('auth.unauthorized');
}
@ -36,401 +35,88 @@ async function checkPermissions(permission, currentUser) {
}
module.exports = class SearchService {
static async search(searchQuery, currentUser ) {
static async search(searchQuery, currentUser) {
try {
if (!searchQuery) {
throw new ValidationError('iam.errors.searchQueryRequired');
}
const tableColumns = {
courses: [
'title',
'slug',
'short_description',
'description',
'currency',
],
"users": [
course_sections: ['title'],
"firstName",
lessons: ['title', 'slug', 'content', 'video_url'],
"lastName",
enrollments: ['notes'],
"phoneNumber",
course_reviews: ['title', 'comment'],
"email",
course_announcements: ['title', 'message'],
],
quizzes: ['title', 'instructions'],
quiz_questions: ['prompt', 'explanation'],
quiz_options: ['label'],
assignment_submissions: ['submission_text', 'instructor_feedback'],
marketing_pages: [
'title',
'slug',
'hero_headline',
'hero_subheadline',
"courses": [
'content',
],
"title",
contact_messages: ['name', 'email', 'subject', 'message'],
"slug",
"short_description",
"description",
"currency",
],
"course_sections": [
"title",
],
"lessons": [
"title",
"slug",
"content",
"video_url",
],
"enrollments": [
"notes",
],
"course_reviews": [
"title",
"comment",
],
"course_announcements": [
"title",
"message",
],
"quizzes": [
"title",
"instructions",
],
"quiz_questions": [
"prompt",
"explanation",
],
"quiz_options": [
"label",
],
"assignment_submissions": [
"submission_text",
"instructor_feedback",
],
"marketing_pages": [
"title",
"slug",
"hero_headline",
"hero_subheadline",
"content",
],
"contact_messages": [
"name",
"email",
"subject",
"message",
],
"pricing_plans": [
"name",
"description",
"currency",
],
"plan_features": [
"name",
"description",
],
pricing_plans: ['name', 'description', 'currency'],
plan_features: ['name', 'description'],
users: ['firstName', 'lastName', 'phoneNumber', 'email'],
};
const columnsInt = {
courses: ['price'],
course_sections: ['position'],
lessons: ['duration_minutes', 'position'],
enrollments: ['progress_percent'],
lesson_progress: ['progress_percent'],
course_reviews: ['rating'],
quizzes: ['time_limit_minutes', 'pass_percent'],
quiz_questions: ['points', 'position'],
quiz_options: ['position'],
quiz_attempts: ['score_percent'],
"courses": [
"price",
],
"course_sections": [
"position",
],
"lessons": [
"duration_minutes",
"position",
],
"enrollments": [
"progress_percent",
],
"lesson_progress": [
"progress_percent",
],
"course_reviews": [
"rating",
],
"quizzes": [
"time_limit_minutes",
"pass_percent",
],
"quiz_questions": [
"points",
"position",
],
"quiz_options": [
"position",
],
"quiz_attempts": [
"score_percent",
],
"assignment_submissions": [
"grade_percent",
],
"pricing_plans": [
"price_monthly",
"price_yearly",
"sort_order",
],
"plan_features": [
"sort_order",
],
assignment_submissions: ['grade_percent'],
pricing_plans: ['price_monthly', 'price_yearly', 'sort_order'],
plan_features: ['sort_order'],
};
let allFoundRecords = [];
@ -441,44 +127,59 @@ module.exports = class SearchService {
const attributesIntToSearch = columnsInt[tableName] || [];
const whereCondition = {
[Op.or]: [
...attributesToSearch.map(attribute => ({
...attributesToSearch.map((attribute) => ({
[attribute]: {
[Op.iLike] : `%${searchQuery}%`,
[Op.iLike]: `%${searchQuery}%`,
},
})),
...attributesIntToSearch.map(attribute => (
...attributesIntToSearch.map((attribute) =>
Sequelize.where(
Sequelize.cast(Sequelize.col(`${tableName}.${attribute}`), 'varchar'),
{ [Op.iLike]: `%${searchQuery}%` }
)
)),
Sequelize.cast(
Sequelize.col(`${tableName}.${attribute}`),
'varchar',
),
{ [Op.iLike]: `%${searchQuery}%` },
),
),
],
};
const hasPermission = await checkPermissions(`READ_${tableName.toUpperCase()}`, currentUser);
const hasPermission = await checkPermissions(
`READ_${tableName.toUpperCase()}`,
currentUser,
);
if (!hasPermission) {
continue;
}
const foundRecords = await db[tableName].findAll({
where: whereCondition,
attributes: [...tableColumns[tableName], 'id', ...attributesIntToSearch],
attributes: [
...tableColumns[tableName],
'id',
...attributesIntToSearch,
],
});
const modifiedRecords = foundRecords.map((record) => {
const matchAttribute = [];
for (const attribute of attributesToSearch) {
if (record[attribute]?.toLowerCase()?.includes(searchQuery.toLowerCase())) {
if (
record[attribute]
?.toLowerCase()
?.includes(searchQuery.toLowerCase())
) {
matchAttribute.push(attribute);
}
}
for (const attribute of attributesIntToSearch) {
const castedValue = String(record[attribute]);
if (castedValue && castedValue.toLowerCase().includes(searchQuery.toLowerCase())) {
if (
castedValue &&
castedValue.toLowerCase().includes(searchQuery.toLowerCase())
) {
matchAttribute.push(attribute);
}
}
@ -499,4 +200,4 @@ module.exports = class SearchService {
throw error;
}
}
}
};

View File

@ -2,269 +2,230 @@ import dayjs from 'dayjs';
import _ from 'lodash';
export default {
filesFormatter(arr) {
if (!arr || !arr.length) return [];
return arr.map((item) => item);
},
imageFormatter(arr) {
if (!arr || !arr.length) return []
return arr.map(item => ({
publicUrl: item.publicUrl || ''
}))
},
oneImageFormatter(arr) {
if (!arr || !arr.length) return ''
return arr[0].publicUrl || ''
},
dateFormatter(date) {
if (!date) return ''
return dayjs(date).format('YYYY-MM-DD')
},
dateTimeFormatter(date) {
if (!date) return ''
return dayjs(date).format('YYYY-MM-DD HH:mm')
},
booleanFormatter(val) {
return val ? 'Yes' : 'No'
},
dataGridEditFormatter(obj) {
return _.transform(obj, (result, value, key) => {
if (_.isArray(value)) {
result[key] = _.map(value, 'id');
} else if (_.isObject(value)) {
result[key] = value.id;
} else {
result[key] = value;
}
});
},
filesFormatter(arr) {
if (!arr || !arr.length) return [];
return arr.map((item) => item);
},
imageFormatter(arr) {
if (!arr || !arr.length) return [];
return arr.map((item) => ({
publicUrl: item.publicUrl || '',
}));
},
oneImageFormatter(arr) {
if (!arr || !arr.length) return '';
return arr[0].publicUrl || '';
},
dateFormatter(date) {
if (!date) return '';
return dayjs(date).format('YYYY-MM-DD');
},
dateTimeFormatter(date) {
if (!date) return '';
return dayjs(date).format('YYYY-MM-DD HH:mm');
},
booleanFormatter(val) {
return val ? 'Yes' : 'No';
},
dataGridEditFormatter(obj) {
return _.transform(obj, (result, value, key) => {
if (_.isArray(value)) {
result[key] = _.map(value, 'id');
} else if (_.isObject(value)) {
result[key] = value.id;
} else {
result[key] = value;
}
});
},
rolesManyListFormatter(val) {
if (!val || !val.length) return [];
return val.map((item) => item.name);
},
rolesOneListFormatter(val) {
if (!val) return '';
return val.name;
},
rolesManyListFormatterEdit(val) {
if (!val || !val.length) return [];
return val.map((item) => {
return { id: item.id, label: item.name };
});
},
rolesOneListFormatterEdit(val) {
if (!val) return '';
return { label: val.name, id: val.id };
},
usersManyListFormatter(val) {
if (!val || !val.length) return []
return val.map((item) => item.firstName)
},
usersOneListFormatter(val) {
if (!val) return ''
return val.firstName
},
usersManyListFormatterEdit(val) {
if (!val || !val.length) return []
return val.map((item) => {
return {id: item.id, label: item.firstName}
});
},
usersOneListFormatterEdit(val) {
if (!val) return ''
return {label: val.firstName, id: val.id}
},
permissionsManyListFormatter(val) {
if (!val || !val.length) return [];
return val.map((item) => item.name);
},
permissionsOneListFormatter(val) {
if (!val) return '';
return val.name;
},
permissionsManyListFormatterEdit(val) {
if (!val || !val.length) return [];
return val.map((item) => {
return { id: item.id, label: item.name };
});
},
permissionsOneListFormatterEdit(val) {
if (!val) return '';
return { label: val.name, id: val.id };
},
coursesManyListFormatter(val) {
if (!val || !val.length) return [];
return val.map((item) => item.title);
},
coursesOneListFormatter(val) {
if (!val) return '';
return val.title;
},
coursesManyListFormatterEdit(val) {
if (!val || !val.length) return [];
return val.map((item) => {
return { id: item.id, label: item.title };
});
},
coursesOneListFormatterEdit(val) {
if (!val) return '';
return { label: val.title, id: val.id };
},
course_sectionsManyListFormatter(val) {
if (!val || !val.length) return [];
return val.map((item) => item.title);
},
course_sectionsOneListFormatter(val) {
if (!val) return '';
return val.title;
},
course_sectionsManyListFormatterEdit(val) {
if (!val || !val.length) return [];
return val.map((item) => {
return { id: item.id, label: item.title };
});
},
course_sectionsOneListFormatterEdit(val) {
if (!val) return '';
return { label: val.title, id: val.id };
},
rolesManyListFormatter(val) {
if (!val || !val.length) return []
return val.map((item) => item.name)
},
rolesOneListFormatter(val) {
if (!val) return ''
return val.name
},
rolesManyListFormatterEdit(val) {
if (!val || !val.length) return []
return val.map((item) => {
return {id: item.id, label: item.name}
});
},
rolesOneListFormatterEdit(val) {
if (!val) return ''
return {label: val.name, id: val.id}
},
lessonsManyListFormatter(val) {
if (!val || !val.length) return [];
return val.map((item) => item.title);
},
lessonsOneListFormatter(val) {
if (!val) return '';
return val.title;
},
lessonsManyListFormatterEdit(val) {
if (!val || !val.length) return [];
return val.map((item) => {
return { id: item.id, label: item.title };
});
},
lessonsOneListFormatterEdit(val) {
if (!val) return '';
return { label: val.title, id: val.id };
},
enrollmentsManyListFormatter(val) {
if (!val || !val.length) return [];
return val.map((item) => item.notes);
},
enrollmentsOneListFormatter(val) {
if (!val) return '';
return val.notes;
},
enrollmentsManyListFormatterEdit(val) {
if (!val || !val.length) return [];
return val.map((item) => {
return { id: item.id, label: item.notes };
});
},
enrollmentsOneListFormatterEdit(val) {
if (!val) return '';
return { label: val.notes, id: val.id };
},
quizzesManyListFormatter(val) {
if (!val || !val.length) return [];
return val.map((item) => item.title);
},
quizzesOneListFormatter(val) {
if (!val) return '';
return val.title;
},
quizzesManyListFormatterEdit(val) {
if (!val || !val.length) return [];
return val.map((item) => {
return { id: item.id, label: item.title };
});
},
quizzesOneListFormatterEdit(val) {
if (!val) return '';
return { label: val.title, id: val.id };
},
permissionsManyListFormatter(val) {
if (!val || !val.length) return []
return val.map((item) => item.name)
},
permissionsOneListFormatter(val) {
if (!val) return ''
return val.name
},
permissionsManyListFormatterEdit(val) {
if (!val || !val.length) return []
return val.map((item) => {
return {id: item.id, label: item.name}
});
},
permissionsOneListFormatterEdit(val) {
if (!val) return ''
return {label: val.name, id: val.id}
},
quiz_questionsManyListFormatter(val) {
if (!val || !val.length) return [];
return val.map((item) => item.prompt);
},
quiz_questionsOneListFormatter(val) {
if (!val) return '';
return val.prompt;
},
quiz_questionsManyListFormatterEdit(val) {
if (!val || !val.length) return [];
return val.map((item) => {
return { id: item.id, label: item.prompt };
});
},
quiz_questionsOneListFormatterEdit(val) {
if (!val) return '';
return { label: val.prompt, id: val.id };
},
plan_featuresManyListFormatter(val) {
if (!val || !val.length) return [];
return val.map((item) => item.name);
},
plan_featuresOneListFormatter(val) {
if (!val) return '';
return val.name;
},
plan_featuresManyListFormatterEdit(val) {
if (!val || !val.length) return [];
return val.map((item) => {
return { id: item.id, label: item.name };
});
},
plan_featuresOneListFormatterEdit(val) {
if (!val) return '';
return { label: val.name, id: val.id };
},
coursesManyListFormatter(val) {
if (!val || !val.length) return []
return val.map((item) => item.title)
},
coursesOneListFormatter(val) {
if (!val) return ''
return val.title
},
coursesManyListFormatterEdit(val) {
if (!val || !val.length) return []
return val.map((item) => {
return {id: item.id, label: item.title}
});
},
coursesOneListFormatterEdit(val) {
if (!val) return ''
return {label: val.title, id: val.id}
},
course_sectionsManyListFormatter(val) {
if (!val || !val.length) return []
return val.map((item) => item.title)
},
course_sectionsOneListFormatter(val) {
if (!val) return ''
return val.title
},
course_sectionsManyListFormatterEdit(val) {
if (!val || !val.length) return []
return val.map((item) => {
return {id: item.id, label: item.title}
});
},
course_sectionsOneListFormatterEdit(val) {
if (!val) return ''
return {label: val.title, id: val.id}
},
lessonsManyListFormatter(val) {
if (!val || !val.length) return []
return val.map((item) => item.title)
},
lessonsOneListFormatter(val) {
if (!val) return ''
return val.title
},
lessonsManyListFormatterEdit(val) {
if (!val || !val.length) return []
return val.map((item) => {
return {id: item.id, label: item.title}
});
},
lessonsOneListFormatterEdit(val) {
if (!val) return ''
return {label: val.title, id: val.id}
},
enrollmentsManyListFormatter(val) {
if (!val || !val.length) return []
return val.map((item) => item.notes)
},
enrollmentsOneListFormatter(val) {
if (!val) return ''
return val.notes
},
enrollmentsManyListFormatterEdit(val) {
if (!val || !val.length) return []
return val.map((item) => {
return {id: item.id, label: item.notes}
});
},
enrollmentsOneListFormatterEdit(val) {
if (!val) return ''
return {label: val.notes, id: val.id}
},
quizzesManyListFormatter(val) {
if (!val || !val.length) return []
return val.map((item) => item.title)
},
quizzesOneListFormatter(val) {
if (!val) return ''
return val.title
},
quizzesManyListFormatterEdit(val) {
if (!val || !val.length) return []
return val.map((item) => {
return {id: item.id, label: item.title}
});
},
quizzesOneListFormatterEdit(val) {
if (!val) return ''
return {label: val.title, id: val.id}
},
quiz_questionsManyListFormatter(val) {
if (!val || !val.length) return []
return val.map((item) => item.prompt)
},
quiz_questionsOneListFormatter(val) {
if (!val) return ''
return val.prompt
},
quiz_questionsManyListFormatterEdit(val) {
if (!val || !val.length) return []
return val.map((item) => {
return {id: item.id, label: item.prompt}
});
},
quiz_questionsOneListFormatterEdit(val) {
if (!val) return ''
return {label: val.prompt, id: val.id}
},
plan_featuresManyListFormatter(val) {
if (!val || !val.length) return []
return val.map((item) => item.name)
},
plan_featuresOneListFormatter(val) {
if (!val) return ''
return val.name
},
plan_featuresManyListFormatterEdit(val) {
if (!val || !val.length) return []
return val.map((item) => {
return {id: item.id, label: item.name}
});
},
plan_featuresOneListFormatterEdit(val) {
if (!val) return ''
return {label: val.name, id: val.id}
},
}
usersManyListFormatter(val) {
if (!val || !val.length) return [];
return val.map((item) => item.firstName);
},
usersOneListFormatter(val) {
if (!val) return '';
return val.firstName;
},
usersManyListFormatterEdit(val) {
if (!val || !val.length) return [];
return val.map((item) => {
return { id: item.id, label: item.firstName };
});
},
usersOneListFormatterEdit(val) {
if (!val) return '';
return { label: val.firstName, id: val.id };
},
};

View File

@ -1,5 +1,5 @@
import * as icon from '@mdi/js';
import { MenuAsideItem } from './interfaces'
import { MenuAsideItem } from './interfaces';
const menuAside: MenuAsideItem[] = [
{
@ -8,21 +8,13 @@ const menuAside: MenuAsideItem[] = [
label: 'Dashboard',
},
{
href: '/users/users-list',
label: 'Users',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiAccountGroup ?? icon.mdiTable,
permissions: 'READ_USERS'
},
{
href: '/roles/roles-list',
label: 'Roles',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiShieldAccountVariantOutline ?? icon.mdiTable,
permissions: 'READ_ROLES'
permissions: 'READ_ROLES',
},
{
href: '/permissions/permissions-list',
@ -30,135 +22,191 @@ const menuAside: MenuAsideItem[] = [
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiShieldAccountOutline ?? icon.mdiTable,
permissions: 'READ_PERMISSIONS'
permissions: 'READ_PERMISSIONS',
},
{
href: '/courses/courses-list',
label: 'Courses',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiSchool' in icon ? icon['mdiSchool' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_COURSES'
icon:
'mdiSchool' in icon
? icon['mdiSchool' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_COURSES',
},
{
href: '/course_sections/course_sections-list',
label: 'Course sections',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiViewList' in icon ? icon['mdiViewList' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_COURSE_SECTIONS'
icon:
'mdiViewList' in icon
? icon['mdiViewList' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_COURSE_SECTIONS',
},
{
href: '/lessons/lessons-list',
label: 'Lessons',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiPlayCircleOutline' in icon ? icon['mdiPlayCircleOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_LESSONS'
icon:
'mdiPlayCircleOutline' in icon
? icon['mdiPlayCircleOutline' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_LESSONS',
},
{
href: '/enrollments/enrollments-list',
label: 'Enrollments',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiAccountSchool' in icon ? icon['mdiAccountSchool' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_ENROLLMENTS'
icon:
'mdiAccountSchool' in icon
? icon['mdiAccountSchool' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_ENROLLMENTS',
},
{
href: '/lesson_progress/lesson_progress-list',
label: 'Lesson progress',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiProgressCheck' in icon ? icon['mdiProgressCheck' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_LESSON_PROGRESS'
icon:
'mdiProgressCheck' in icon
? icon['mdiProgressCheck' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_LESSON_PROGRESS',
},
{
href: '/course_reviews/course_reviews-list',
label: 'Course reviews',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiStarCircle' in icon ? icon['mdiStarCircle' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_COURSE_REVIEWS'
icon:
'mdiStarCircle' in icon
? icon['mdiStarCircle' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_COURSE_REVIEWS',
},
{
href: '/course_announcements/course_announcements-list',
label: 'Course announcements',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiBullhorn' in icon ? icon['mdiBullhorn' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_COURSE_ANNOUNCEMENTS'
icon:
'mdiBullhorn' in icon
? icon['mdiBullhorn' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_COURSE_ANNOUNCEMENTS',
},
{
href: '/quizzes/quizzes-list',
label: 'Quizzes',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiHelpCircleOutline' in icon ? icon['mdiHelpCircleOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_QUIZZES'
icon:
'mdiHelpCircleOutline' in icon
? icon['mdiHelpCircleOutline' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_QUIZZES',
},
{
href: '/quiz_questions/quiz_questions-list',
label: 'Quiz questions',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiOrderBoolAscendingVariant' in icon ? icon['mdiOrderBoolAscendingVariant' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_QUIZ_QUESTIONS'
icon:
'mdiOrderBoolAscendingVariant' in icon
? icon['mdiOrderBoolAscendingVariant' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_QUIZ_QUESTIONS',
},
{
href: '/quiz_options/quiz_options-list',
label: 'Quiz options',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiCheckboxMarkedCircleOutline' in icon ? icon['mdiCheckboxMarkedCircleOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_QUIZ_OPTIONS'
icon:
'mdiCheckboxMarkedCircleOutline' in icon
? icon['mdiCheckboxMarkedCircleOutline' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_QUIZ_OPTIONS',
},
{
href: '/quiz_attempts/quiz_attempts-list',
label: 'Quiz attempts',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiClipboardTextOutline' in icon ? icon['mdiClipboardTextOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_QUIZ_ATTEMPTS'
icon:
'mdiClipboardTextOutline' in icon
? icon['mdiClipboardTextOutline' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_QUIZ_ATTEMPTS',
},
{
href: '/assignment_submissions/assignment_submissions-list',
label: 'Assignment submissions',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiFileUploadOutline' in icon ? icon['mdiFileUploadOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_ASSIGNMENT_SUBMISSIONS'
icon:
'mdiFileUploadOutline' in icon
? icon['mdiFileUploadOutline' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_ASSIGNMENT_SUBMISSIONS',
},
{
href: '/marketing_pages/marketing_pages-list',
label: 'Marketing pages',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiWeb' in icon ? icon['mdiWeb' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_MARKETING_PAGES'
icon:
'mdiWeb' in icon
? icon['mdiWeb' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_MARKETING_PAGES',
},
{
href: '/contact_messages/contact_messages-list',
label: 'Contact messages',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiEmailOutline' in icon ? icon['mdiEmailOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_CONTACT_MESSAGES'
icon:
'mdiEmailOutline' in icon
? icon['mdiEmailOutline' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_CONTACT_MESSAGES',
},
{
href: '/pricing_plans/pricing_plans-list',
label: 'Pricing plans',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiCashMultiple' in icon ? icon['mdiCashMultiple' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_PRICING_PLANS'
icon:
'mdiCashMultiple' in icon
? icon['mdiCashMultiple' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_PRICING_PLANS',
},
{
href: '/plan_features/plan_features-list',
label: 'Plan features',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiChecklist' in icon ? icon['mdiChecklist' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_PLAN_FEATURES'
icon:
'mdiChecklist' in icon
? icon['mdiChecklist' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_PLAN_FEATURES',
},
{
href: '/users/users-list',
label: 'Users',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiAccountGroup ?? icon.mdiTable,
permissions: 'READ_USERS',
},
{
href: '/profile',
@ -166,14 +214,13 @@ const menuAside: MenuAsideItem[] = [
icon: icon.mdiAccountCircle,
},
{
href: '/api-docs',
target: '_blank',
label: 'Swagger API',
icon: icon.mdiFileCode,
permissions: 'READ_API_DOCS'
permissions: 'READ_API_DOCS',
},
]
];
export default menuAside
export default menuAside;

File diff suppressed because it is too large Load Diff

View File

@ -4,25 +4,25 @@ import mainReducer from './mainSlice';
import authSlice from './authSlice';
import openAiSlice from './openAiSlice';
import usersSlice from "./users/usersSlice";
import rolesSlice from "./roles/rolesSlice";
import permissionsSlice from "./permissions/permissionsSlice";
import coursesSlice from "./courses/coursesSlice";
import course_sectionsSlice from "./course_sections/course_sectionsSlice";
import lessonsSlice from "./lessons/lessonsSlice";
import enrollmentsSlice from "./enrollments/enrollmentsSlice";
import lesson_progressSlice from "./lesson_progress/lesson_progressSlice";
import course_reviewsSlice from "./course_reviews/course_reviewsSlice";
import course_announcementsSlice from "./course_announcements/course_announcementsSlice";
import quizzesSlice from "./quizzes/quizzesSlice";
import quiz_questionsSlice from "./quiz_questions/quiz_questionsSlice";
import quiz_optionsSlice from "./quiz_options/quiz_optionsSlice";
import quiz_attemptsSlice from "./quiz_attempts/quiz_attemptsSlice";
import assignment_submissionsSlice from "./assignment_submissions/assignment_submissionsSlice";
import marketing_pagesSlice from "./marketing_pages/marketing_pagesSlice";
import contact_messagesSlice from "./contact_messages/contact_messagesSlice";
import pricing_plansSlice from "./pricing_plans/pricing_plansSlice";
import plan_featuresSlice from "./plan_features/plan_featuresSlice";
import rolesSlice from './roles/rolesSlice';
import permissionsSlice from './permissions/permissionsSlice';
import coursesSlice from './courses/coursesSlice';
import course_sectionsSlice from './course_sections/course_sectionsSlice';
import lessonsSlice from './lessons/lessonsSlice';
import enrollmentsSlice from './enrollments/enrollmentsSlice';
import lesson_progressSlice from './lesson_progress/lesson_progressSlice';
import course_reviewsSlice from './course_reviews/course_reviewsSlice';
import course_announcementsSlice from './course_announcements/course_announcementsSlice';
import quizzesSlice from './quizzes/quizzesSlice';
import quiz_questionsSlice from './quiz_questions/quiz_questionsSlice';
import quiz_optionsSlice from './quiz_options/quiz_optionsSlice';
import quiz_attemptsSlice from './quiz_attempts/quiz_attemptsSlice';
import assignment_submissionsSlice from './assignment_submissions/assignment_submissionsSlice';
import marketing_pagesSlice from './marketing_pages/marketing_pagesSlice';
import contact_messagesSlice from './contact_messages/contact_messagesSlice';
import pricing_plansSlice from './pricing_plans/pricing_plansSlice';
import plan_featuresSlice from './plan_features/plan_featuresSlice';
import usersSlice from './users/usersSlice';
export const store = configureStore({
reducer: {
@ -31,29 +31,29 @@ export const store = configureStore({
auth: authSlice,
openAi: openAiSlice,
users: usersSlice,
roles: rolesSlice,
permissions: permissionsSlice,
courses: coursesSlice,
course_sections: course_sectionsSlice,
lessons: lessonsSlice,
enrollments: enrollmentsSlice,
lesson_progress: lesson_progressSlice,
course_reviews: course_reviewsSlice,
course_announcements: course_announcementsSlice,
quizzes: quizzesSlice,
quiz_questions: quiz_questionsSlice,
quiz_options: quiz_optionsSlice,
quiz_attempts: quiz_attemptsSlice,
assignment_submissions: assignment_submissionsSlice,
marketing_pages: marketing_pagesSlice,
contact_messages: contact_messagesSlice,
pricing_plans: pricing_plansSlice,
plan_features: plan_featuresSlice,
roles: rolesSlice,
permissions: permissionsSlice,
courses: coursesSlice,
course_sections: course_sectionsSlice,
lessons: lessonsSlice,
enrollments: enrollmentsSlice,
lesson_progress: lesson_progressSlice,
course_reviews: course_reviewsSlice,
course_announcements: course_announcementsSlice,
quizzes: quizzesSlice,
quiz_questions: quiz_questionsSlice,
quiz_options: quiz_optionsSlice,
quiz_attempts: quiz_attemptsSlice,
assignment_submissions: assignment_submissionsSlice,
marketing_pages: marketing_pagesSlice,
contact_messages: contact_messagesSlice,
pricing_plans: pricing_plansSlice,
plan_features: plan_featuresSlice,
users: usersSlice,
},
})
});
// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
export type RootState = ReturnType<typeof store.getState>;
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch
export type AppDispatch = typeof store.dispatch;