]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-20652 workshop: initial work on example submissions
authorDavid Mudrak <david.mudrak@gmail.com>
Mon, 4 Jan 2010 18:27:21 +0000 (18:27 +0000)
committerDavid Mudrak <david.mudrak@gmail.com>
Mon, 4 Jan 2010 18:27:21 +0000 (18:27 +0000)
mod/workshop/example.php [new file with mode: 0644]
mod/workshop/lang/en_utf8/workshop.php
mod/workshop/locallib.php
mod/workshop/renderer.php
mod/workshop/styles.css
mod/workshop/submission.php
mod/workshop/view.php

diff --git a/mod/workshop/example.php b/mod/workshop/example.php
new file mode 100644 (file)
index 0000000..d4d7d1d
--- /dev/null
@@ -0,0 +1,177 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * View or edit a single example example
+ *
+ * @package   mod-workshop
+ * @copyright 2009 David Mudrak <david.mudrak@gmail.com>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once(dirname(dirname(dirname(__FILE__))).'/config.php');
+require_once(dirname(__FILE__).'/lib.php');
+require_once(dirname(__FILE__).'/locallib.php');
+
+$cmid   = required_param('cmid', PARAM_INT);            // course module id
+$id     = required_param('id', PARAM_INT);              // example submission id, 0 for the new one
+$edit   = optional_param('edit', false, PARAM_BOOL);    // open for editing?
+$delete = optional_param('delete', false, PARAM_BOOL);  // example removal requested
+$confirm = optional_param('confirm', false, PARAM_BOOL);  // example removal request confirmed
+
+$cm     = get_coursemodule_from_id('workshop', $cmid, 0, false, MUST_EXIST);
+$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
+
+require_login($course, false, $cm);
+if (isguestuser()) {
+    print_error('guestsarenotallowed');
+}
+
+$workshop = $DB->get_record('workshop', array('id' => $cm->instance), '*', MUST_EXIST);
+$workshop = new workshop($workshop, $cm, $course);
+
+$PAGE->set_url(new moodle_url($workshop->example_url($id), array('edit' => $edit)));
+
+if ($id) { // example is specified
+    $example = $workshop->get_example_by_id($id);
+} else { // no example specified - create new one
+    require_capability('mod/workshop:manageexamples', $workshop->context);
+    $example = new stdClass();
+    $example->id = null;
+    $example->authorid = $USER->id;
+}
+
+$canmanage  = has_capability('mod/workshop:manageexamples', $workshop->context);
+$isreviewer = $DB->record_exists('workshop_assessments', array('submissionid' => $example->id, 'reviewerid' => $USER->id));
+
+if ($id and $delete and $confirm and $canmanage) {
+    require_sesskey();
+    $workshop->delete_submission($example);
+    redirect($workshop->view_url());
+}
+
+if ($example->id and ($canmanage or $isreviewer)) {
+    // ok you can go
+} elseif (is_null($example->id) and $canmanage) {
+    // ok you can go
+} else {
+    print_error('nopermissions');
+}
+
+if ($edit and $canmanage) {
+    require_once(dirname(__FILE__).'/submission_form.php');
+
+    $maxfiles       = $workshop->nattachments;
+    $maxbytes       = $workshop->maxbytes;
+    $contentopts    = array('trusttext' => true, 'subdirs' => false, 'maxfiles' => $maxfiles, 'maxbytes' => $maxbytes);
+    $attachmentopts = array('subdirs' => true, 'maxfiles' => $maxfiles, 'maxbytes' => $maxbytes);
+    $example        = file_prepare_standard_editor($example, 'content', $contentopts, $workshop->context,
+                                        'workshop_submission_content', $example->id);
+    $example        = file_prepare_standard_filemanager($example, 'attachment', $attachmentopts, $workshop->context,
+                                        'workshop_submission_attachment', $example->id);
+
+    $mform          = new workshop_submission_form($PAGE->url, array('current' => $example, 'workshop' => $workshop,
+                                                    'contentopts' => $contentopts, 'attachmentopts' => $attachmentopts));
+
+    if ($mform->is_cancelled()) {
+        redirect($workshop->view_url());
+
+    } elseif ($canmanage and $formdata = $mform->get_data()) {
+        $timenow = time();
+        if (empty($formdata->id)) {
+            $formdata->workshopid     = $workshop->id;
+            $formdata->example        = 1;
+            $formdata->authorid       = $USER->id;
+            $formdata->timecreated    = $timenow;
+            $formdata->feedbackauthorformat = FORMAT_HTML; // todo better default
+        }
+        $formdata->timemodified       = $timenow;
+        $formdata->title              = trim($formdata->title);
+        $formdata->content            = '';          // updated later
+        $formdata->contentformat      = FORMAT_HTML; // updated later
+        $formdata->contenttrust       = 0;           // updated later
+        if (empty($formdata->id)) {
+            $formdata->id = $DB->insert_record('workshop_submissions', $formdata);
+            // todo add to log
+        }
+        // save and relink embedded images and save attachments
+        $formdata = file_postupdate_standard_editor($formdata, 'content', $contentopts, $workshop->context,
+                                                      'workshop_submission_content', $formdata->id);
+        $formdata = file_postupdate_standard_filemanager($formdata, 'attachment', $attachmentopts, $workshop->context,
+                                                           'workshop_submission_attachment', $formdata->id);
+        if (empty($formdata->attachment)) {
+            // explicit cast to zero integer
+            $formdata->attachment = 0;
+        }
+        // store the updated values or re-save the new example (re-saving needed because URLs are now rewritten)
+        $DB->update_record('workshop_submissions', $formdata);
+        redirect($workshop->example_url($formdata->id));
+    }
+}
+
+$PAGE->set_title($workshop->name);
+$PAGE->set_heading($course->fullname);
+if ($edit) {
+    $PAGE->navbar->add(get_string('exampleediting', 'workshop'));
+} else {
+    $PAGE->navbar->add(get_string('example', 'workshop'));
+}
+
+// Output starts here
+echo $OUTPUT->header();
+$currenttab = 'submission';
+include(dirname(__FILE__) . '/tabs.php');
+echo $OUTPUT->heading(format_string($workshop->name), 2);
+
+// if in edit mode, display the form to edit the example
+if ($edit and $canmanage) {
+    $mform->display();
+    echo $OUTPUT->footer();
+    die();
+}
+
+// else display the example...
+if ($example->id) {
+    if ($canmanage and $delete) {
+    echo $OUTPUT->confirm(get_string('exampledeleteconfirm', 'workshop'),
+            new moodle_url($PAGE->url, array('delete' => 1, 'confirm' => 1)), $workshop->view_url());
+    }
+    $wsoutput = $PAGE->theme->get_renderer('mod_workshop', $PAGE);
+    echo $wsoutput->example_full($example, true);
+}
+// ...with an option to edit and remove it
+if ($canmanage) {
+    echo $OUTPUT->container_start('buttonsbar');
+    if (empty($edit) and empty($delete)) {
+        $editbutton                 = new html_form();
+        $editbutton->method         = 'get';
+        $editbutton->button->text   = get_string('exampleedit', 'workshop');
+        $editbutton->url            = new moodle_url($workshop->example_url($example->id), array('edit' => 'on'));
+        echo $OUTPUT->button($editbutton);
+    }
+    if (empty($delete)) {
+        $deletebutton               = new html_form();
+        $deletebutton->method       = 'get';
+        $deletebutton->button->text = get_string('exampledelete', 'workshop');
+        $deletebutton->url          = new moodle_url($workshop->example_url($example->id), array('delete' => 'on'));
+        echo $OUTPUT->button($deletebutton);
+    }
+    echo $OUTPUT->container_end();
+}
+
+// and possibly display the example's review(s) - todo
+echo $OUTPUT->footer();
index e8d3544d6666c8e1a134008e26ccc32fa7ba3fcc..40bb067832361a056034b4dfe8004192638ef42e 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
-$string[''] = '';
-$string[''] = '';
-$string[''] = '';
-$string[''] = '';
 $string[''] = '';
 $string[''] = '';
 $string[''] = '';
