Skip to content

Commit

Permalink
Merge pull request #538 from bluewave-labs/535-tour-url-services
Browse files Browse the repository at this point in the history
535 tour url services
  • Loading branch information
DeboraSerra authored Feb 13, 2025
2 parents 3adf9a3 + 0c44e9d commit 4b2dd50
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 75 deletions.
118 changes: 59 additions & 59 deletions backend/src/controllers/guide.controller.js
Original file line number Diff line number Diff line change
@@ -1,72 +1,72 @@
const bannerService = require("../service/banner.service");
const guidelogService = require("../service/guidelog.service");
const helperLinkService = require("../service/helperLink.service");
const popupService = require("../service/popup.service");
const hintService = require("../service/hint.service");
const { internalServerError } = require("../utils/errors.helper");
const bannerService = require('../service/banner.service');
const guidelogService = require('../service/guidelog.service');
const helperLinkService = require('../service/helperLink.service');
const popupService = require('../service/popup.service');
const hintService = require('../service/hint.service');
const { internalServerError } = require('../utils/errors.helper');
const tourService = require('../service/tour.service');

class GuideController {
async getGuidesByUrl(req, res) {
try {
const { url } = req.body;
async getGuidesByUrl(req, res) {
try {
const { url } = req.body;

if (!url || typeof url !== 'string') {
return res.status(400).json({ errors: [{ msg: "URL is missing or invalid" }] });
}
const [banner, popup, hint, helperLink] = await Promise.all([
bannerService.getBannerByUrl(url),
popupService.getPopupByUrl(url),
hintService.getHintByUrl(url),
helperLinkService.getAllHelpersWithLinks(),
]);
res.status(200).json({ banner, popup, hint, helperLink });
} catch (error) {
internalServerError(
"GET_GUIDES_BY_URL_ERROR",
error.message,
);
}
if (!url || typeof url !== 'string') {
return res.status(400).json({ errors: [{ msg: 'URL is missing or invalid' }] });
}
const [banner, popup, hint, helperLink, tour] = await Promise.all([
bannerService.getBannerByUrl(url),
popupService.getPopupByUrl(url),
hintService.getHintByUrl(url),
helperLinkService.getAllHelpersWithLinks(),
tourService.getTourByUrl(url),
]);
res.status(200).json({ banner, popup, hint, helperLink, tour });
} catch (error) {
const { payload, statusCode } = internalServerError('GET_GUIDES_BY_URL_ERROR', error.message);
res.status(statusCode).json(payload);
}
}

async getIncompleteGuidesByUrl(req, res) {
try {
const { url, userId } = req.body;
async getIncompleteGuidesByUrl(req, res) {
try {
const { url, userId } = req.body;

if (!url || typeof url !== 'string') {
return res.status(400).json({ errors: [{ msg: "URL is missing or invalid" }] });
}
if (!userId || typeof userId !== 'string') {
return res.status(400).json({ errors: [{ msg: "userId is missing or invalid" }] });
}
if (!url || typeof url !== 'string') {
return res.status(400).json({ errors: [{ msg: 'URL is missing or invalid' }] });
}
if (!userId || typeof userId !== 'string') {
return res.status(400).json({ errors: [{ msg: 'userId is missing or invalid' }] });
}

const [completePopupLogs, completeBannerLogs, completeHintLogs, completeHelperLogs] = await Promise.all([
guidelogService.getCompletePopupLogs(userId),
guidelogService.getCompleteBannerLogs(userId),
guidelogService.getCompleteHintLogs(userId),
guidelogService.getCompleteHelperLogs(userId),
]);
const [completePopupLogs, completeBannerLogs, completeHintLogs, completeHelperLogs, completeTourLogs] =
await Promise.all([
guidelogService.getCompletePopupLogs(userId),
guidelogService.getCompleteBannerLogs(userId),
guidelogService.getCompleteHintLogs(userId),
guidelogService.getCompleteHelperLogs(userId),
guidelogService.getCompleteToursLogs(userId),
]);

const popupIds = completePopupLogs.map(log => log.guideId);
const bannerIds = completeBannerLogs.map(log => log.guideId);
const hintIds = completeHintLogs.map(log => log.guideId);
//const helperLinkIds = completeHelperLogs.map(log => log.guideId);
const popupIds = completePopupLogs.map((log) => log.guideId);
const bannerIds = completeBannerLogs.map((log) => log.guideId);
const hintIds = completeHintLogs.map((log) => log.guideId);
//const helperLinkIds = completeHelperLogs.map(log => log.guideId);
const tourIds = completeTourLogs.map((log) => log.guideId);

const [popup, banner, hint, helperLink] = await Promise.all([
popupService.getIncompletePopupsByUrl(url, popupIds),
bannerService.getIncompleteBannersByUrl(url, bannerIds),
hintService.getIncompleteHintsByUrl(url, hintIds),
//helperLinkService.getIncompleteHelpers(helperLinkIds),
helperLinkService.getAllHelpersWithLinks()
]);
res.status(200).json({popup, banner, hint, helperLink });

} catch (error) {
internalServerError(
"GET_INCOMPLETE_GUIDES_BY_URL_ERROR",
error.message,
);
}
const [popup, banner, hint, helperLink, tour] = await Promise.all([
popupService.getIncompletePopupsByUrl(url, popupIds),
bannerService.getIncompleteBannersByUrl(url, bannerIds),
hintService.getIncompleteHintsByUrl(url, hintIds),
//helperLinkService.getIncompleteHelpers(helperLinkIds),
helperLinkService.getAllHelpersWithLinks(),
tourService.getIncompleteTourByUrl(url, tourIds),
]);
res.status(200).json({ popup, banner, hint, helperLink, tour });
} catch (error) {
internalServerError('GET_INCOMPLETE_GUIDES_BY_URL_ERROR', error.message);
}
}
}

module.exports = new GuideController();
11 changes: 11 additions & 0 deletions backend/src/controllers/tour.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ class TourController {
}
}

async getTourByUrl(req, res) {
try {
const { url } = req.body;
const tours = await TourService.getTourByUrl(url);
res.status(200).json(tours);
} catch (err) {
const { statusCode, payload } = internalServerError('GET_TOUR_BY_URL_ERROR', err.message);
res.status(statusCode).json(payload);
}
}

async createTour(req, res) {
try {
const userId = req.user.id;
Expand Down
2 changes: 1 addition & 1 deletion backend/src/models/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ db.Link.belongsTo(db.HelperLink, { foreignKey: "helperId", as: "helper" });
db.User.hasMany(db.Banner, { foreignKey: "createdBy", as: "banners" });
db.Banner.belongsTo(db.User, { foreignKey: "createdBy", as: "creator" });

db.Tour.hasMany(db.TourPopup, { foreignKey: "tourId", as: "popups" });
db.Tour.hasMany(db.TourPopup, { foreignKey: "tourId", as: "steps" });
db.TourPopup.belongsTo(db.Tour, { foreignKey: "tourId", as: "tour" });

db.Invite.belongsTo(db.User, { foreignKey: "invitedBy" });
Expand Down
4 changes: 2 additions & 2 deletions backend/src/routes/tour.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ const tourController = require('../controllers/tour.controller');
const authenticateJWT = require('../middleware/auth.middleware');
const settings = require('../../config/settings');
const accessGuard = require('../middleware/accessGuard.middleware');
const { tourValidator, paramsIdValidator } = require('../utils/tour.helper');
const { tourValidator, paramsIdValidator, bodyUrlValidator } = require('../utils/tour.helper');
const { handleValidationErrors } = require('../middleware/validation.middleware');

const router = express.Router();
const teamPermissions = settings.team.permissions.tours;

// router.get("/get_tour_by_url", tourController.getTourByUrl);
router.get('/get_tour_by_url', bodyUrlValidator, handleValidationErrors, tourController.getTourByUrl);

router.use(authenticateJWT);

Expand Down
40 changes: 28 additions & 12 deletions backend/src/service/guidelog.service.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
const db = require("../models");
const db = require('../models');
const GuideLog = db.GuideLog;
const { GuideType } = require('../utils/guidelog.helper');

class GuideLogService {
async addGuideLog({ guideType, userId, guideId, completed }) {
const transaction = await db.sequelize.transaction();
try {
const log = await GuideLog.create({
guideType,
userId,
guideId,
showingTime: new Date(),
completed
}, { transaction });
const log = await GuideLog.create(
{
guideType,
userId,
guideId,
showingTime: new Date(),
completed,
},
{ transaction }
);
await transaction.commit();
return log;
} catch (err) {
Expand All @@ -30,7 +33,7 @@ class GuideLogService {
where: {
userId: userId,
completed: true,
guideType: GuideType.BANNER
guideType: GuideType.BANNER,
},
});
} catch (err) {
Expand All @@ -44,7 +47,7 @@ class GuideLogService {
where: {
userId: userId,
completed: true,
guideType: GuideType.POPUP
guideType: GuideType.POPUP,
},
});
} catch (err) {
Expand All @@ -57,7 +60,7 @@ class GuideLogService {
where: {
userId: userId,
completed: true,
guideType: GuideType.HINT
guideType: GuideType.HINT,
},
});
} catch (err) {
Expand All @@ -71,14 +74,27 @@ class GuideLogService {
where: {
userId: userId,
completed: true,
guideType: GuideType.LINK
guideType: GuideType.LINK,
},
});
} catch (err) {
throw new Error(`Failed to retrieve helper link log for user ${userId}: ${err.message}`);
}
}

