Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integration python microservice flask #134

Merged
merged 9 commits into from
Nov 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added node_modules/career-model/model.pkl
Binary file not shown.
96 changes: 96 additions & 0 deletions node_modules/career-model/predict.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions node_modules/career-model/requirements.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

112 changes: 112 additions & 0 deletions public/src/client/career.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
'use strict';

define('forum/career', [
'translator', 'jquery-form',
], function (translator) {
const Career = {};
let validationError = false;

Career.init = function () {
const student_id = $('#student_id');
const age = $('#age');
const gpa = $('#gpa');
const num_programming_languages = $('#num_programming_languages');
const num_past_internships = $('#num_past_internships');
const signup = $('#signup');

function validateForm(callback) {
validationError = false;
validateNonEmpty(student_id.val(), $('#student-id-notify'));
validateRangedInt(age.val(), $('#age-notify'), 18, 25);
validateRangedFloat(gpa.val(), $('#gpa-notify'), 0.0, 4.0);
validateRangedInt(num_programming_languages.val(), $('#num-programming-languages-notify'), 1, 5);
validateRangedInt(num_past_internships.val(), $('#num-past-internships-notify'), 0, 4);
callback();
}

signup.on('click', function (e) {
const registerBtn = $(this);
const errorEl = $('#career-error-notify');
errorEl.addClass('hidden');
e.preventDefault();
validateForm(function () {
if (validationError) {
return;
}

registerBtn.addClass('disabled');

registerBtn.parents('form').ajaxSubmit({
headers: {
'x-csrf-token': config.csrf_token,
},
success: function () {
location.reload();
},
error: function (data) {
translator.translate(data.responseText, config.defaultLang, function (translated) {
if (data.status === 403 && data.responseText === 'Forbidden') {
window.location.href = config.relative_path + '/career?error=csrf-invalid';
} else {
errorEl.find('p').text(translated);
errorEl.removeClass('hidden');
registerBtn.removeClass('disabled');
}
});
},
});
});
});
};

function validateNonEmpty(value, value_notify) {
if (!value || value.length === 0) {
showError(value_notify, 'Must be non-empty');
} else {
showSuccess(value_notify);
}
}

function validateRangedInt(value, value_notify, min_val, max_val) {
if (!value || isNaN(value)) {
showError(value_notify, `Must be a valid integer`);
} else if (parseInt(value, 10) < min_val || parseInt(value, 10) > max_val) {
showError(value_notify, `Must be within the range [${min_val}, ${max_val}]`);
} else {
showSuccess(value_notify);
}
}

function validateRangedFloat(value, value_notify, min_val, max_val) {
if (!value || isNaN(value)) {
showError(value_notify, `Must be a valid floating point value`);
} else if (parseFloat(value) < min_val || parseFloat(value) > max_val) {
showError(value_notify, `Must be within the range [${min_val}, ${max_val}]`);
} else {
showSuccess(value_notify);
}
}

function showError(element, msg) {
translator.translate(msg, function (msg) {
element.html(msg);
element.parent()
.removeClass('register-success')
.addClass('register-danger');
element.show();
});
validationError = true;
}

function showSuccess(element, msg) {
translator.translate(msg, function (msg) {
element.html(msg);
element.parent()
.removeClass('register-danger')
.addClass('register-success');
element.show();
});
}

return Career;
});
11 changes: 11 additions & 0 deletions public/src/modules/helpers.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ module.exports = function (utils, Benchpress, relative_path) {
userAgentIcons,
buildAvatar,
register,
getPredictionColor,
formatPrediction,
__escape: identity,
};

Expand Down Expand Up @@ -336,6 +338,15 @@ module.exports = function (utils, Benchpress, relative_path) {
styles.push('background-color: ' + userObj['icon:bgColor'] + ';');
return '<span ' + attributes.join(' ') + ' style="' + styles.join(' ') + '">' + userObj['icon:text'] + '</span>';
}
function getPredictionColor(prediction) {
if (prediction === 1) { return `"background-color: rgb(0, 255, 0);"`; }
return `"background-color: rgb(255, 0, 0);"`;
}