@@ -41,6 +37,7 @@ $string['allocatedetails'] = 'expected: $a->expected<br />submitted: $a->submitt
 $string['allocationdone'] = 'Allocation done';
 $string['allocationerror'] = 'Allocation error';
 $string['allocation'] = 'Submission allocation';
+$string['allsubmissions'] = 'All submissions';
 $string['alreadygraded'] = 'Already graded';
 $string['areainstructauthors'] = 'Instructions for submitting';
 $string['areasubmissionattachment'] = 'Submission attachments';
@@ -79,9 +76,16 @@ $string['err_removegrademappings'] = 'Unable to remove the unused grade mappings
 $string['evaluategradeswait'] = 'Please wait until the assessments are evaluated and the grades are calculated';
 $string['evaluation'] = 'Grading evaluation';
 $string['evaluationmethod'] = 'Grading evaluation method';
+$string['exampleadd'] = 'Add example submission';
+$string['exampledeleteconfirm'] = 'Are you sure you want to delete the following example submission?';
+$string['exampledelete'] = 'Delete example';
+$string['exampleedit'] = 'Edit example';
+$string['exampleediting'] = 'Editing example';
+$string['example'] = 'Example submission';
 $string['examplesbeforeassessment'] = 'Examples are available after own submission and must be assessed before assessment phase';
 $string['examplesbeforesubmission'] = 'Examples must be assessed before own submission';
 $string['examplesmode'] = 'Mode of examples assessment';
