diff --git a/services/web/app/src/Features/Project/ProjectController.js b/services/web/app/src/Features/Project/ProjectController.js index 2d85ca40ce..3f2e7ce064 100644 --- a/services/web/app/src/Features/Project/ProjectController.js +++ b/services/web/app/src/Features/Project/ProjectController.js @@ -437,7 +437,7 @@ const ProjectController = { ) User.findById( userId, - 'email first_name last_name referal_id signUpDate featureSwitches features featuresEpoch refProviders alphaProgram betaProgram isAdmin ace labsProgram', + 'email first_name last_name referal_id signUpDate featureSwitches features featuresEpoch refProviders alphaProgram betaProgram isAdmin ace labsProgram completedTutorials', (err, user) => { // Handle case of deleted user if (user == null) { @@ -877,6 +877,7 @@ const ProjectController = { alphaProgram: user.alphaProgram, betaProgram: user.betaProgram, labsProgram: user.labsProgram, + completedTutorials: user.completedTutorials, isAdmin: hasAdminAccess(user), }, userSettings: { diff --git a/services/web/app/src/Features/Tutorial/TutorialController.js b/services/web/app/src/Features/Tutorial/TutorialController.js new file mode 100644 index 0000000000..876722404e --- /dev/null +++ b/services/web/app/src/Features/Tutorial/TutorialController.js @@ -0,0 +1,21 @@ +const SessionManager = require('../Authentication/SessionManager') +const TutorialHandler = require('./TutorialHandler') +const { expressify } = require('../../util/promises') + +const VALID_KEYS = ['react-history-buttons-tutorial'] + +async function completeTutorial(req, res, next) { + const userId = SessionManager.getLoggedInUserId(req.session) + const tutorialKey = req.params.tutorialKey + + if (!VALID_KEYS.includes(tutorialKey)) { + return res.sendStatus(400) + } + + await TutorialHandler.saveCompletion(userId, tutorialKey) + res.sendStatus(204) +} + +module.exports = { + completeTutorial: expressify(completeTutorial), +} diff --git a/services/web/app/src/Features/Tutorial/TutorialHandler.js b/services/web/app/src/Features/Tutorial/TutorialHandler.js new file mode 100644 index 0000000000..ceab01dada --- /dev/null +++ b/services/web/app/src/Features/Tutorial/TutorialHandler.js @@ -0,0 +1,13 @@ +const UserUpdater = require('../User/UserUpdater') + +async function saveCompletion(userId, tutorialKey) { + const completionDate = new Date() + + await UserUpdater.promises.updateUser(userId, { + $set: { + [`completedTutorials.${tutorialKey}`]: completionDate, + }, + }) +} + +module.exports = { saveCompletion } diff --git a/services/web/app/src/models/User.js b/services/web/app/src/models/User.js index d5fd4d8eb4..826a57d566 100644 --- a/services/web/app/src/models/User.js +++ b/services/web/app/src/models/User.js @@ -187,6 +187,7 @@ const UserSchema = new Schema( splitTests: Schema.Types.Mixed, analyticsId: { type: String }, surveyResponses: Schema.Types.Mixed, + completedTutorials: Schema.Types.Mixed, }, { minimize: false } ) diff --git a/services/web/app/src/router.js b/services/web/app/src/router.js index 624ee610b2..90739bc5e3 100644 --- a/services/web/app/src/router.js +++ b/services/web/app/src/router.js @@ -21,6 +21,7 @@ const UserInfoController = require('./Features/User/UserInfoController') const UserController = require('./Features/User/UserController') const UserEmailsController = require('./Features/User/UserEmailsController') const UserPagesController = require('./Features/User/UserPagesController') +const TutorialController = require('./Features/Tutorial/TutorialController') const DocumentController = require('./Features/Documents/DocumentController') const CompileManager = require('./Features/Compile/CompileManager') const CompileController = require('./Features/Compile/CompileController') @@ -427,6 +428,12 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) { TpdsController.getQueues ) + webRouter.post( + '/tutorial/:tutorialKey/complete', + AuthenticationController.requireLogin(), + TutorialController.completeTutorial + ) + webRouter.get( '/user/projects', AuthenticationController.requireLogin(),