Hints per lesson (#314)

Squashing and merging ...

* Each assigment should have the options to have its own set of hints #278

* Updating lessons due to changes from #278

* Enable i18n client side #312

* IDOR move hints to assignment and enable i18n #312
This commit is contained in:
Nanne Baars
2017-01-24 15:34:06 +01:00
committed by misfir3
parent 6d727b98e3
commit 0779f7a3d0
56 changed files with 488 additions and 367 deletions

View File

@ -17,11 +17,6 @@ define(['jquery',
DeveloperControlsView,
TitleView) {
var lessonContentView = new LessonContentView();
var menuView = new MenuView();
var developerControlsView = new DeveloperControlsView();
var titleView = new TitleView();
function getContentElement() {
return $('#main-content');
};
@ -38,7 +33,8 @@ define(['jquery',
};
var GoatAppRouter = Backbone.Router.extend({
routes: {
routes: {
'welcome': 'welcomeRoute',
'lesson/:name': 'lessonRoute',
'lesson/:name/:pageNum': 'lessonPageRoute',
@ -46,14 +42,9 @@ define(['jquery',
'reportCard': 'reportCard'
},
lessonController: new LessonController({
lessonContentView: lessonContentView,
titleView: titleView
}),
menuController: new MenuController({
menuView: menuView
}),
lessonController: null,
menuController : null,
titleView: null,
setUpCustomJS: function () {
webgoat.customjs.jquery = $; //passing jquery into custom js scope ... still klunky, but works for now
@ -75,54 +66,45 @@ define(['jquery',
}
},
init: function () {
goatRouter = new GoatAppRouter();
initialize: function () {
this.menuController = new MenuController({menuView: new MenuView()});
this.titleView = new TitleView();
this.lessonController = new LessonController({lessonContentView: new LessonContentView(), titleView: this.titleView}),
this.lessonController.start();
// this.menuController.initMenu();
webgoat = {};
webgoat.customjs = {};
this.setUpCustomJS();
goatRouter.on('route:lessonRoute', function (name) {
render();
this.lessonController.loadLesson(name, 0);
//TODO - update menu code from below
this.menuController.updateMenu(name);
});
goatRouter.on('route:lessonPageRoute', function (name, pageNum) {
render();
pageNum = (_.isNumber(parseInt(pageNum))) ? parseInt(pageNum) : 0;
this.lessonController.loadLesson(name, pageNum);
//TODO - update menu code from below
this.menuController.updateMenu(name);
});
goatRouter.on('route:welcomeRoute', function () {
render();
this.lessonController.loadWelcome();
});
goatRouter.on('route:testRoute', function (param) {
render();
this.lessonController.testHandler(param);
});
goatRouter.on("route", function (route, params) {
});
Backbone.history.start();
this.listenTo(this.lessonController, 'menu:reload', this.reloadMenu)
},
lessonRoute: function(name) {
render();
this.lessonController.loadLesson(name, 0);
this.menuController.updateMenu(name);
},
lessonPageRoute: function (name, pageNum) {
render();
pageNum = (_.isNumber(parseInt(pageNum))) ? parseInt(pageNum) : 0;
this.lessonController.loadLesson(name, pageNum);
this.menuController.updateMenu(name);
},
welcomeRoute: function () {
render();
this.lessonController.loadWelcome();
},
reloadMenu: function (curLesson) {
this.menuController.updateMenu();
},
reportCard : function () {
var self = this;
require(['goatApp/view/ReportCardView'], function (ReportCardView) {
titleView.render('Report card');
self.titleView.render('Report card');
render(new ReportCardView());
});
},

View File

@ -12,33 +12,34 @@ function($,_,Backbone) {
this.hasPlan = options.hasPlan;
this.hasSolution = options.hasSolution;
this.hasSource = options.hasSource;
this.hasHints = options.hasHints;
var self = this;
Backbone.on('navigatedToPage', function(nav) {
self.showHideHintsButton(nav)
});
},
showHideHintsButton: function(nav) {
if (typeof nav['assignmentPath'] !== 'undefined') {
this.$el.find('#show-hints-button').unbind().on('click',this.showHints.bind(this)).show();
} else {
$('#show-hints-button').hide();
}
},
render:function(title) {
//this.$el.html();
// if still showing, hide
$('#show-source-button').hide();
$('#show-solution-button').hide();
$('#show-plan-button').hide();
$('#show-hints-button').hide();
if (this.hasSource) {
this.$el.find('#show-source-button').unbind().on('click',_.bind(this.showSource,this)).show();
}
if (this.hasHints) {
this.$el.find('#show-hints-button').unbind().on('click',this.showHints.bind(this)).show();
}
if (this.hasSolution) {
this.$el.find('#show-solution-button').unbind().on('click',_.bind(this.showSolution,this)).show();
}
if (true) { //FIXME: change to this.hasAttack
this.$el.find('#show-attack-button').unbind().on('click',_.bind(this.showAttack,this)).show();
}
this.$el.find('#show-lesson-overview-button').unbind().on('click', _.bind(this.showLessonOverview, this)).show();
this.$el.find('#restart-lesson-button').unbind().on('click',_.bind(this.restartLesson,this)).show();
//this.$el.append(this.helpButtons.restartLesson);
},
showHints: function() {
@ -53,10 +54,6 @@ function($,_,Backbone) {
this.trigger('solution:show','solution');
},
showAttack: function() {
this.trigger('attack:show',{show:true});
},
restartLesson: function() {
this.trigger('lesson:restart');
},

View File

@ -15,8 +15,13 @@ function($,
initialize: function() {
this.curHint=0;
this.collection = new HintCollection();
this.hintsToShow = new Array();
this.listenTo(this.collection,'loaded',this.onModelLoaded);
this.hideHints();
var self = this;
Backbone.on('navigatedToPage', function(nav){
self.selectHints(nav)
});
},
isVisible: function() {
@ -34,19 +39,38 @@ function($,
render:function() {
if (this.isVisible()) {
this.$el.hide(350);
} else {
} else if (this.hintsToShow.length > 0) {
this.$el.show(350);
}
this.toggleLabel()
if (this.collection.length > 0) {
if (this.hintsToShow.length > 0) {
this.hideShowPrevNextButtons();
}
this.displayHint(this.curHint);
},
/**
* Select the hints, we get '/WebGoat/HttpBasics/attack1' in the json (nav) we need to select all the hints
* from the model where the assignment name is contained in the assignmentPath. We do this not to mess
* with contextRoots etc and try to select the name from the url.
*
* @todo we can of course try to add the assigment name to the html form as attribute.
*
* @param nav the json structure for navigating
*/
selectHints: function(nav) {
this.curHint = 0;
var assignmentPath = nav['assignmentPath'];
if (assignmentPath != null) {
this.hintsToShow = this.collection.getHintsForAssignment(assignmentPath);
} else {
this.hintsToShow = new Array();
}
},
onModelLoaded: function() {
this.trigger('hints:loaded',{'helpElement':'hints','value':true})
},
@ -58,7 +82,7 @@ function($,
},
showNextHint: function() {
this.curHint = (this.curHint < this.collection.length -1) ? this.curHint+1 : this.curHint;
this.curHint = (this.curHint < this.hintsToShow.length -1) ? this.curHint+1 : this.curHint;
this.hideShowPrevNextButtons();
this.displayHint(this.curHint);
},
@ -70,11 +94,15 @@ function($,
},
displayHint: function(curHint) {
this.$el.find('#lesson-hint-content').html(this.collection.models[curHint].get('hint'));
if(this.hintsToShow.length == 0) {
this.hideHints();
} else {
this.$el.find('#lesson-hint-content').html(polyglot.t(this.hintsToShow[curHint].get('hint')));
}
},
hideShowPrevNextButtons: function() {
if (this.curHint === this.collection.length -1) {
if (this.curHint === this.hintsToShow.length -1) {
this.$el.find('#show-next-hint').css('visibility','hidden');
} else {
this.$el.find('#show-next-hint').css('visibility','visible');

View File

@ -189,7 +189,7 @@ define(['jquery',
if (this.currentPage < this.numPages -1) {
this.currentPage++;
window.location.href = this.model.get('lessonUrl') + '/' + this.currentPage;
//this.showCurContentPage(true);
//this.showCurContentPage(true);Con
}
if (this.currentPage > 0) {
@ -225,10 +225,21 @@ define(['jquery',
this.$el.find(this.$contentPages[this.currentPage]).show();
},
findAssigmentEndpointOnPage: function(pageNumber) {
var contentPage = this.$contentPages[this.currentPage];
var form = $('form.attack-form', contentPage);
var action = form.attr('action')
if (action !== undefined) {
return action;
}
},
navToPage: function (pageNum) {
this.setCurrentPage(pageNum);//provides validation
this.showCurContentPage(this.currentPage);
this.hideShowNavButtons();
var assignmentPath = this.findAssigmentEndpointOnPage(pageNum);
Backbone.trigger('navigatedToPage',{'pageNumber':pageNum, 'assignmentPath' : assignmentPath});
},
hideShowNavButtons: function () {

View File

@ -7,13 +7,13 @@ function($,
_,
Backbone) {
return Backbone.View.extend({
el:'#toggle-menu', //Check this,
el:'#toggle-menu',
initialize: function() {
this.$el.on('click',this.toggleMenu);
},
toggleMenu: function() {
events: {
"click": "toggleMenu"
},
toggleMenu: function(e) {
//left
if (!$('.sidebarRight').hasClass('.sidebar-toggle-right')) {
$('.sidebarRight').removeClass('sidebar-toggle-right');
@ -21,7 +21,7 @@ function($,
}
$('.sidebar').toggleClass('sidebar-toggle');
$('.main-content-wrapper').toggleClass('main-content-toggle-left');
//e.stopPropagation();
e.stopImmediatePropagation();
}
});
});

View File

@ -60,7 +60,7 @@ define(['jquery',
var categoryLessonList = $('<ul>',{class:'slideDown lessonsAndStages',id:catId}); //keepOpen
for (var j=0; j < lessons.length;j++) {
var lessonItem = $('<li>',{class:'lesson'});
var lessonName = lessons[j].name;
var lessonName = polyglot.t(lessons[j].name);
var lessonId = catId + '-' + GoatUtils.makeId(lessonName);
if (this.curLessonLinkId === lessonId) {
lessonItem.addClass('selected');