+$string['examplesubmissions'] = 'Example submissions';
 $string['examplesvoluntary'] = 'Assessment of example submission is voluntary';
 $string['feedbackauthor'] = 'Feedback for the author';
 $string['feedbackreviewer'] = 'Feedback for the reviewer';
@@ -117,6 +121,7 @@ $string['modulenameplural'] = 'Workshops';
 $string['modulename'] = 'Workshop';
 $string['mysubmission'] = 'My submission';
 $string['nattachments'] = 'Maximum number of submission attachments';
+$string['noexamples'] = 'No examples yet in this workshop';
 $string['nogradeyet'] = 'No grade yet';
 $string['nosubmissionfound'] = 'No submission found for this user';
 $string['nosubmissions'] = 'No submissions yet in this workshop';
@@ -133,6 +138,7 @@ $string['phaseclosed'] = 'Closed';
 $string['phaseevaluation'] = 'Grading evaluation phase';
 $string['phasesetup'] = 'Setup phase';
 $string['phasesubmission'] = 'Submission phase';
+$string['prepareexamples'] = 'Prepare example submissions';
 $string['previewassessmentform'] = 'Preview';
 $string['reassess'] = 'Re-assess';
 $string['receivedgrades'] = 'Received grades';
@@ -182,3 +188,4 @@ $string['withoutsubmission'] = 'Reviewer without own submission';
 $string['workshopadministration'] = 'Workshop administration';
 $string['workshopfeatures'] = 'Workshop features';
 $string['workshopname'] = 'Workshop name';
+$string['yoursubmission'] = 'Your submission';
index ea2a3137254b3e5b60633944655f4daaac4eb2fa..e85a04d45b2ac7945874e5849c5c0ae021216e96 100644 (file)
@@ -394,7 +394,7 @@ class workshop {
                        u.picture AS authorpicture, u.imagealt AS authorimagealt
                   FROM {workshop_submissions} s
             INNER JOIN {user} u ON (s.authorid = u.id)
-                 WHERE s.workshopid = :workshopid AND s.id = :id';
+                 WHERE s.example = 0 AND s.workshopid = :workshopid AND s.id = :id';
         $params = array('workshopid' => $this->id, 'id' => $id);
         return $DB->get_record_sql($sql, $params, MUST_EXIST);
     }
@@ -421,6 +421,41 @@ class workshop {
         return $DB->get_record_sql($sql, $params);
     }
 
