Source

API/src/controllers/downloadableresources.controllers.js

/**
 * @category Backend API
 * @subcategory Controllers
 * @module DownloadableResources Controller
 * 
 * @description Controller for downloadable resources, including text materials and videos </br>
 * 
 * The following routes are handled here: </br>
 * 
 * </br
 * 
 * <b>POST</b> /downloadableresource/new </br> 
 * <b>POST</b> /downloadableresource/upload </br>
 * <b>PATCH</b> /downloadableresource/update/:id </br>
 * <b>DELETE</b> /downloadableresource/delete/:id </br>
 */

const { DownloadableResource, TextMaterial, Video, Course } = require('../models/course.models');
const { uploadToCloudinary } = require('../utils/cloudinary');
const fs = require('fs');
const { BadRequestError, NotFoundError } = require('../utils/errors');
const { translateDoc } = require('../utils/crowdin');

/**
 * Get all downloadable resources
 * 
 * @description This function is used to get all downloadable resources
 * 
 * @param {String} id - The course id
 * @param {Request} req - Express request object
 * @param {Response} res - Express response object
 * @param {NextFunction} next - Express next function
 * 
 * @returns {Object} - The downloadable resources
 */
exports.getDownloadableResources = async (req, res, next) => {
    const { textmaterial_id, video_id, course_id } = req.query;

    let downloadable_resources;

    // Check if textmaterial_id is provided
    if (textmaterial_id && textmaterial_id != null && textmaterial_id != undefined) {
        const text_material = await TextMaterial.findById(textmaterial_id);
        if (!text_material) { return next(new NotFoundError('Text material not found')); }
        downloadable_resources = await DownloadableResource.find({ textmaterial: textmaterial_id });
    }

    if (course_id && course_id != null && course_id != undefined) {
        const course = await Course.findById(course_id);
        if (!course) { return next(new NotFoundError('Course not found')); }
        downloadable_resources = await DownloadableResource.find({ video: video_id });
    }

    if (video_id && video_id != null && video_id != undefined) {
        const video = await Video.findById(video_id);
        if (!video) { return next(new NotFoundError('Video not found')); }
        downloadable_resources = await DownloadableResource.find({ video: video_id });
    }

    res.status(200).json({
        status: 'success',
        data: {
            downloadable_resources
        }
    })
}

/**
 * Get downloadable resource data
 * 
 * @description This function is used to get downloadable resource data
 * 
 * @param {String} id - The resource id
 * @param {Request} req - Express request object
 * @param {Response} res - Express response object
 * @param {NextFunction} next - Express next function
 * 
 * @returns {Object} - The resource data
 */
exports.getDownloadableResourceData = async (req, res, next) => {
    const { id } = req.params;

    // Check if id is provided
    if (!id || id == null || id == undefined) {
        return next(new BadRequestError('Resource id is required'));
    }

    const downloadable_resource = await DownloadableResource.findById(id);
    if (!downloadable_resource) {
        return next(new NotFoundError('Resource not found'));
    }

    res.status(200).json({
        status: 'success',
        data: {
            downloadable_resource
        }
    })
}

/**
 * Delete downloadable resource
 * 
 * @description This function is used to delete downloadable resource
 * 
 * @param {String} id - The resource id
 * 
 * @returns {Object} - The deleted resource
 */
exports.deleteDownloadableResource = async (req, res, next) => {
    const { id } = req.params;

    // Check if id is provided
    if (!id || id == null || id == undefined) {
        return next(new BadRequestError('Resource id is required'));
    }

    const downloadable_resource = await DownloadableResource.findById(id);
    if (!downloadable_resource) {
        return next(new NotFoundError('Resource not found'));
    }

    await downloadable_resource.remove();


    res.status(200).json({
        status: 'success',
        data: {
            downloadable_resource
        }
    })
}

