MDL-71691 core_course: activity styling

This commit is contained in:
Bas Brands
2021-12-08 13:14:05 +01:00
parent cdb651d46a
commit c68813be08
21 changed files with 658 additions and 214 deletions
@@ -124,7 +124,7 @@ class block_site_main_menu extends block_list {
$mod
);
$menu = $controlmenu->get_action_menu();
$menu = $controlmenu->get_action_menu($OUTPUT);
// Add a move primary action.
$menu->add(
@@ -118,7 +118,7 @@ class block_social_activities extends block_list {
['disableindentation' => true]
);
$menu = $controlmenu->get_action_menu();
$menu = $controlmenu->get_action_menu($OUTPUT);
// Add a move primary action.
$menu->add(
@@ -25,6 +25,7 @@
namespace core_courseformat\output\local\content;
use cm_info;
use context_module;
use core\activity_dates;
use core_completion\cm_completion_details;
use core_courseformat\base as course_format;
@@ -124,7 +125,7 @@ class cm implements renderable, templatable {
// Grouping activity.
$groupinglabel = $mod->get_grouping_label($displayoptions['textclasses']);
$activityinfodata = null;
$activityinfodata = (object) ['hasdates' => false, 'hascompletion' => false];
// - There are activity dates to be shown; or
// - Completion info needs to be displayed
// * The activity tracks completion; AND
@@ -154,15 +155,20 @@ class cm implements renderable, templatable {
$this->displayoptions
);
$modavailability = $availability->export_for_template($output);
$data = (object)[
'cmname' => $cmname->export_for_template($output),
'grouping' => $groupinglabel,
'afterlink' => $mod->afterlink,
'altcontent' => $mod->get_formatted_content(['overflowdiv' => true, 'noclean' => true]),
'modavailability' => $availability->export_for_template($output),
'modavailability' => $mod->visible ? $modavailability : null,
'modname' => get_string('pluginname', 'mod_' . $mod->modname),
'url' => $mod->url,
'activityinfo' => $activityinfodata,
'activityname' => $mod->get_formatted_name(),
'textclasses' => $displayoptions['textclasses'],
'classlist' => []
];
if (!empty($mod->indent) && $format->uses_indentation()) {
@@ -172,13 +178,33 @@ class cm implements renderable, templatable {
}
}
if (!empty($data->cmname)) {
$data->hasname = true;
}
$data->altcontent = (empty($data->altcontent)) ? false : $data->altcontent;
$data->hasname = !empty($data->cmname['displayvalue']);
if (!empty($data->url)) {
$data->hasurl = true;
}
if (!$mod->visible) {
// This module is hidden but current user has capability to see it.
$data->modhiddenfromstudents = true;
} else if ($mod->is_stealth()) {
// This module is available but is normally not displayed on the course page
// (this user can see it because they can manage it).
$data->modstealth = true;
}
if ($mod->modname == 'label' &&
!$modavailability->hasmodavailability &&
!$activityinfodata->hascompletion &&
!isset($data->modhiddenfromstudents) &&
!isset($data->modstealth) &&
!$format->show_editor()
) {
$data->modinline = true;
}
$returnsection = $format->get_section_number();
if ($format->show_editor()) {
@@ -191,13 +217,15 @@ class cm implements renderable, templatable {
);
$data->controlmenu = $controlmenu->export_for_template($output);
// Move and select options.
if ($format->supports_components()) {
$data->moveicon = $output->pix_icon('i/dragdrop', '', 'moodle', ['class' => 'editing_move dragicon']);
} else {
// Add the legacy YUI move link.
$data->moveicon = course_get_cm_move($mod, $returnsection);
}
// Move and select options.
$modcontext = context_module::instance($mod->id);
}
return $data;
@@ -206,10 +234,6 @@ class cm implements renderable, templatable {
/**
* Returns the CSS classes for the activity name/content
*
* For items which are hidden, unavailable or stealth but should be displayed
* to current user ($mod->is_visible_on_course_page()), we show those as dimmed.
* Students will also see as dimmed activities names that are not yet available
* but should still be displayed (without link) with availability info.
*/
protected function load_classes() {
@@ -222,23 +246,10 @@ class cm implements renderable, templatable {
$conditionalhidden = !$info->is_available_for_all();
$accessiblebutdim = (!$mod->visible || $conditionalhidden) &&
has_capability('moodle/course:viewhiddenactivities', $mod->context);
if ($accessiblebutdim) {
$linkclasses .= ' dimmed';
$textclasses .= ' dimmed_text';
if ($conditionalhidden) {
$linkclasses .= ' conditionalhidden';
$textclasses .= ' conditionalhidden';
}
if ($accessiblebutdim && $conditionalhidden) {
$linkclasses .= ' conditionalhidden';
$textclasses .= ' conditionalhidden';
}
if ($mod->is_stealth()) {
// Stealth activity is the one that is not visible on course page.
// It still may be displayed to the users who can manage it.
$linkclasses .= ' stealth';
$textclasses .= ' stealth';
}
} else {
$linkclasses .= ' dimmed';
$textclasses .= ' dimmed dimmed_text';
}
$this->linkclasses = $linkclasses;
$this->textclasses = $textclasses;
@@ -78,6 +78,7 @@ class availability extends section_avalability {
$data = (object)[
'info' => $this->get_info($output),
'hasmodavailability' => false,
];
if (!empty($data->info)) {
@@ -124,17 +125,6 @@ class availability extends section_avalability {
// information that module is not available to all/some students.
$modcontext = $mod->context;
$canviewhidden = has_capability('moodle/course:viewhiddenactivities', $modcontext);
if ($canviewhidden && !$mod->visible) {
// This module is hidden but current user has capability to see it.
// Do not display the availability info if the whole section is hidden.
if ($section->visible) {
$info[] = $this->availability_info(get_string('hiddenfromstudents'), 'ishidden');
}
} else if ($mod->is_stealth()) {
// This module is available but is normally not displayed on the course page
// (this user can see it because they can manage it).
$info[] = $this->availability_info(get_string('hiddenoncoursepage'), 'isstealth');
}
if ($canviewhidden && !empty($CFG->enableavailability)) {
// Display information about conditional availability.
@@ -82,7 +82,7 @@ class controlmenu implements renderable, templatable {
$mod = $this->mod;
$menu = $this->get_action_menu();
$menu = $this->get_action_menu($output);
if (empty($menu)) {
return new stdClass();
@@ -106,10 +106,10 @@ class controlmenu implements renderable, templatable {
* Generate the aciton menu element.
*
* This method is public in case some block needs to modify the menu before output it.
*
* @param \renderer_base $output typically, the renderer that's calling this function
* @return aciton_menu the activity action menu
*/
public function get_action_menu(): ?action_menu {
public function get_action_menu(\renderer_base $output): ?action_menu {
if (!empty($this->menu)) {
return $this->menu;
@@ -126,7 +126,8 @@ class controlmenu implements renderable, templatable {
// Convert control array into an action_menu.
$menu = new action_menu();
$menu->set_alignment(action_menu::TR, action_menu::BR);
$menu->set_menu_trigger(get_string('edit'));
$icon = $output->pix_icon('i/menu', get_string('edit'));
$menu->set_menu_trigger($icon, 'btn btn-icon d-flex align-items-center justify-content-center');
$menu->attributes['class'] .= ' section-cm-edit-actions commands';
@@ -106,6 +106,8 @@ class title implements renderable, templatable {
'instancename' => $mod->get_formatted_name(),
'uservisible' => $mod->uservisible,
'icon' => $mod->get_icon_url(),
'modname' => $mod->modname,
'pluginname' => get_string('pluginname', 'mod_' . $mod->modname),
'linkclasses' => $displayoptions['linkclasses'],
'textclasses' => $displayoptions['textclasses'],
];
@@ -21,68 +21,95 @@
Example context (json):
{
"cmname": "<a class=\"aalink\" href=\"#\"><span class=\"instancename\">Activity example</span></a>",
"cmname": {
"displayvalue" : "<a class=\"aalink\" href=\"#\"><span class=\"instancename\">Activity example</span></a>"
},
"hasname": "true",
"moveicon": "<i>[Move]</i>",
"indent": 2,
"afterlink": "<span class=\"badge badge-primary\">30 unread messages</span>",
"hasextras": true,
"extras": ["<span class=\"badge badge-secondary\">[extras]</span>"],
"activityinfo": {
"hasmodavailability": true,
"activityname": "Activity example",
"hascompletion": true,
"uservisible": true,
"hasdates": true,
"isautomatic": true,
"istrackeduser": true,
"activitydates": [{ "label": "Opens:", "timestamp": 1293876000 }],
"completiondetails": [{ "statusincomplete": 1, "description": "Receive a grade" }]
"activitydates": [
{
"label": "Opens:",
"datestring": "6 April 2021, 6:46 PM"
}
],
"completiondetails": [
{
"statuscomplete": 1,
"description": "Viewed"
},
{
"statusincomplete": 1,
"description": "Receive a grade"
}
]
},
"availability": "<div><span class=\"badge badge-info\">Restricted</span> Available from <strong>3 Dec 2029</strong></div>"
"modstealth": true
}
}}
<div>
<div class="mod-indent-outer w-100">
{{#moveicon}} {{{moveicon}}} {{/moveicon}}
{{! This div is used to indent the content. }}
<div class="mod-indent {{#indent}}mod-indent-{{indent}}{{/indent}} {{#hugeindent}}mod-indent-huge{{/hugeindent}}"></div>
{{! Start a wrapper for the actual content to keep the indentation consistent. }}
<div>
{{! Display the link to the module (or do nothing if module has no url). }}
{{#hasname}}
<div class="activityinstance">
{{#cmname}} {{> core/inplace_editable }} {{/cmname}}
{{{grouping}}}
{{{afterlink}}}
</div>
<div class="activity-item {{#modstealth}}hiddenactivity{{/modstealth}}{{!
}}{{#modhiddenfromstudents}}hiddenactivity{{/modhiddenfromstudents}}{{!
}}{{#modinline}}activityinline{{/modinline}}" data-activityname="{{activityname}}">
{{#moveicon}} {{{moveicon}}} {{/moveicon}}
<div class="activity-basis d-flex align-items-center">
<div class="d-flex flex-column flex-md-row w-100 align-self-start">
{{^hasname}}
{{> core_courseformat/local/content/cm/badges }}
{{/hasname}}
{{! If there is content but NO link (eg label), then display the
content here (BEFORE any icons). In this case cons must be
displayed after the content so that it makes more sense visually
and for accessibility reasons, e.g. if you have a one-line label
it should work similarly (at least in terms of ordering) to an
activity. }}
{{^hasurl}}
<div class="contentwithoutlink {{textclasses}}"> {{{altcontent}}} </div>
{{/hasurl}}
{{#controlmenu}}
{{> core_courseformat/local/content/cm/controlmenu }}
{{/controlmenu}}
{{#cmname}} {{> core/inplace_editable }} {{/cmname}}
{{#afterlink}}
<div class="afterlink">
{{{afterlink}}}
</div>
{{/afterlink}}
{{#activityinfo}}
{{> core_course/activity_info}}
{{/activityinfo}}
{{#modavailability}}
{{> core_courseformat/local/content/cm/availability }}
{{/modavailability}}
{{#hasurl}}
<div class="contentafterlink {{textclasses}}">
{{{altcontent}}}
{{^hasname}} {{{grouping}}} {{/hasname}}
<div class="activity-info mt-1 mt-md-0">
{{> core_courseformat/local/content/cm/activity_info}}
</div>
{{/hasurl}}
{{/activityinfo}}
</div>
{{#controlmenu}}
<div class="activity-actions align-self-start">
{{> core_courseformat/local/content/cm/controlmenu }}
</div>
{{/controlmenu}}
</div>
{{#hasname}}
{{> core_courseformat/local/content/cm/badges }}
{{/hasname}}
<div class="description">
{{#activityinfo}}
{{#hasdates}}
<div data-region="activity-dates" class="activity-dates small course-description-item">
<div class="description-inner">
{{#activitydates}}
{{>core_course/activity_date}}
{{/activitydates}}
</div>
</div>
{{/hasdates}}
{{/activityinfo}}
{{#altcontent}}
<div class="activity-altcontent {{#hasname}}course-description-item small{{/hasname}}{{^hasname}}contentwithoutlink{{/hasname}} d-flex">
<div class="flex-fill description-inner">
{{{altcontent}}}
</div>
</div>
{{/altcontent}}
{{#modavailability}}
{{> core_courseformat/local/content/cm/availability }}
{{/modavailability}}
</div>
</div>
@@ -0,0 +1,62 @@
{{!
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/>.
}}
{{!
@template core_courseformat/local/content/cm/activity_info
Container to display activity information on the course page such as:
- Activity completion requirements (automatic completion)
- Manual completion button
Example context (json):
{
"activityname": "Course announcements",
"hascompletion": true,
"uservisible": true,
"isautomatic": true,
"showmanualcompletion": true,
"completiondetails": [
{
"statuscomplete": 1,
"description": "Viewed"
},
{
"statusincomplete": 1,
"description": "Receive a grade"
}
]
}
}}
<div data-region="activity-information" data-activityname="{{activityname}}" class="activity-information">
{{#hascompletion}}
{{#uservisible}}
<div data-region="completion-info">
{{#isautomatic}}
<div class="automatic-completion-conditions" data-region ="completionrequirements" role="list" aria-label="{{#str}}completionrequirements, core_course, {{activityname}}{{/str}}">
{{#completiondetails}}
{{> core_course/completion_automatic }}
{{/completiondetails}}
</div>
{{/isautomatic}}
{{^isautomatic}}
{{#showmanualcompletion}}
{{> core_course/completion_manual }}
{{/showmanualcompletion}}
{{/isautomatic}}
</div>
{{/uservisible}}
{{/hascompletion}}
</div>
@@ -36,12 +36,14 @@
}}
{{#hasmodavailability}}
{{#info}}
<div class="availabilityinfo {{classes}}">
<div class="availabilityinfo small course-description-item {{classes}}">
{{^isrestricted}}
<span class="badge badge-info">{{{text}}}</span>
<span class="badge badge-pill badge-warning">{{{text}}}</span>
{{/isrestricted}}
{{#isrestricted}}
<span class="badge badge-info">{{#str}}restricted, core{{/str}}</span> {{{text}}}
<div class="description-inner">
{{#pix}}t/unlock, core{{/pix}} {{{text}}}
</div>
{{/isrestricted}}
</div>
{{/info}}
@@ -0,0 +1,39 @@
{{!
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/>.
}}
{{!
@template core_courseformat/local/content/cm/badges
Convenience mustache to displays if an activity is in hidden or stealth mode.
Format plugins are free to implement an alternative inplace editable for activities.
Example context (json):
{
"modhiddenfromstudents" : "1",
"modstealth" : "1"
}
}}
{{#modhiddenfromstudents}}
<div class="my-1 d-flex align-items-center">
<span class="badge badge-pill badge-warning">{{#str}}hiddenfromstudents{{/str}}</span>
</div>
{{/modhiddenfromstudents}}
{{#modstealth}}
<div class="my-1 d-flex align-items-center">
<span class="badge badge-pill badge-warning">{{#str}}hiddenoncoursepage{{/str}}</span>
</div>
{{/modstealth}}
@@ -26,26 +26,35 @@
"uservisible": true,
"icon": "../../../pix/help.svg",
"onclick": "alert('ok')",
"pluginname": "File",
"altname": "PDF file",
"linkclasses": "",
"textclasses": ""
}
}}
{{#url}}
{{#uservisible}}
<a href="{{url}}" class="aalink {{linkclasses}}" onclick="{{{onclick}}}">
<img class="iconlarge activityicon" src="{{icon}}" alt="" role="presentation" aria-hidden="true" />
<span class="instancename">
{{{instancename}}} {{{altname}}}
</span>
</a>
{{/uservisible}}
{{^uservisible}}
<div class="{{textclasses}}">
<img class="iconlarge activityicon" src="{{icon}}" alt="" role="presentation" aria-hidden="true" />
<span class="instancename">
{{{instancename}}} {{{altname}}}
</span>
<div class="activity-instance d-flex flex-column">
<div class="activitytitle media {{textclasses}} modtype_{{modname}} position-relative align-self-start">
<div class="activityiconcontainer courseicon align-self-start mr-3">
<img src="{{{icon}}}" class="activityicon " alt="{{{modname}}} icon">
</div>
<div class="media-body align-self-center">
<div class="text-uppercase small">
{{{pluginname}}}
</div>
<div class="activityname">
{{#uservisible}}
<a href="{{url}}" class="{{linkclasses}} aalink stretched-link" onclick="{{{onclick}}}">
<span class="instancename">{{{instancename}}} {{{altname}}}</span>
</a>
{{/uservisible}}
{{^uservisible}}
<span class="instancename">
{{{instancename}}} {{{altname}}}
</span>
{{/uservisible}}
</div>
</div>
</div>
{{/uservisible}}
</div>
{{/url}}
@@ -41,7 +41,9 @@
<span class="badge badge-pill badge-warning">{{{text}}}</span>
{{/isrestricted}}
{{#isrestricted}}
{{#pix}}t/unlock, core{{/pix}}</span> {{{text}}}
<div class="description-inner">
{{#pix}}t/unlock, core{{/pix}} {{{text}}}
</div>
{{/isrestricted}}
</div>
{{/info}}
@@ -37,7 +37,7 @@
}
}}
<li
class="activity {{module}} modtype_{{module}} {{extraclasses}} {{#hasinfo}}hasinfo{{/hasinfo}}"
class="activity activity-wrapper {{module}} modtype_{{module}} {{extraclasses}} {{#hasinfo}}hasinfo{{/hasinfo}}"
id="module-{{id}}"
data-for="cmitem"
data-id="{{id}}"
@@ -39,7 +39,7 @@
"cmname": "<a class=\"aalink\" href=\"#\"><span class=\"instancename\">Assign example</span></a>",
"hasname": "true"
},
"id": 3,
"id": 4,
"module": "assign",
"extraclasses": ""
}
@@ -56,7 +56,7 @@
{{#showmovehere}}
<p>{{movingstr}} (<a href="{{{cancelcopyurl}}}">{{#str}} cancel {{/str}}</a>)</p>
{{/showmovehere}}
<ul class="section img-text {{#hascms}} d-block {{/hascms}}" data-for="cmlist">
<ul class="section m-0 p-0 img-text {{#hascms}} d-block {{/hascms}}" data-for="cmlist">
{{#cms}}
{{#showmovehere}}
<li class="movehere">
-35
View File
@@ -1958,41 +1958,6 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
);
}
// Groupmode.
if ($hasmanageactivities && !$mod->coursegroupmodeforce) {
if (plugin_supports('mod', $mod->modname, FEATURE_GROUPS, false)) {
if ($mod->effectivegroupmode == SEPARATEGROUPS) {
$nextgroupmode = VISIBLEGROUPS;
$grouptitle = $str->groupsseparate;
$actionname = 'groupsseparate';
$nextactionname = 'groupsvisible';
$groupimage = 'i/groups';
} else if ($mod->effectivegroupmode == VISIBLEGROUPS) {
$nextgroupmode = NOGROUPS;
$grouptitle = $str->groupsvisible;
$actionname = 'groupsvisible';
$nextactionname = 'groupsnone';
$groupimage = 'i/groupv';
} else {
$nextgroupmode = SEPARATEGROUPS;
$grouptitle = $str->groupsnone;
$actionname = 'groupsnone';
$nextactionname = 'groupsseparate';
$groupimage = 'i/groupn';
}
$actions[$actionname] = new action_menu_link_primary(
new moodle_url($baseurl, array('id' => $mod->id, 'groupmode' => $nextgroupmode)),
new pix_icon($groupimage, '', 'moodle', array('class' => 'iconsmall')),
$grouptitle,
array('class' => 'editing_'. $actionname, 'data-action' => $nextactionname,
'aria-live' => 'assertive', 'data-sectionreturn' => $sr)
);
} else {
$actions['nogroupsupport'] = new action_menu_filler();
}
}
// Assign.
if (has_capability('moodle/role:assign', $modcontext)){
$actions['assign'] = new action_menu_link_secondary(
@@ -29,25 +29,27 @@
}}
{{#istrackeduser}}
{{#statuscomplete}}
<span class="badge badge-success rounded mb-1" role="listitem" {{!
<span class="badge badge-pill alert-success icon-no-margin" role="listitem" {{!
}}{{#accessibledescription}}{{!
}}title="{{.}}" {{!
}}aria-label="{{.}}" {{!
}}{{/accessibledescription}}>
{{#pix}}i/checked{{/pix}}
<strong>{{#str}}completion_automatic:done, core_course{{/str}}</strong> <span class="font-weight-normal">{{description}}</span>
</span>
{{/statuscomplete}}
{{#statuscompletefail}}
<span class="badge badge-danger rounded mb-1" role="listitem" {{!
<span class="badge badge-pill alert-danger icon-no-margin" role="listitem" {{!
}}{{#accessibledescription}}{{!
}}title="{{.}}" {{!
}}aria-label="{{.}}" {{!
}}{{/accessibledescription}}>
{{#pix}}e/cancel{{/pix}}
<strong>{{#str}}completion_automatic:failed, core_course{{/str}}</strong> <span class="font-weight-normal">{{description}}</span>
</span>
{{/statuscompletefail}}
{{#statusincomplete}}
<span class="badge badge-secondary rounded mb-1" role="listitem" {{!
<span class="badge badge-pill badge-light" role="listitem" {{!
}}{{#accessibledescription}}{{!
}}title="{{.}}" {{!
}}aria-label="{{.}}" {{!
@@ -57,7 +59,7 @@
{{/statusincomplete}}
{{/istrackeduser}}
{{^istrackeduser}}
<span class="badge badge-secondary rounded mb-1" role="listitem">
<span class="badge badge-pill badge-light" role="listitem">
<span class="font-weight-normal">{{description}}</span>
</span>
{{/istrackeduser}}
+3 -3
View File
@@ -28,7 +28,7 @@
}}
{{#istrackeduser}}
{{#overallcomplete}}
<button class="btn btn-outline-success" data-action="toggle-manual-completion" data-toggletype="manual:undo" data-cmid="{{cmid}}" data-activityname="{{activityname}}" data-withavailability="{{withavailability}}" {{!
<button class="btn btn-success btn-sm text-nowrap" data-action="toggle-manual-completion" data-toggletype="manual:undo" data-cmid="{{cmid}}" data-activityname="{{activityname}}" data-withavailability="{{withavailability}}" {{!
}}{{#accessibledescription}}{{!
}}title="{{.}}" {{!
}}aria-label="{{.}}" {{!
@@ -41,7 +41,7 @@
</button>
{{/overallcomplete}}
{{#overallincomplete}}
<button class="btn btn-outline-secondary" data-action="toggle-manual-completion" data-toggletype="manual:mark-done" data-cmid="{{cmid}}" data-activityname="{{activityname}}" data-withavailability="{{withavailability}}" {{!
<button class="btn btn-outline-secondary btn-sm text-nowrap" data-action="toggle-manual-completion" data-toggletype="manual:mark-done" data-cmid="{{cmid}}" data-activityname="{{activityname}}" data-withavailability="{{withavailability}}" {{!
}}{{#accessibledescription}}{{!
}}title="{{.}}" {{!
}}aria-label="{{.}}" {{!
@@ -55,7 +55,7 @@
{{/overallincomplete}}
{{/istrackeduser}}
{{^istrackeduser}}
<button class="btn btn-outline-secondary" disabled>
<button class="btn btn-outline-secondary btn-sm text-nowrap" disabled>
{{#str}} completion_manual:markdone, core_course {{/str}}
</button>
{{/istrackeduser}}
+2 -2
View File
@@ -5682,13 +5682,13 @@ function forum_cm_info_view(cm_info $cm) {
if (forum_tp_can_track_forums()) {
if ($unread = forum_tp_count_forum_unread_posts($cm, $cm->get_course())) {
$out = '<span class="unread"> <a href="' . $cm->url . '#unread">';
$out = '<span class="badge badge-secondary">';
if ($unread == 1) {
$out .= get_string('unreadpostsone', 'forum');
} else {
$out .= get_string('unreadpostsnumber', 'forum', $unread);
}
$out .= '</a></span>';
$out .= '</span>';
$cm->set_after_link($out);
}
}
+163 -19
View File
@@ -172,12 +172,11 @@ body:not(.editing) .sitetopic ul.section {
padding-right: 200px;
}
.editing_move {
/* Move the move icon to the start of the line */
position: absolute;
left: 0;
top: 0;
display: flex;
left: 5px;
top: 5px;
}
.mod-indent-outer {
/**
* Add appropriate padding such that nothing overlaps the
@@ -187,6 +186,12 @@ body:not(.editing) .sitetopic ul.section {
}
}
}
.activity .editing_move_activity {
position: absolute;
display: flex;
left: 5px;
top: 5px;
}
// Remove old spinners if the reactive state is ready.
.course-content .stateready .section .spinner {
display: none;
@@ -271,7 +276,10 @@ body:not(.editing) .sitetopic ul.section {
}
}
.section li.activity {
// The activity-wrapper class ensures these styles are not used when the new activity styles
// from MDL-71691 are not affected. As soons as MDL-72656 is integrated and these styles
// are removed the core_courseformat/local/content/cm template no longer needs this class.
.section li.activity:not(.activity-wrapper) {
padding: 0.2em;
clear: both;
@@ -302,8 +310,8 @@ body:not(.editing) .sitetopic ul.section {
padding-left: 30px;
}
.section .activity .availabilityinfo,
.section .activity .contentafterlink {
.section.main:not(.course-section) .activity .availabilityinfo,
.section.main:not(.course-section) .activity .contentafterlink {
margin-top: 0.5em;
margin-left: 30px;
}
@@ -312,7 +320,7 @@ body:not(.editing) .sitetopic ul.section {
margin: .5em 0;
}
.editing .section {
.editing .section.main:not(.course-section) {
.activity:hover,
.activity.action-menu-shown,
.sectionname:hover {
@@ -399,7 +407,7 @@ body:not(.editing) .sitetopic ul.section {
margin-top: 0;
}
.course-content ul li.section.main {
.course-content ul li.section.main:not(.course-section) {
border-bottom: $border-width solid $table-border-color;
margin-top: 0;
@@ -408,7 +416,7 @@ body:not(.editing) .sitetopic ul.section {
}
}
.course-content ul li.section.hidden {
.course-content ul li.section.hidden:not(.course-section) {
.sectionname > span,
.content > div.summary,
.activity .activityinstance {
@@ -566,8 +574,8 @@ body:not(.editing) .sitetopic ul.section {
margin-right: 5px;
}
.path-site li.activity > div,
.path-course-view li.activity > div {
.path-site li.activity > div:not(.activity-item),
.path-course-view li.activity > div:not(.activity-item) {
position: relative;
padding: 0 16px 0 0; /* to accommodate the floated completion icon with highlighting */
}
@@ -1290,6 +1298,12 @@ span.editinstructions {
}
}
$activity-item-background: theme-color-level('primary', -12) !default;
$activity-item-border: theme-color-level('primary', -2) !default;
$activity-item-color: $body-color;
$activity-item-hover: theme-color-level('primary', -12) !default;
$activity-add-hover: theme-color-level('primary', -10) !default;
.activity-add,
.block-add {
@if $enable-rounded {
@@ -1303,7 +1317,7 @@ span.editinstructions {
}
&:hover {
cursor: pointer;
background-color: $primary-light-hover;
background-color: $activity-add-hover;
}
width: 100%;
border-radius: 4px;
@@ -1346,7 +1360,7 @@ span.editinstructions {
}
.sectionbadges .badge {
margin-left: 0.5rem;
margin-left: map-get($spacers, 2);
}
.course-section-header.draggable {
@@ -1365,10 +1379,10 @@ span.editinstructions {
}
&.section-summary {
padding-left: 1rem;
padding-right: 1rem;
margin-bottom: 0.5rem;
margin-top: 0.5rem;
padding-left: map-get($spacers, 3);
padding-right: map-get($spacers, 3);
margin-bottom: map-get($spacers, 2);
margin-top: map-get($spacers, 2);
@if $enable-rounded {
@include border-radius($border-radius-lg);
}
@@ -1393,7 +1407,7 @@ $activity-iconcontainer-height: 50px;
justify-content: center;
align-items: center;
background-color: $gray-100;
border-radius: 4px;
border-radius: $border-radius;
padding: 0.7rem;
.activityicon {
@@ -1422,6 +1436,8 @@ $activity-iconcontainer-height: 50px;
&:first-child {
margin-top: map-get($spacers, 3);
padding-top: map-get($spacers, 3);
border-top-left-radius: $border-radius;
border-top-right-radius: $border-radius;
.description-inner {
padding-top: 0;
@@ -1430,6 +1446,8 @@ $activity-iconcontainer-height: 50px;
&:last-child {
padding-bottom: map-get($spacers, 3);
border-bottom-left-radius: $border-radius;
border-bottom-right-radius: $border-radius;
.description-inner {
padding-bottom: 0;
@@ -1437,3 +1455,129 @@ $activity-iconcontainer-height: 50px;
}
}
}
.activity-item {
position: relative;
margin: map-get($spacers, 2) 0;
@if $enable-rounded {
@include border-radius($border-radius-lg);
}
&:not(.activityinline) {
border: $border-width solid $border-color;
padding: map-get($spacers, 3);
}
&.activityinline {
padding: map-get($spacers, 3) 0;
}
&.hiddenactivity {
background-color: $gray-100;
.description .course-description-item,
.activityiconcontainer,
.badge {
mix-blend-mode: multiply;
}
}
.activity-actions {
.actions {
position: relative;
}
.dropdown-toggle::after {
display: none;
}
}
.inplaceeditable {
display: flex;
flex: 0 1 auto;
max-width: 100%;
}
.inplaceeditable .quickeditlink,
.afterlink {
margin: 1.5rem 0 0.2rem 0.5rem;
}
.action-menu-item {
display: flex;
align-items: center;
}
.action-menu-item .filler {
display: none;
}
.no-overflow {
width: 100%;
}
@include media-breakpoint-down(sm) {
.badge {
white-space: normal;
text-align: left;
}
}
@include media-breakpoint-up(md) {
.automatic-completion-conditions {
display: flex;
flex-direction: column;
align-items: flex-end;
}
&:not(.activityinline) {
padding: map-get($spacers, 4);
}
.activity-info,
.activity-actions {
margin-left: auto;
padding-left: map-get($spacers, 2);
align-self: start;
display: flex;
flex-direction: column;
justify-content: center;
}
}
}
.editing .activity-item {
cursor: move;
.a {
cursor: pointer;
}
&:hover {
@include alert-variant($activity-item-hover, $activity-item-border, $activity-item-color);
.description .course-description-item,
.activityiconcontainer,
.badge {
mix-blend-mode: multiply;
}
}
}
.section .draggable .activity-item .dragicon {
display: none;
}
.automatic-completion-conditions .badge {
font-size: 80%;
padding: map-get($spacers, 2);
margin-top: map-get($spacers, 1);
.icon {
width: 0.7rem;
height: 0.7rem;
font-size: 0.7rem;
}
&:first-child {
margin-top: 0;
}
}
+115 -21
View File
@@ -13780,10 +13780,10 @@ body:not(.editing) .sitetopic ul.section {
padding-right: 200px; }
.editing .section .activity .editing_move {
/* Move the move icon to the start of the line */
position: absolute;
left: 0;
top: 0; }
display: flex;
left: 5px;
top: 5px; }
.editing .section .activity .mod-indent-outer {
/**
@@ -13792,6 +13792,12 @@ body:not(.editing) .sitetopic ul.section {
*/
padding-left: 2rem; }
.editing .activity .editing_move_activity {
position: absolute;
display: flex;
left: 5px;
top: 5px; }
.editing .course-content .stateready .section .spinner {
display: none; }
@@ -13845,14 +13851,14 @@ body:not(.editing) .sitetopic ul.section {
.section .activity.modtype_label.label.hasinfo i:last-child {
margin-bottom: 0; }
.section li.activity {
.section li.activity:not(.activity-wrapper) {
padding: 0.2em;
clear: both; }
.section li.activity.hasinfo {
.section li.activity:not(.activity-wrapper).hasinfo {
border-bottom: 1px solid #dee2e6;
padding-top: 1rem;
padding-bottom: 1rem; }
.section li.activity.hasinfo:last-child {
.section li.activity:not(.activity-wrapper).hasinfo:last-child {
border-bottom: 0;
padding-bottom: 0; }
@@ -13865,17 +13871,17 @@ body:not(.editing) .sitetopic ul.section {
.section .activity .activityinstance .groupinglabel {
padding-left: 30px; }
.section .activity .availabilityinfo,
.section .activity .contentafterlink {
.section.main:not(.course-section) .activity .availabilityinfo,
.section.main:not(.course-section) .activity .contentafterlink {
margin-top: 0.5em;
margin-left: 30px; }
.section .activity .contentafterlink p {
margin: .5em 0; }
.editing .section .activity:hover,
.editing .section .activity.action-menu-shown,
.editing .section .sectionname:hover {
.editing .section.main:not(.course-section) .activity:hover,
.editing .section.main:not(.course-section) .activity.action-menu-shown,
.editing .section.main:not(.course-section) .sectionname:hover {
background-color: rgba(0, 0, 0, 0.03); }
.course-content .current {
@@ -13942,15 +13948,15 @@ body:not(.editing) .sitetopic ul.section {
.course-content .single-section .section-navigation .mdl-bottom {
margin-top: 0; }
.course-content ul li.section.main {
.course-content ul li.section.main:not(.course-section) {
border-bottom: 1px solid #dee2e6;
margin-top: 0; }
.course-content ul li.section.main:last-child {
.course-content ul li.section.main:not(.course-section):last-child {
border-bottom: 0; }
.course-content ul li.section.hidden .sectionname > span,
.course-content ul li.section.hidden .content > div.summary,
.course-content ul li.section.hidden .activity .activityinstance {
.course-content ul li.section.hidden:not(.course-section) .sectionname > span,
.course-content ul li.section.hidden:not(.course-section) .content > div.summary,
.course-content ul li.section.hidden:not(.course-section) .activity .activityinstance {
color: #6a737b; }
.course-content ul.topics,
@@ -14057,8 +14063,8 @@ body:not(.editing) .sitetopic ul.section {
.path-course-view .single-section .completionprogress {
margin-right: 5px; }
.path-site li.activity > div,
.path-course-view li.activity > div {
.path-site li.activity > div:not(.activity-item),
.path-course-view li.activity > div:not(.activity-item) {
position: relative;
padding: 0 16px 0 0;
/* to accommodate the floated completion icon with highlighting */ }
@@ -14683,7 +14689,7 @@ span.editinstructions {
justify-content: center;
align-items: center;
background-color: #f8f9fa;
border-radius: 4px;
border-radius: 0.25rem;
padding: 0.7rem; }
.activity-item .activityiconcontainer .activityicon {
margin: 0;
@@ -14703,15 +14709,103 @@ span.editinstructions {
margin-bottom: 0; }
.description .course-description-item:first-child {
margin-top: 1rem;
padding-top: 1rem; }
padding-top: 1rem;
border-top-left-radius: 0.25rem;
border-top-right-radius: 0.25rem; }
.description .course-description-item:first-child .description-inner {
padding-top: 0; }
.description .course-description-item:last-child {
padding-bottom: 1rem; }
padding-bottom: 1rem;
border-bottom-left-radius: 0.25rem;
border-bottom-right-radius: 0.25rem; }
.description .course-description-item:last-child .description-inner {
padding-bottom: 0;
border-bottom: 0; }
.activity-item {
position: relative;
margin: 0.5rem 0;
border-radius: 0.3rem; }
.activity-item:not(.activityinline) {
border: 1px solid #dee2e6;
padding: 1rem; }
.activity-item.activityinline {
padding: 1rem 0; }
.activity-item.hiddenactivity {
background-color: #f8f9fa; }
.activity-item.hiddenactivity .description .course-description-item,
.activity-item.hiddenactivity .activityiconcontainer,
.activity-item.hiddenactivity .badge {
mix-blend-mode: multiply; }
.activity-item .activity-actions .actions {
position: relative; }
.activity-item .activity-actions .dropdown-toggle::after {
display: none; }
.activity-item .inplaceeditable {
display: flex;
flex: 0 1 auto;
max-width: 100%; }
.activity-item .inplaceeditable .quickeditlink,
.activity-item .afterlink {
margin: 1.5rem 0 0.2rem 0.5rem; }
.activity-item .action-menu-item {
display: flex;
align-items: center; }
.activity-item .action-menu-item .filler {
display: none; }
.activity-item .no-overflow {
width: 100%; }
@media (max-width: 767.98px) {
.activity-item .badge {
white-space: normal;
text-align: left; } }
@media (min-width: 768px) {
.activity-item .automatic-completion-conditions {
display: flex;
flex-direction: column;
align-items: flex-end; }
.activity-item:not(.activityinline) {
padding: 1.5rem; }
.activity-item .activity-info,
.activity-item .activity-actions {
margin-left: auto;
padding-left: 0.5rem;
align-self: start;
display: flex;
flex-direction: column;
justify-content: center; } }
.editing .activity-item {
cursor: move; }
.editing .activity-item .a {
cursor: pointer; }
.editing .activity-item:hover {
color: #1d2125;
background-color: #f5f9fc;
border-color: #3584c9; }
.editing .activity-item:hover hr {
border-top-color: #3077b5; }
.editing .activity-item:hover .alert-link {
color: #070808; }
.editing .activity-item:hover .description .course-description-item,
.editing .activity-item:hover .activityiconcontainer,
.editing .activity-item:hover .badge {
mix-blend-mode: multiply; }
.section .draggable .activity-item .dragicon {
display: none; }
.automatic-completion-conditions .badge {
font-size: 80%;
padding: 0.5rem;
margin-top: 0.25rem; }
.automatic-completion-conditions .badge .icon {
width: 0.7rem;
height: 0.7rem;
font-size: 0.7rem; }
.automatic-completion-conditions .badge:first-child {
margin-top: 0; }
/* Anchor link offset fix. This makes hash links scroll 60px down to account for the fixed header. */
:target {
scroll-margin-top: 70px; }
+115 -21
View File
@@ -13780,10 +13780,10 @@ body:not(.editing) .sitetopic ul.section {
padding-right: 200px; }
.editing .section .activity .editing_move {
/* Move the move icon to the start of the line */
position: absolute;
left: 0;
top: 0; }
display: flex;
left: 5px;
top: 5px; }
.editing .section .activity .mod-indent-outer {
/**
@@ -13792,6 +13792,12 @@ body:not(.editing) .sitetopic ul.section {
*/
padding-left: 2rem; }
.editing .activity .editing_move_activity {
position: absolute;
display: flex;
left: 5px;
top: 5px; }
.editing .course-content .stateready .section .spinner {
display: none; }
@@ -13845,14 +13851,14 @@ body:not(.editing) .sitetopic ul.section {
.section .activity.modtype_label.label.hasinfo i:last-child {
margin-bottom: 0; }
.section li.activity {
.section li.activity:not(.activity-wrapper) {
padding: 0.2em;
clear: both; }
.section li.activity.hasinfo {
.section li.activity:not(.activity-wrapper).hasinfo {
border-bottom: 1px solid #dee2e6;
padding-top: 1rem;
padding-bottom: 1rem; }
.section li.activity.hasinfo:last-child {
.section li.activity:not(.activity-wrapper).hasinfo:last-child {
border-bottom: 0;
padding-bottom: 0; }
@@ -13865,17 +13871,17 @@ body:not(.editing) .sitetopic ul.section {
.section .activity .activityinstance .groupinglabel {
padding-left: 30px; }
.section .activity .availabilityinfo,
.section .activity .contentafterlink {
.section.main:not(.course-section) .activity .availabilityinfo,
.section.main:not(.course-section) .activity .contentafterlink {
margin-top: 0.5em;
margin-left: 30px; }
.section .activity .contentafterlink p {
margin: .5em 0; }
.editing .section .activity:hover,
.editing .section .activity.action-menu-shown,
.editing .section .sectionname:hover {
.editing .section.main:not(.course-section) .activity:hover,
.editing .section.main:not(.course-section) .activity.action-menu-shown,
.editing .section.main:not(.course-section) .sectionname:hover {
background-color: rgba(0, 0, 0, 0.03); }
.course-content .current {
@@ -13942,15 +13948,15 @@ body:not(.editing) .sitetopic ul.section {
.course-content .single-section .section-navigation .mdl-bottom {
margin-top: 0; }
.course-content ul li.section.main {
.course-content ul li.section.main:not(.course-section) {
border-bottom: 1px solid #dee2e6;
margin-top: 0; }
.course-content ul li.section.main:last-child {
.course-content ul li.section.main:not(.course-section):last-child {
border-bottom: 0; }
.course-content ul li.section.hidden .sectionname > span,
.course-content ul li.section.hidden .content > div.summary,
.course-content ul li.section.hidden .activity .activityinstance {
.course-content ul li.section.hidden:not(.course-section) .sectionname > span,
.course-content ul li.section.hidden:not(.course-section) .content > div.summary,
.course-content ul li.section.hidden:not(.course-section) .activity .activityinstance {
color: #6a737b; }
.course-content ul.topics,
@@ -14057,8 +14063,8 @@ body:not(.editing) .sitetopic ul.section {
.path-course-view .single-section .completionprogress {
margin-right: 5px; }
.path-site li.activity > div,
.path-course-view li.activity > div {
.path-site li.activity > div:not(.activity-item),
.path-course-view li.activity > div:not(.activity-item) {
position: relative;
padding: 0 16px 0 0;
/* to accommodate the floated completion icon with highlighting */ }
@@ -14683,7 +14689,7 @@ span.editinstructions {
justify-content: center;
align-items: center;
background-color: #f8f9fa;
border-radius: 4px;
border-radius: 0.25rem;
padding: 0.7rem; }
.activity-item .activityiconcontainer .activityicon {
margin: 0;
@@ -14703,15 +14709,103 @@ span.editinstructions {
margin-bottom: 0; }
.description .course-description-item:first-child {
margin-top: 1rem;
padding-top: 1rem; }
padding-top: 1rem;
border-top-left-radius: 0.25rem;
border-top-right-radius: 0.25rem; }
.description .course-description-item:first-child .description-inner {
padding-top: 0; }
.description .course-description-item:last-child {
padding-bottom: 1rem; }
padding-bottom: 1rem;
border-bottom-left-radius: 0.25rem;
border-bottom-right-radius: 0.25rem; }
.description .course-description-item:last-child .description-inner {
padding-bottom: 0;
border-bottom: 0; }
.activity-item {
position: relative;
margin: 0.5rem 0;
border-radius: 0.3rem; }
.activity-item:not(.activityinline) {
border: 1px solid #dee2e6;
padding: 1rem; }
.activity-item.activityinline {
padding: 1rem 0; }
.activity-item.hiddenactivity {
background-color: #f8f9fa; }
.activity-item.hiddenactivity .description .course-description-item,
.activity-item.hiddenactivity .activityiconcontainer,
.activity-item.hiddenactivity .badge {
mix-blend-mode: multiply; }
.activity-item .activity-actions .actions {
position: relative; }
.activity-item .activity-actions .dropdown-toggle::after {
display: none; }
.activity-item .inplaceeditable {
display: flex;
flex: 0 1 auto;
max-width: 100%; }
.activity-item .inplaceeditable .quickeditlink,
.activity-item .afterlink {
margin: 1.5rem 0 0.2rem 0.5rem; }
.activity-item .action-menu-item {
display: flex;
align-items: center; }
.activity-item .action-menu-item .filler {
display: none; }
.activity-item .no-overflow {
width: 100%; }
@media (max-width: 767.98px) {
.activity-item .badge {
white-space: normal;
text-align: left; } }
@media (min-width: 768px) {
.activity-item .automatic-completion-conditions {
display: flex;
flex-direction: column;
align-items: flex-end; }
.activity-item:not(.activityinline) {
padding: 1.5rem; }
.activity-item .activity-info,
.activity-item .activity-actions {
margin-left: auto;
padding-left: 0.5rem;
align-self: start;
display: flex;
flex-direction: column;
justify-content: center; } }
.editing .activity-item {
cursor: move; }
.editing .activity-item .a {
cursor: pointer; }
.editing .activity-item:hover {
color: #1d2125;
background-color: #f5f9fc;
border-color: #3584c9; }
.editing .activity-item:hover hr {
border-top-color: #3077b5; }
.editing .activity-item:hover .alert-link {
color: #070808; }
.editing .activity-item:hover .description .course-description-item,
.editing .activity-item:hover .activityiconcontainer,
.editing .activity-item:hover .badge {
mix-blend-mode: multiply; }
.section .draggable .activity-item .dragicon {
display: none; }
.automatic-completion-conditions .badge {
font-size: 80%;
padding: 0.5rem;
margin-top: 0.25rem; }
.automatic-completion-conditions .badge .icon {
width: 0.7rem;
height: 0.7rem;
font-size: 0.7rem; }
.automatic-completion-conditions .badge:first-child {
margin-top: 0; }
/* Anchor link offset fix. This makes hash links scroll 60px down to account for the fixed header. */
:target {
scroll-margin-top: 60px; }