diff options
-rw-r--r-- | css/codeq.css | 8 | ||||
-rw-r--r-- | index.html | 15 | ||||
-rw-r--r-- | js/codeq/comms.js | 7 | ||||
-rw-r--r-- | js/codeq/problem_list.js | 54 | ||||
-rw-r--r-- | js/codeq/solutions.js | 49 | ||||
-rw-r--r-- | res/en.json | 3 | ||||
-rw-r--r-- | res/sl.json | 1 |
7 files changed, 121 insertions, 16 deletions
diff --git a/css/codeq.css b/css/codeq.css index 0c30f62..9e4bd2e 100644 --- a/css/codeq.css +++ b/css/codeq.css @@ -158,14 +158,18 @@ div.vertical-line{ margin: 0 1% 0 1%; } - -/* screen problems*/ +/* screen problems */ .block { padding: 0; min-height: 4em; overflow: hidden; } +/* screen solutions */ +h2.group-title a.view-solutions { + font-size: small; +} + /* description */ .block.block1 { border-bottom: 1px solid #ddd; @@ -319,6 +319,20 @@ <!-- problem selection screen for a specific language: groups of problems, with descriptions --> <div class="container" id="screen_problem_list" style="display: none;"></div> + <!-- screen to display all user solutions for a given langauge --> + <div class="container" id="screen_solutions" style="display: none;"> + <div class="row"> + <div class="col-md-12"> + <h2 data-tkey="your_solutions">Your solutions</h2> + <div class="btn-group"> + <button type="button" class="btn btn-default btnGoBack" data-tkey="go_back">Go back</button> + </div> + <hr> + <div class="solutions"></div> + </div> + </div> + </div> + <!-- problem screen: prolog --> <div class="container-fluid quadrants block1" id="screen_prolog" style="display: none;"> <div class="row"> @@ -550,6 +564,7 @@ <script src="js/codeq/prolog.js"></script> <script src="js/codeq/python.js"></script> <script src="js/codeq/robot.js"></script> + <script src="js/codeq/solutions.js"></script> <script src="js/codeq/signup.js"></script> <script src="js/codeq/login.js"></script> <script src="js/codeq/aaiLogin.js"></script> diff --git a/js/codeq/comms.js b/js/codeq/comms.js index d3f9252..c3f86f5 100644 --- a/js/codeq/comms.js +++ b/js/codeq/comms.js @@ -469,6 +469,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ }); }, + getSolutions: function commsGetSolutions (problem_ids) { + return this.send({ + 'action': 'get_solutions', + 'problem_ids': problem_ids + }); + }, + loadProblem: function commsLoadProblem (problem_id) { return this.send({ 'action': 'load_problem', diff --git a/js/codeq/problem_list.js b/js/codeq/problem_list.js index 97bac25..e5ca36e 100644 --- a/js/codeq/problem_list.js +++ b/js/codeq/problem_list.js @@ -214,10 +214,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ var li = languageIdentifier, // a shorthand rawTranslations = data.translations || {}, groups = data.groups || [], - Ngroups = groups.length, html = [], problemReferences = [], - group, problems, Nproblems, problem, i, j, nrefs, + groupReferences = [], groupProblemIDs, + group, problems, problem, i, j, nrefs, baseTabIndex = 200; // tabindex attribute of the first problem link var langDict = convertTranslations(rawTranslations, 'name', 'description'), // this will be the resulting dictionary: multi-level keys that lead up to the lang-dict groupDict, problemDict; @@ -227,26 +227,32 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ // title: HTML structure for "name" and "desc" html.push('<h1 class="language-title" ', ta(langDict.name), '></h1><hr>'); html.push('<p class="language-description" ', ta(langDict.description), '></p>'); + // content: problem directory - for (i = 0; i < Ngroups; i++) { + for (i = 0; i < groups.length; i++) { group = groups[i] || {}; + problems = group.problems || []; + groupDict = convertTranslations(group.translations, 'name', 'description'); // the group-level translations, added will codeq.template.processDictionary(groupDict.description, [languageIdentifier, group.identifier]); + // group content - html.push('<h2 class="group-title" ', ta(groupDict.name), '></h2>'); + html.push('<h2 class="group-title group-' + i + '"><span ', ta(groupDict.name), '></span></h2>'); html.push('<div class="group-description" ', ta(groupDict.description), '></div>'); html.push('<ul class="group-problems">'); + // problem content - problems = group.problems || []; - Nproblems = problems.length; - for (j = 0; j < Nproblems; j++) { + groupProblemIDs = []; + for (j = 0; j < problems.length; j++) { nrefs = problemReferences.length; problem = problems[j] || {}; problemDict = convertTranslations(problem.translations, 'name'); html.push('<li><a href="#" tabindex="' + (baseTabIndex+nrefs) + '"' + ' class="problem-', '' + nrefs, '" ', ta(problemDict.name), '></a></li>'); problemReferences.push({'g': group.identifier || 'nogroup', 'p': problem.identifier || 'noproblem', 'id': problem.id}); + groupProblemIDs.push(problem.id); } + groupReferences.push(groupProblemIDs); html.push('</ul>'); } @@ -254,6 +260,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ 'language': languageIdentifier, // 'prolog', 'python', ... 'html': html.join(''), // the DOM structure (without textual content), as HTML text 'refs': problemReferences, // array of problem info {g: group, p: problem, id: problem_id}, referenced from DOM <a> elements + 'groups': groupReferences, // array of group info [problem_id1, problem_id2, …] 'commonDef': { 'hint': processHints(rawTranslations), // hint translations: keyword -> lang -> value 'hint_type': data.hint_type || {} @@ -286,18 +293,39 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ }, /** - * Show attempted/solved status in the link for every problem. + * Update mutable data in the problem list screen. */ - showAttempts = function (languageData, attempts) { - var i; + updateDom = function (languageData, attempts) { + var problems = languageData.refs, + groups = languageData.groups, + jqGroup = jqScreen.find('h2.group-title'), + i; + + // show attempted/solved status in the link for each problem for (i = 0; i < languageData.refs.length; i++) { var ref = languageData.refs[i]; if (ref.id in attempts) { jqScreen.find('a.problem-'+i) - .removeClass('solved attempted') - .addClass(attempts[ref.id] ? 'solved' : 'attempted'); + .removeClass('solved attempted') + .addClass(attempts[ref.id] ? 'solved' : 'attempted'); } } + + // add links to view all solutions for each group + jqGroup.find('a.view-solutions').remove(); + jqGroup.each(function () { + var group = +$(this).attr('class').split(' ')[1].split('-')[1], + problem_ids = groups[group].filter(function (pid) { return pid in attempts }), + link; + if (problem_ids.length > 0) { + var link = $('<a class="view-solutions"><span class="glyphicon glyphicon-download-alt"></span></a>') + .on('click', function (e) { + e.preventDefault(); + codeq.globalStateMachine.transition('solutions', problem_ids); + }); + $(this).append(' ', link); + } + }); }, // ================================================================================ @@ -418,7 +446,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ createDom(data); } currentLanguage = language; - showAttempts(data, attemptData.data); + updateDom(data, attemptData.data); })).done(); jqScreen.css('display', ''); diff --git a/js/codeq/solutions.js b/js/codeq/solutions.js new file mode 100644 index 0000000..399c934 --- /dev/null +++ b/js/codeq/solutions.js @@ -0,0 +1,49 @@ +/* CodeQ: an online programming tutor. + Copyright (C) 2016 UL FRI + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU Affero General Public License as published by the Free +Software Foundation, either version 3 of the License, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +(function(){ + "use strict"; + var jqScreen = $('#screen_solutions'), + jqSolutions = jqScreen.find('.solutions'), + jqBtnGoBack = jqScreen.find('.btnGoBack'); + + // Register with the state machine + codeq.globalStateMachine.register('solutions', { + 'jqScreen': jqScreen, + 'isModal': true, + + 'enter': function (problem_ids) { + jqBtnGoBack.on('click', function () { + history.back(); + }); + codeq.comms.getSolutions(problem_ids) + .then(function (solutions) { + var i; + solutions = solutions.data; + for (i = 0; i < solutions.length; i++) { + jqSolutions.append('<pre>' + solutions[i].trim() + '</pre>'); + } + }) + .done(); + jqScreen.css('display', ''); + }, + 'exit' : function(){ + jqBtnGoBack.off('click'); + jqSolutions.empty(); + jqScreen.css('display', 'none'); + } + }); +})(); diff --git a/res/en.json b/res/en.json index a4731ed..364dfbd 100644 --- a/res/en.json +++ b/res/en.json @@ -5,8 +5,9 @@ "robot_address_placeholder": "IP address", "robot_address_title": "Set the robot's IPv4 or IPv6 address.", "settings": "User settings", - "problem_list": "Problems", "save": "Save", + "your_solutions": "Your solutions", + "problem_list": "Problems", "python": "Python", "prolog": "Prolog", "robot": "Robot", diff --git a/res/sl.json b/res/sl.json index 2743647..a9032ef 100644 --- a/res/sl.json +++ b/res/sl.json @@ -6,6 +6,7 @@ "robot_address_title": "Vnesi IPv4 ali IPv6 naslov robota.", "settings": "Uporabniške nastavitve", "save": "Shrani", + "your_solutions": "Tvoje rešitve", "problem_list": "Naloge", "python": "Python", "prolog": "Prolog", |