/**
 * Update downloadable resource
 * 
 * @description This function is used to update downloadable resource.
 * The user can update the title, description and file url
 * 
 * @param {String} id - The resource id
 * 
 * @returns {Object} - The updated resource
 */
exports.updateDownloadableResource = async (req, res, next) => {
    const { id } = req.params;

    if (!id || id == null || id == undefined) {
        return next(new BadRequestError('Resource id is required'));
    }

    const downloadable_resource = await DownloadableResource.findByIdAndUpdate(
        id,
        { $set: req.body },
        { new: true });

    if (!downloadable_resource) {
        return next(new NotFoundError('Resource not found'));
    }

    const updated_downloadable_resource = await translateDoc(downloadable_resource)

    res.status(200).json({
        status: 'success',
        data: {
            updated_resource: updated_downloadable_resource
        }
    })
}

/**
 * Upload downloadable resource
 * 
 * @description This function is used to upload downloadable resource.
 * This is used when the user wants to upload a file to the server
 * 
 * @param {String} id - The course id
 * @param {String} title - The title of the resource
 * @param {String} description - The description of the resource
 * @param {String} file - The file to be uploaded
 * 
 * @returns {Object} - The uploaded resource
 */
exports.uploadDownloadableResource = async (req, res, next) => {
    const { title, description, course_id, resource_type, video_id, text_material_id } = req.body;
    console.log(req.body)
    let video, textmaterial;
    if (video_id) {
        video = await Video.findById(video_id);
        if (!video) {
            return next(new NotFoundError('Video not found'));
        }
    } else if (text_material_id) {
        textmaterial = await TextMaterial.findById(text_material_id);
        if (!textmaterial) {
            return next(new NotFoundError('Text material not found'));
        }
    } else if (!course_id) { return next(new BadRequestError('Missing required params in request body')); }

    console.log(textmaterial, video)

    let downloadable_resource = new DownloadableResource({
        title,
        description,
        course: course_id || textmaterial?.course || video?.course,
        textmaterial: textmaterial?._id,
        video: video?._id,
        resource_type
    });

    const file_url = await uploadToCloudinary({
        path: req.file.path,
        file_name: `${downloadable_resource._id}_${req.file.filename}`,
        destination_path: `courses/${course_id}/downloadable_resources`
    });

    // Delete the file from the server
    await fs.unlinkSync(req.file.path, (err) => {
        if (err) {
            console.log(err);
        }
    });

    downloadable_resource.file_url = file_url;
    downloadable_resource = await downloadable_resource.save();

    res.status(200).json({
        status: 'success',
        data: {
            downloadable_resource
        }
    })
}

/**
 * Create downloadable resource
 * 
 * @description This function is used to create downloadable resource.
 * This is used when the user wants to create a resource with a url to the file
 * 
 * @param {String} course_id - The course id
 * @param {String} title - The title of the resource
 * @param {String} description - The description of the resource
 * @param {String} file_url - The url to the file
 *  
 * @returns {Object} - The created resource
 */
exports.createDownloadableResource = async (req, res, next) => {
    const { title, description, file_url, course_id, video_id, text_material_id, resource_type } = req.body;

    let video, textmaterial;
    if (video_id) {
        video = await Video.findById(video_id);
        if (!video) {
            return next(new NotFoundError('Video not found'));
        }
    } else if (text_material_id) {
        textmaterial = await TextMaterial.findById(text_material_id);
        if (!textmaterial) {
            return next(new NotFoundError('Text material not found'));
        }
    } else if (!course_id) { return next(new BadRequestError('Missing required params in request body')); }

    console.log(textmaterial, video)

    let downloadable_resource = new DownloadableResource({
        title,
        description,
        course: course_id || textmaterial?.course || video?.course,
        textmaterial: textmaterial?._id,
        video: video?._id,
        resource_type,
        file_url
    });

    downloadable_resource = await downloadable_resource.save();

    res.status(200).json({
        status: 'success',
        data: {
            downloadable_resource
        }
    })
}