From dca26cf237fcff99d6133c1f7cffc68bba44ba4c Mon Sep 17 00:00:00 2001 From: Alexander Kastius Date: Thu, 1 Sep 2016 10:49:55 +0200 Subject: [PATCH] Refactored frontend. Moved output to editor tab. Added collapse function to sidebar. --- app/assets/javascripts/editor/editor.js.erb | 55 +++++++++++++++++-- .../javascripts/editor/evaluation.js.erb | 7 ++- .../javascripts/editor/submissions.js.erb | 3 +- app/assets/stylesheets/editor.css.scss | 51 +++++++++++++++++ app/views/exercises/_editor.html.slim | 5 +- .../exercises/_editor_file_tree.html.slim | 27 ++++++--- app/views/exercises/_editor_output.html.slim | 29 ++++++++++ app/views/exercises/implement.html.slim | 30 +--------- 8 files changed, 159 insertions(+), 48 deletions(-) create mode 100644 app/views/exercises/_editor_output.html.slim diff --git a/app/assets/javascripts/editor/editor.js.erb b/app/assets/javascripts/editor/editor.js.erb index b16892ff..026aa2a9 100644 --- a/app/assets/javascripts/editor/editor.js.erb +++ b/app/assets/javascripts/editor/editor.js.erb @@ -100,7 +100,8 @@ var CodeOceanEditor = { showOutput: function(event) { event.preventDefault(); - this.showTab(1); + this.showTab(0); + this.showOutputBar(); $('#output').scrollTo($(this).attr('href')); }, @@ -144,10 +145,8 @@ var CodeOceanEditor = { handleKeyPress: function (event) { if (event.which === this.ALT_1_KEY_CODE) { this.showWorkspaceTab(event); - } else if (event.which === this.ALT_2_KEY_CODE) { - this.showTab(1); } else if (event.which === this.ALT_3_KEY_CODE) { - this.showTab(2); + this.showTab(1); } else if (event.which === this.ALT_R_KEY_CODE) { $('#run').trigger('click'); } else if (event.which === this.ALT_S_KEY_CODE) { @@ -270,16 +269,37 @@ var CodeOceanEditor = { var frame = $('[data-file-id="' + active_file.id + '"]').parent(); this.showFrame(frame); this.toggleButtonStates(); - }); + }.bind(this)); }, initializeFileTreeButtons: function () { $('#create-file').on('click', this.showFileDialog.bind(this)); + $('#create-file-collapsed').on('click', this.showFileDialog.bind(this)); $('#destroy-file').on('click', this.confirmDestroy.bind(this)); + $('#destroy-file-collapsed').on('click', this.confirmDestroy.bind(this)); $('#download').on('click', this.downloadCode.bind(this)); + $('#download-collapsed').on('click', this.downloadCode.bind(this)); $('#request-for-comments').on('click', this.requestComments.bind(this)); }, + initializeSideBarCollapse: function() { + $('#sidebar-collapsed').addClass('hidden'); + $('#sidebar-collapse-collapsed').on('click',this.handleSideBarToggle.bind(this)); + $('#sidebar-collapse').on('click',this.handleSideBarToggle.bind(this)) + }, + + handleSideBarToggle: function() { + $('#sidebar').toggleClass('sidebar-col').toggleClass('sidebar-col-collapsed');/** + $('#frames').toggleClass('editor-col') + if (main_area.hasClass('col-sm-10')) { + main_area.removeClass('col-sm-10').addClass('col-sm-11'); + } else if (main_area.hasClass('col-sm-11')) { + main_area.removeClass('col-sm-11').addClass('col-sm-10'); + }*/ + $('#sidebar-collapsed').toggleClass('hidden'); + $('#sidebar-uncollapsed').toggleClass('hidden'); + }, + initializeRegexes: function () { this.regex_for_language.set("ace/mode/python", /File "(.+?)", line (\d+)/g); this.regex_for_language.set("ace/mode/java", /(.*\.java):(\d+):/g); @@ -454,7 +474,8 @@ var CodeOceanEditor = { this.clearOutput(); $('#hint').fadeOut(); $('#flowrHint').fadeOut(); - this.showTab(1); + this.showTab(0); + this.showOutputBar(); }, isActiveFileBinary: function () { @@ -544,6 +565,26 @@ var CodeOceanEditor = { }); }, + initializeOutputBarToggle: function() { + $('#toggle-sidebar-output').on('click',this.hideOutputBar.bind(this)); + $('#toggle-sidebar-output-collapsed').on('click',this.showOutputBar.bind(this)); + }, + + showOutputBar: function() { + if ($('#sidebar').hasClass('sidebar-col')) { + this.handleSideBarToggle(); + } + $('#output_sidebar_collapsed').addClass('hidden'); + $('#output_sidebar_uncollapsed').removeClass('hidden'); + $('#output_sidebar').removeClass('output-col-collapsed').addClass('output-col'); + }, + + hideOutputBar: function() { + $('#output_sidebar_collapsed').removeClass('hidden'); + $('#output_sidebar_uncollapsed').addClass('hidden'); + $('#output_sidebar').removeClass('output-col').addClass('output-col-collapsed'); + }, + initializeEverything: function() { this.initializeRegexes(); this.initializeCodePilot(); @@ -552,6 +593,8 @@ var CodeOceanEditor = { this.initializeEditors(); this.initializeEventHandlers(); this.initializeFileTree(); + this.initializeSideBarCollapse(); + this.initializeOutputBarToggle(); this.initializeTooltips(); this.initPrompt(); this.renderScore(); diff --git a/app/assets/javascripts/editor/evaluation.js.erb b/app/assets/javascripts/editor/evaluation.js.erb index 0f944239..4e19bc9a 100644 --- a/app/assets/javascripts/editor/evaluation.js.erb +++ b/app/assets/javascripts/editor/evaluation.js.erb @@ -8,7 +8,7 @@ CodeOceanEditorEvaluation = { }, 0).toFixed(2); $('#score').data('score', score); this.renderScore(); - this.showTab(2); + this.showTab(1); }, handleTestResponse: function (result) { @@ -18,7 +18,8 @@ CodeOceanEditorEvaluation = { this.qa_api.executeCommand('syncOutput', [result]); } this.showStatus(result); - this.showTab(1); + this.showTab(0); + this.showOutputBar(); }, printOutput: function (output, colorize, index) { @@ -132,7 +133,7 @@ CodeOceanEditorEvaluation = { this.hideSpinner(); this.running = false; this.toggleButtonStates(); - }); + }.bind(this)); jqxhr.fail(ajaxError); }, diff --git a/app/assets/javascripts/editor/submissions.js.erb b/app/assets/javascripts/editor/submissions.js.erb index f752dde2..32557d8d 100644 --- a/app/assets/javascripts/editor/submissions.js.erb +++ b/app/assets/javascripts/editor/submissions.js.erb @@ -115,7 +115,8 @@ CodeOceanEditorSubmissions = { stderr: message }, true, 0); this.sendError(message, response.id); - this.showTab(1); + this.showTab(0); + this.showOutputBar(); }; } }); diff --git a/app/assets/stylesheets/editor.css.scss b/app/assets/stylesheets/editor.css.scss index e41153e2..9f1b4784 100644 --- a/app/assets/stylesheets/editor.css.scss +++ b/app/assets/stylesheets/editor.css.scss @@ -64,6 +64,7 @@ button i.fa-spin { #outputInformation { #output { max-height: 500px; + width: 100%; overflow: auto; margin: 2em 0; @@ -95,3 +96,53 @@ button i.fa-spin { margin-right: 25px; float: right; } + +.sidebar-col-collapsed { + -webkit-transition: width 2s; + transition: width 2s; + width:52px; + float:left; + min-height: 1px; + padding-left: 15px; +} + +.sidebar-col { + -webkit-transition: width 2s; + transition: width 2s; + width:20%; + float:left; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} + +.editor-col { + min-height: 1px; + padding-left: 15px; + padding-right: 15px; + width:auto; + height:100%; + overflow:hidden; +} + +.output-col { + -webkit-transition: width 2s; + transition: width 2s; + width:40%; + float:right; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; + box-sizing: border-box +} + +.output-col-collapsed { + -webkit-transition: width 2s; + transition: width 2s; + width:67px; + float:right; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; + box-sizing: border-box +} \ No newline at end of file diff --git a/app/views/exercises/_editor.html.slim b/app/views/exercises/_editor.html.slim index 0ce5b73f..9c04b7ef 100644 --- a/app/views/exercises/_editor.html.slim +++ b/app/views/exercises/_editor.html.slim @@ -1,6 +1,7 @@ #editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id - div class=(@exercise.hide_file_tree ? 'hidden col-sm-3' : 'col-sm-3') = render('editor_file_tree', files: @files) - div id='frames' class=(@exercise.hide_file_tree ? 'col-sm-12' : 'col-sm-9') + div id="sidebar" class=(@exercise.hide_file_tree ? 'hidden sidebar-col' : 'sidebar-col') = render('editor_file_tree', files: @files) + div id='output_sidebar' class='output-col-collapsed' = render('exercises/editor_output') + div id='frames' class=(@exercise.hide_file_tree ? 'editor-col' : 'editor-col') - @files.each do |file| = render('editor_frame', exercise: exercise, file: file) #autosave-label diff --git a/app/views/exercises/_editor_file_tree.html.slim b/app/views/exercises/_editor_file_tree.html.slim index c23158b9..26f14112 100644 --- a/app/views/exercises/_editor_file_tree.html.slim +++ b/app/views/exercises/_editor_file_tree.html.slim @@ -1,10 +1,23 @@ -#files data-entries=FileTree.new(files).to_js_tree +div id='sidebar-collapsed' + = render('editor_button', classes: 'btn-block btn-primary btn-sm', icon: 'fa fa-plus-square', id: 'sidebar-collapse-collapsed', label:'') + - if @exercise.allow_file_creation? + = render('editor_button', classes: 'btn-block btn-primary btn-sm', data: {:'data-cause' => 'file'}, icon: 'fa fa-plus', id: 'create-file-collapsed', label:'') + = render('editor_button', classes: 'btn-block btn-warning btn-sm', data: {:'data-cause' => 'file', :'data-message-confirm' => t('shared.confirm_destroy')}, label:'', icon: 'fa fa-times', id: 'destroy-file-collapsed') -hr + = render('editor_button', classes: 'btn-block btn-primary btn-sm', icon: 'fa fa-download', id: 'download-collapsed', label:'') -- if @exercise.allow_file_creation? - = render('editor_button', classes: 'btn-block btn-primary btn-sm', data: {:'data-cause' => 'file'}, icon: 'fa fa-plus', id: 'create-file', label: t('exercises.editor.create_file')) - = render('editor_button', classes: 'btn-block btn-warning btn-sm', data: {:'data-cause' => 'file', :'data-message-confirm' => t('shared.confirm_destroy')}, icon: 'fa fa-times', id: 'destroy-file', label: t('exercises.editor.destroy_file')) - = render('shared/modal', id: 'modal-file', template: 'code_ocean/files/_form', title: t('exercises.editor.create_file')) +div id='sidebar-uncollapsed' + = render('editor_button', classes: 'btn-block btn-primary btn-sm', icon: 'fa fa-minus-square', id: 'sidebar-collapse', label: 'Collapse') -= render('editor_button', classes: 'btn-block btn-primary btn-sm', icon: 'fa fa-download', id: 'download', label: t('exercises.editor.download')) + hr + + #files data-entries=FileTree.new(files).to_js_tree + + hr + + - if @exercise.allow_file_creation? + = render('editor_button', classes: 'btn-block btn-primary btn-sm', data: {:'data-cause' => 'file'}, icon: 'fa fa-plus', id: 'create-file', label: t('exercises.editor.create_file')) + = render('editor_button', classes: 'btn-block btn-warning btn-sm', data: {:'data-cause' => 'file', :'data-message-confirm' => t('shared.confirm_destroy')}, icon: 'fa fa-times', id: 'destroy-file', label: t('exercises.editor.destroy_file')) + = render('shared/modal', id: 'modal-file', template: 'code_ocean/files/_form', title: t('exercises.editor.create_file')) + + = render('editor_button', classes: 'btn-block btn-primary btn-sm', icon: 'fa fa-download', id: 'download', label: t('exercises.editor.download')) diff --git a/app/views/exercises/_editor_output.html.slim b/app/views/exercises/_editor_output.html.slim new file mode 100644 index 00000000..e96911ac --- /dev/null +++ b/app/views/exercises/_editor_output.html.slim @@ -0,0 +1,29 @@ +div id='output_sidebar_collapsed' + = render('editor_button', classes: 'btn-block btn-primary btn-sm', icon: 'fa fa-plus-square', id: 'toggle-sidebar-output-collapsed', label: '') +div id='output_sidebar_uncollapsed' class='hidden col-sm-12' data-message-no-output=t('exercises.implement.no_output') + .row + = render('editor_button', classes: 'btn-block btn-primary btn-sm', icon: 'fa fa-minus-square', id: 'toggle-sidebar-output', label: 'Collapse') + hr + div + #hint + .panel.panel-warning + .panel-heading = t('exercises.implement.hint') + .panel-body + div + // todo set to full width if turtle isnt used + #prompt.input-group.hidden + span.input-group-addon data-prompt=t('exercises.editor.input') = t('exercises.editor.input') + input#prompt-input.form-control type='text' + span.input-group-btn + button#prompt-submit.btn.btn-primary type="button" = t('exercises.editor.send') + #output + pre = t('exercises.implement.no_output_yet') + - if CodeOcean::Config.new(:code_ocean).read[:flowr][:enabled] + #flowrHint.panel.panel-info data-url=CodeOcean::Config.new(:code_ocean).read[:flowr][:url] role='tab' + .panel-heading = 'Gain more insights here' + .panel-body + hr + div + #turtlediv + // todo what should the canvas default size be? + canvas#turtlecanvas.hidden width=400 height=400 style='border-style:solid;border-width:thin' \ No newline at end of file diff --git a/app/views/exercises/implement.html.slim b/app/views/exercises/implement.html.slim index 0c5e109b..19924a1a 100644 --- a/app/views/exercises/implement.html.slim +++ b/app/views/exercises/implement.html.slim @@ -1,5 +1,5 @@ .row - #editor-column.col-md-10.col-md-offset-1 + #editor-column.col-md-12 h1 = @exercise span.badge.pull-right.score @@ -16,10 +16,6 @@ a data-placement='top' data-toggle='tab' data-tooltip=true href='#workspace' role='tab' title=t('shared.tooltips.shortcut', shortcut: 'ALT + 1') i.fa.fa-code = t('.workspace') - li - a data-placement='top' data-toggle='tab' data-tooltip=true href='#outputInformation' role='tab' title=t('shared.tooltips.shortcut', shortcut: 'ALT + 2') - i.fa.fa-terminal - = t('.output') li a data-placement='top' data-toggle='tab' data-tooltip=true href='#progress' role='tab' title=t('shared.tooltips.shortcut', shortcut: 'ALT + 3') i.fa.fa-line-chart @@ -29,30 +25,6 @@ .tab-content #workspace.tab-pane.active = render('editor', exercise: @exercise, files: @files, submission: @submission) - #outputInformation.tab-pane data-message-no-output=t('.no_output') - #hint - .panel.panel-warning - .panel-heading = t('.hint') - .panel-body - .row - / #output-col1.col-sm-12 - #output-col1 - // todo set to full width if turtle isnt used - #prompt.input-group.hidden - span.input-group-addon data-prompt=t('exercises.editor.input') = t('exercises.editor.input') - input#prompt-input.form-control type='text' - span.input-group-btn - button#prompt-submit.btn.btn-primary type="button" = t('exercises.editor.send') - #output - pre = t('.no_output_yet') - - if CodeOcean::Config.new(:code_ocean).read[:flowr][:enabled] - #flowrHint.panel.panel-info data-url=CodeOcean::Config.new(:code_ocean).read[:flowr][:url] role='tab' - .panel-heading = 'Gain more insights here' - .panel-body - #output-col2.col-lg-5.col-md-5 - #turtlediv - // todo what should the canvas default size be? - canvas#turtlecanvas.hidden width=400 height=400 style='border-style:solid;border-width:thin' #progress.tab-pane #results h2 = t('.results')