async getCompleteToursLogs(userId) {
try {
return await GuideLog.findAll({
where: {
userId: userId,
completed: true,
guideType: GuideType.TOUR,
},
});
} catch (err) {
throw new Error(`Failed to retrieve tour log for user ${userId}: ${err.message}`);
}
}

async getCompleteGuideLogs(userId) {
try {
Expand Down
38 changes: 37 additions & 1 deletion backend/src/service/tour.service.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const db = require('../models');
const { Op } = require('sequelize');

const Tour = db.Tour;
const TourPopup = db.TourPopup;
Expand All @@ -20,6 +21,41 @@ class TourService {
});
}

async getTourByUrl(url) {
try {
return await Tour.findAll({
where: {
[Op.and]: [{ url }, { active: true }],
},
include: [
{
model: db.TourPopup,
as: 'steps',
},
],
});
} catch (err) {
console.log(err);
throw new Error('Error finding tour by url');
}
}

async getIncompleteTourByUrl(url, ids) {
try {
return await Tour.findAll({
where: {
url,
id: {
[Op.notIn]: ids,
},
},
});
} catch (err) {
console.log(err);
throw new Error('Error finding incomplete tours by url');
}
}

async createTour(data) {
const { steps, ...info } = data;
const transaction = await db.sequelize.transaction();
Expand Down Expand Up @@ -55,7 +91,7 @@ class TourService {
});
if (affectedRows === 0) {
await transaction.commit();
return null
return null;
}
await TourPopup.destroy({ where: { tourId: id }, transaction });
const formattedSteps = steps.map((step) => ({
Expand Down
5 changes: 5 additions & 0 deletions backend/src/utils/tour.helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,14 @@ const tourValidator = [

const paramsIdValidator = [param('id').isInt().withMessage('Invalid value for id')];

const bodyUrlValidator = [
body('url').isString().withMessage('url is required').custom(validateUrl).withMessage('Invalid value for url'),
];

module.exports = {
URL_REGEX,
validateUrl,
tourValidator,
paramsIdValidator,
bodyUrlValidator,
};

0 comments on commit 4b2dd50

Please sign in to comment.