+    /**
+     * Returns example submissions for this workshop
+     *
+     * @return array of records or an empty array
+     */
+    public function get_examples() {
+        global $DB;
+        return $DB->get_records('workshop_submissions', array('workshopid' => $this->id, 'example' => 1), 'title', 'id,title');
+    }
+
+    /**
+     * Returns full record of the given example submission
+     *
+     * @param int $id example submission od
+     * @return object
+     */
+    public function get_example_by_id($id) {
+        global $DB;
+        return $DB->get_record('workshop_submissions',
+                array('id' => $id, 'workshopid' => $this->id, 'example' => 1), '*', MUST_EXIST);
+    }
+
+    /**
+     * Removes the submission and all relevant data
+     *
+     * @param stdClass $submission record to delete
+     * @return void
+     */
+    public function delete_submission(stdClass $submission) {
+        global $DB;
+        $assessments = $DB->get_records('workshop_assessments', array('submissionid' => $submission->id), '', 'id');
+        $this->delete_assessment(array_keys($assessments));
+        $DB->delete_records('workshop_submissions', array('id' => $submission->id));
+    }
+
     /**
      * Returns the list of all assessments in the workshop with some data added
      *
@@ -652,6 +687,15 @@ class workshop {
         return new moodle_url($CFG->wwwroot . '/mod/workshop/submission.php', array('cmid' => $this->cm->id, 'id' => $id));
     }
 
+    /**
+     * @param int $id example submission id
+     * @return moodle_url of the page to view an example submission
+     */
+    public function example_url($id) {
+        global $CFG;
+        return new moodle_url($CFG->wwwroot . '/mod/workshop/example.php', array('cmid' => $this->cm->id, 'id' => $id));
+    }
+
     /**
      * @return moodle_url of the mod_edit form
      */
@@ -773,6 +817,16 @@ class workshop {
             }
             $phase->tasks['editform'] = $task;
         }