function formatPrediction(prediction) {
return prediction;
}


function register() {
Object.keys(helpers).forEach(function (helperName) {
Expand Down
5 changes: 1 addition & 4 deletions src/controllers/authentication.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,9 @@ authenticationController.register = async function (req, res) {
if (userData.password.length > 512) {
throw new Error('[[error:password-too-long]]');
}

if (!userData['account-type'] ||
(userData['account-type'] !== 'student' && userData['account-type'] !== 'instructor')) {
if (!userData['account-type'] || (userData['account-type'] !== 'student' && userData['account-type'] !== 'instructor' && userData['account-type'] !== 'recruiter')) {
throw new Error('Invalid account type');
}

user.isPasswordValid(userData.password);

res.locals.processLogin = true; // set it to false in plugin if you wish to just register only
Expand Down
8 changes: 0 additions & 8 deletions src/controllers/career.js

This file was deleted.

28 changes: 28 additions & 0 deletions src/controllers/careers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict';

const user = require('../user');
const helpers = require('./helpers');

const careerController = module.exports;

careerController.get = async function (req, res) {
const userData = await user.getUserFields(req.uid, ['accounttype']);

const accountType = userData.accounttype;
let careerData = {};

if (accountType === 'recruiter') {
careerData.allData = await user.getAllCareerData();
} else {
const userCareerData = await user.getCareerData(req.uid);
if (userCareerData) {
careerData = userCareerData;
} else {
careerData.newAccount = true;
}
}

careerData.accountType = accountType;
careerData.breadcrumbs = helpers.buildBreadcrumbs([{ text: 'Career', url: '/career' }]);
res.render('career', careerData);
};
3 changes: 2 additions & 1 deletion src/controllers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Controllers.ping = require('./ping');
Controllers.home = require('./home');
Controllers.topics = require('./topics');
Controllers.posts = require('./posts');
Controllers.career = require('./career');
Controllers.careers = require('./careers');
Controllers.categories = require('./categories');
Controllers.category = require('./category');
Controllers.unread = require('./unread');
Expand Down Expand Up @@ -188,6 +188,7 @@ Controllers.register = async function (req, res, next) {
<select class="form-control" name="account-type" aria-label="Account Type">
<option value="student" selected>Student</option>
<option value="instructor">Instructor</option>
<option value="recruiter">Recruiter</option>
</select>
`,
},
Expand Down
54 changes: 54 additions & 0 deletions src/controllers/write/career.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use strict';

const helpers = require('../helpers');
const user = require('../../user');
const db = require('../../database');

const Career = module.exports;
Career.register = async function (req, res) {
const userData = req.query;
try {
// Forward the request to the Flask application
// console.log(userData.student_id);
const flaskResponse = await fetch('http://127.0.0.1:5000/predict', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
// Include any other necessary headers
},
body: JSON.stringify({
student_id: userData.student_id,
major: userData.major,
age: userData.age,
gender: userData.gender,
gpa: userData.gpa,
extra_curricular: userData.extra_curricular,
num_programming_languages: userData.num_programming_languages,
num_past_internships: userData.num_past_internships,
}),
});

const userCareerData = {
student_id: userData.student_id,
major: userData.major,
age: userData.age,
gender: userData.gender,
gpa: userData.gpa,
extra_curricular: userData.extra_curricular,
num_programming_languages: userData.num_programming_languages,
num_past_internships: userData.num_past_internships,
};
if (!flaskResponse.ok) {
throw new Error('Failed to get prediction from Flask app.');
}
const predictionResult = await flaskResponse.json();
console.log(predictionResult);
userCareerData.prediction = predictionResult.good_employee;
await user.setCareerData(req.uid, userCareerData);
db.sortedSetAdd('users:career', req.uid, req.uid);
res.json({});
} catch (err) {
console.log(err);
helpers.noScriptErrors(req, res, err.message, 400);
}
};
Loading