+        if ($this->useexamples and has_capability('mod/workshop:manageexamples', $this->context, $userid)) {
+            $task = new stdClass();
+            $task->title = get_string('prepareexamples', 'workshop');
+            if ($DB->count_records('workshop_submissions', array('example' => 1, 'workshopid' => $this->id)) > 0) {
+                $task->completed = true;
+            } elseif ($this->phase > self::PHASE_SETUP) {
+                $task->completed = false;
+            }
+            $phase->tasks['prepareexamples'] = $task;
+        }
         if (empty($phase->tasks) and $this->phase == self::PHASE_SETUP) {
             // if we are in the setup phase and there is no task (typical for students), let us
             // display some explanation what is going on
@@ -787,7 +841,8 @@ class workshop {
         $phase = new stdClass();
         $phase->title = get_string('phasesubmission', 'workshop');
         $phase->tasks = array();
-        if (has_capability('moodle/course:manageactivities', $this->context, $userid)) {
+        if (($this->usepeerassessment or $this->useselfassessment)
+             and has_capability('moodle/course:manageactivities', $this->context, $userid)) {
             $task = new stdClass();
             $task->title = get_string('taskinstructreviewers', 'workshop');
             $task->link = $this->updatemod_url();
@@ -811,7 +866,6 @@ class workshop {
             }
             $phase->tasks['submit'] = $task;
         }
-        $phases[self::PHASE_SUBMISSION] = $phase;
         if (has_capability('mod/workshop:allocate', $this->context, $userid)) {
             $task = new stdClass();
             $task->title = get_string('allocate', 'workshop');
@@ -849,6 +903,7 @@ class workshop {
                 $phase->tasks['allocateinfo'] = $task;
             }
         }
+        $phases[self::PHASE_SUBMISSION] = $phase;
 
         // Prepare tasks for the peer-assessment phase (includes eventual self-assessments)
         $phase = new stdClass();
@@ -874,7 +929,7 @@ class workshop {
             }
         }
         unset($a);
-        if ($numofpeers) {
+        if ($this->usepeerassessment and $numofpeers) {
             $task = new stdClass();
             if ($numofpeerstodo == 0) {
                 $task->completed = true;
@@ -889,7 +944,7 @@ class workshop {
             unset($a);
             $phase->tasks['assesspeers'] = $task;
         }
-        if ($numofself) {
+        if ($this->useselfassessment and $numofself) {
             $task = new stdClass();
             if ($numofselftodo == 0) {
                 $task->completed = true;
index f80ea960fdff085c5b6c09e1db7e66cf0f762ea4..3b3c3d800f977da013b9e91af9597ff17e500a9a 100644 (file)
@@ -153,7 +153,6 @@ class mod_workshop_renderer extends plugin_renderer_base {
         return $o;
     }
 
-
     /**
      * Displays the submission fulltext
      *
@@ -290,6 +289,81 @@ class mod_workshop_renderer extends plugin_renderer_base {
         return $this->output->container($outputimgs . $outputfiles, 'attachments');
     }
 
+    /**
+     * Display a short summary of the example submission
+     *
+     * The passed submission object must define at least: id and title
+     *
+     * @param stdClass $example The example submission record
+     * @return string html to be echoed
+     */
+    public function example_summary(stdClass $example) {
+        global $CFG;
+
+        $o  = '';    // output HTML code
+        $classes = 'submission-summary example';
+        $o .= $this->output->container_start($classes);  // main wrapper
+        $link = new html_link();
+        $link->url = new moodle_url($CFG->wwwroot . '/mod/workshop/example.php',
+                                    array('cmid' => $this->page->context->instanceid, 'id' => $example->id));
+        $link->text = format_string($example->title);
+        $link->set_classes('title');
+        $o .= $this->output->link($link);
+
+        $icon = new moodle_action_icon();
+        $icon->image->src = $this->old_icon_url('i/edit');
+        $icon->image->alt = get_string('edit');
+        $icon->link->url = new moodle_url($CFG->wwwroot . '/mod/workshop/example.php',
+                                    array('cmid' => $this->page->context->instanceid, 'id' => $example->id, 'edit' => 'on'));
+        $o .= $this->output->action_icon($icon);
+
+        $icon = new moodle_action_icon();
+        $icon->image->src = $this->old_icon_url('t/delete');
+        $icon->image->alt = get_string('delete');
+        $icon->link->url = new moodle_url($CFG->wwwroot . '/mod/workshop/example.php',
+                                    array('cmid' => $this->page->context->instanceid, 'id' => $example->id, 'delete' => 1));
+        $o .= $this->output->action_icon($icon);
+
+        $o .= $this->output->container_end(); // end of the main wrapper
+        return $o;
+    }
+
+    /**
+     * Displays the example submission fulltext
+     *
+     * By default, this looks similar to a forum post.
+     *
+     * @param stdClass $example        The example submission data
+     * @return string html to be echoed
+     */
+    public function example_full(stdClass $example) {
+        global $CFG;
+
+        $o  = '';    // output HTML code
+        $classes = 'submission-full example';
+        $o .= $this->output->container_start($classes);
+        $o .= $this->output->container_start('header');
+        $o .= $this->output->heading(format_string($example->title), 3, 'title');
+        $created = get_string('userdatecreated', 'workshop', userdate($example->timecreated));
+        $o .= $this->output->container($created, 'userdate created');
+        if ($example->timemodified > $example->timecreated) {
+            $modified = get_string('userdatemodified', 'workshop', userdate($example->timemodified));
+            $o .= $this->output->container($modified, 'userdate modified');
+        }
+        $o .= $this->output->container_end(); // end of header
+
+        $content = format_text($example->content, $example->contentformat);
+        $content = file_rewrite_pluginfile_urls($content, 'pluginfile.php', $this->page->context->id,
+                                                        'workshop_submission_content', $example->id);
+        $o .= $this->output->container($content, 'content');
+
+        $o .= $this->submission_attachments($example);
+
+        $o .= $this->output->container_end(); // end of example-full
+
+        return $o;
+    }
+
     /**
      * Renders the user plannner tool
      *
index 5a83715983ac47c517d022d389b05016db71bf48..8ca8db9805b783e42d0c74d6f1d09e4b7227ef5f 100644 (file)
     margin-right: 5px;
 }
 
+/**
+ * Example submission - summary display
+ */
+.mod-workshop .submission-summary.example .title,
+.mod-workshop .submission-summary.example .userdate {
+    margin: 0px 0px 0px 0px;
+}
+
+/**
+ * Example submission - full display
+ */
+.mod-workshop .submission-full.example .header .title,
+.mod-workshop .submission-full.example .header .userdate {
+    margin: 0px 0px 0px 0px;
+}
+
 /**
  * Elements generated by the workshop renderer
  */
     text-align: center;
 }
 
+.mod-workshop div.buttonsbar .singlebutton {
+    display: inline;
+}
+
 .mod-workshop div.buttonwithhelp div {
     display: inline;
 }
index 621195df950b5ed67aab7f42864484a00675c468..13852a96445f2f404c45f7888b07937c0fe202c1 100644 (file)
@@ -90,7 +90,7 @@ if ($edit and $ownsubmission) {
         $timenow = time();
         if (empty($formdata->id)) {
             $formdata->workshopid     = $workshop->id;
-            $formdata->example        = 0; // todo add examples support
+            $formdata->example        = 0;
             $formdata->authorid       = $USER->id;
             $formdata->timecreated    = $timenow;
             $formdata->feedbackauthorformat = FORMAT_HTML; // todo better default
index d0a787cc3506b8dd7ec724ca4f1484f6b8747e13..d35ed287594a2360f448c65764dd05a3ea74de76 100644 (file)
@@ -83,6 +83,22 @@ case workshop::PHASE_SETUP:
     if (trim(strip_tags($workshop->intro))) {
         echo $OUTPUT->box(format_module_intro('workshop', $workshop, $workshop->cm->id), 'generalbox', 'intro');
     }
+    if ($workshop->useexamples and has_capability('mod/workshop:manageexamples', $PAGE->context)) {
+        echo $OUTPUT->box_start('generalbox examples');
+        echo $OUTPUT->heading(get_string('examplesubmissions', 'workshop'), 3);
+        if (! $examples = $workshop->get_examples()) {
+            echo $OUTPUT->container(get_string('noexamples', 'workshop'), 'noexamples');
+        }
+        foreach ($examples as $example) {
+            echo $wsoutput->example_summary($example);
+        }
+        $editbutton                 = new html_form();
+        $editbutton->method         = 'get';
+        $editbutton->button->text   = get_string('exampleadd', 'workshop');
+        $editbutton->url            = new moodle_url($workshop->example_url(0), array('edit' => 'on'));
+        echo $OUTPUT->button($editbutton);
+        echo $OUTPUT->box_end();
+    }
     break;
 case workshop::PHASE_SUBMISSION:
     if (trim(strip_tags($workshop->instructauthors))) {
@@ -91,22 +107,26 @@ case workshop::PHASE_SUBMISSION:
         echo $OUTPUT->box(format_text($instructions, $workshop->instructauthorsformat), array('generalbox', 'instructions'));
     }
     if (has_capability('mod/workshop:submit', $PAGE->context)) {
+        echo $OUTPUT->box_start('generalbox ownsubmission');
+        echo $OUTPUT->heading(get_string('yoursubmission', 'workshop'), 3);
         if ($submission = $workshop->get_submission_by_author($USER->id)) {
-            echo $OUTPUT->box_start('generalbox mysubmission');
             echo $wsoutput->submission_summary($submission, true);
-            if ($workshop->submitting_allowed()) {
-                $editbutton                 = new html_form();
-                $editbutton->method         = 'get';
-                $editbutton->button->text   = get_string('editsubmission', 'workshop');
-                $editbutton->url            = new moodle_url($workshop->submission_url(), array('edit' => 'on', 'id' => $submission->id));
-                echo $OUTPUT->button($editbutton);
-            }
-            echo $OUTPUT->box_end();
+        } else {
+            echo $OUTPUT->container(get_string('noyoursubmission', 'workshop'));
         }
+        if ($workshop->submitting_allowed()) {
+            $editbutton                 = new html_form();
+            $editbutton->method         = 'get';
+            $editbutton->button->text   = get_string('editsubmission', 'workshop');
+            $editbutton->url            = new moodle_url($workshop->submission_url(), array('edit' => 'on'));
+            echo $OUTPUT->button($editbutton);
+        }
+        echo $OUTPUT->box_end();
     }
     if (has_capability('mod/workshop:viewallsubmissions', $PAGE->context)) {
         $shownames = has_capability('mod/workshop:viewauthornames', $PAGE->context);
         echo $OUTPUT->box_start('generalbox allsubmissions');
+        echo $OUTPUT->heading(get_string('allsubmissions', 'workshop'), 3);
         if (! $submissions = $workshop->get_submissions('all')) {
             echo $OUTPUT->container(get_string('nosubmissions', 'workshop'), 'nosubmissions');
         }