mirror of
https://github.com/moodle/moodle.git
synced 2025-04-13 12:32:08 +02:00
MDL-65032 mod_forum: Add discussion locking functionality
This commit is contained in:
parent
082740b7c6
commit
2893812eb0
1
mod/forum/amd/build/lock_toggle.min.js
vendored
Normal file
1
mod/forum/amd/build/lock_toggle.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
define(["jquery","core/templates","core/notification","mod_forum/repository","mod_forum/selectors"],function(a,b,c,d,e){var f=function(f){f.on("click",e.lock.toggle,function(e){var f=a(this),g=f.data("forumid"),h=f.data("discussionid"),i=f.data("state");d.setDiscussionLockState(g,h,i).then(function(a){return b.render("mod_forum/discussion_lock_toggle",a)}).then(function(a,c){return b.replaceNode(f,a,c)})["catch"](c.exception),e.preventDefault()})};return{init:function(a){f(a)}}});
|
2
mod/forum/amd/build/repository.min.js
vendored
2
mod/forum/amd/build/repository.min.js
vendored
@ -1 +1 @@
|
||||
define(["core/ajax"],function(a){var b=function(b,c,d){var e={methodname:"mod_forum_set_subscription_state",args:{forumid:b,discussionid:c,targetstate:d}};return a.call([e])[0]},c=function(b,c,d){var e={methodname:"mod_forum_add_discussion_post",args:{postid:b,message:d,subject:c}};return a.call([e])[0]};return{setDiscussionSubscriptionState:b,addDiscussionPost:c}});
|
||||
define(["core/ajax"],function(a){var b=function(b,c,d){var e={methodname:"mod_forum_set_subscription_state",args:{forumid:b,discussionid:c,targetstate:d}};return a.call([e])[0]},c=function(b,c,d){var e={methodname:"mod_forum_add_discussion_post",args:{postid:b,message:d,subject:c}};return a.call([e])[0]},d=function(b,c,d){var e={methodname:"mod_forum_set_lock_state",args:{forumid:b,discussionid:c,targetstate:d}};return a.call([e])[0]};return{setDiscussionSubscriptionState:b,addDiscussionPost:c,setDiscussionLockState:d}});
|
2
mod/forum/amd/build/selectors.min.js
vendored
2
mod/forum/amd/build/selectors.min.js
vendored
@ -1 +1 @@
|
||||
define([],function(){return{subscription:{toggle:"[data-type='subscription-toggle'][data-action='toggle']"},pin:{toggle:".pindiscussion [data-action='toggle']"},post:{post:'[data-region="post"]',action:'[data-region="post-action"]',actionsContainer:'[data-region="post-actions-container"]',forumCoreContent:"[data-region-content='forum-post-core']",forumContent:"[data-content='forum-post']",forumSubject:"[data-region-content='forum-post-core-subject']",inpageReplyLink:"[data-action='collapsible-link']",inpageReplyContent:"[data-content='inpage-reply-content']",inpageReplyForm:"form[data-content='inpage-reply-form']",inpageSubmitBtn:"[data-action='forum-inpage-submit']",repliesContainer:"[data-region='replies-container']",modeSelect:"select[name='mode']"}}});
|
||||
define([],function(){return{subscription:{toggle:"[data-type='subscription-toggle'][data-action='toggle']"},pin:{toggle:".pindiscussion [data-action='toggle']"},post:{post:'[data-region="post"]',action:'[data-region="post-action"]',actionsContainer:'[data-region="post-actions-container"]',forumCoreContent:"[data-region-content='forum-post-core']",forumContent:"[data-content='forum-post']",forumSubject:"[data-region-content='forum-post-core-subject']",inpageReplyLink:"[data-action='collapsible-link']",inpageReplyContent:"[data-content='inpage-reply-content']",inpageReplyForm:"form[data-content='inpage-reply-form']",inpageSubmitBtn:"[data-action='forum-inpage-submit']",repliesContainer:"[data-region='replies-container']",modeSelect:"select[name='mode']"},lock:{toggle:"[data-action='toggle'][data-type='lock-toggle']"}}});
|
68
mod/forum/amd/src/lock_toggle.js
Normal file
68
mod/forum/amd/src/lock_toggle.js
Normal file
@ -0,0 +1,68 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Handle the manual locking of individual discussions
|
||||
*
|
||||
* @module mod_forum/lock_toggle
|
||||
* @package mod_forum
|
||||
* @copyright 2019 Peter Dias <peter@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'core/templates',
|
||||
'core/notification',
|
||||
'mod_forum/repository',
|
||||
'mod_forum/selectors',
|
||||
], function(
|
||||
$,
|
||||
Templates,
|
||||
Notification,
|
||||
Repository,
|
||||
Selectors
|
||||
) {
|
||||
|
||||
/**
|
||||
* Register event listeners for the subscription toggle.
|
||||
*
|
||||
* @param {object} root The discussion list root element
|
||||
*/
|
||||
var registerEventListeners = function(root) {
|
||||
root.on('click', Selectors.lock.toggle, function(e) {
|
||||
var toggleElement = $(this);
|
||||
var forumId = toggleElement.data('forumid');
|
||||
var discussionId = toggleElement.data('discussionid');
|
||||
var state = toggleElement.data('state');
|
||||
|
||||
Repository.setDiscussionLockState(forumId, discussionId, state)
|
||||
.then(function(context) {
|
||||
return Templates.render('mod_forum/discussion_lock_toggle', context);
|
||||
})
|
||||
.then(function(html, js) {
|
||||
return Templates.replaceNode(toggleElement, html, js);
|
||||
})
|
||||
.catch(Notification.exception);
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
init: function(root) {
|
||||
registerEventListeners(root);
|
||||
}
|
||||
};
|
||||
});
|
@ -14,7 +14,7 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Forum repository class to encapsulate all of the AJAX requests that
|
||||
* Forum repository class to encapsulate all of the AJAX requests thatsubscribe or unsubscribe
|
||||
* can be sent for forum.
|
||||
*
|
||||
* @module mod_forum/repository
|
||||
@ -56,8 +56,21 @@ define(['core/ajax'], function(Ajax) {
|
||||
return Ajax.call([request])[0];
|
||||
};
|
||||
|
||||
var setDiscussionLockState = function(forumId, discussionId, targetState) {
|
||||
var request = {
|
||||
methodname: 'mod_forum_set_lock_state',
|
||||
args: {
|
||||
forumid: forumId,
|
||||
discussionid: discussionId,
|
||||
targetstate: targetState
|
||||
}
|
||||
};
|
||||
return Ajax.call([request])[0];
|
||||
};
|
||||
|
||||
return {
|
||||
setDiscussionSubscriptionState: setDiscussionSubscriptionState,
|
||||
addDiscussionPost: addDiscussionPost
|
||||
addDiscussionPost: addDiscussionPost,
|
||||
setDiscussionLockState: setDiscussionLockState
|
||||
};
|
||||
});
|
||||
|
@ -41,7 +41,10 @@ define([], function() {
|
||||
inpageReplyForm: "form[data-content='inpage-reply-form']",
|
||||
inpageSubmitBtn: "[data-action='forum-inpage-submit']",
|
||||
repliesContainer: "[data-region='replies-container']",
|
||||
modeSelect: "select[name='mode']",
|
||||
modeSelect: "select[name='mode']"
|
||||
},
|
||||
lock: {
|
||||
toggle: "[data-action='toggle'][data-type='lock-toggle']",
|
||||
}
|
||||
};
|
||||
});
|
||||
|
@ -57,7 +57,8 @@ class discussion {
|
||||
'usermodified' => $discussion->get_user_modified(),
|
||||
'timestart' => $discussion->get_time_start(),
|
||||
'timeend' => $discussion->get_time_end(),
|
||||
'pinned' => $discussion->is_pinned()
|
||||
'pinned' => $discussion->is_pinned(),
|
||||
'locked' => $discussion->get_locked()
|
||||
];
|
||||
}, $discussions);
|
||||
}
|
||||
|
@ -61,6 +61,8 @@ class discussion {
|
||||
private $timeend;
|
||||
/** @var bool $pinned Is the discussion pinned? */
|
||||
private $pinned;
|
||||
/** @var int $locked The timestamp of when the discussion was locked */
|
||||
private $timelocked;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@ -78,6 +80,7 @@ class discussion {
|
||||
* @param int $timestart Start time for the discussion
|
||||
* @param int $timeend End time for the discussion
|
||||
* @param bool $pinned Is the discussion pinned?
|
||||
* @param int $locked Time this discussion was locked
|
||||
*/
|
||||
public function __construct(
|
||||
int $id,
|
||||
@ -92,7 +95,8 @@ class discussion {
|
||||
int $usermodified,
|
||||
int $timestart,
|
||||
int $timeend,
|
||||
bool $pinned
|
||||
bool $pinned,
|
||||
int $locked
|
||||
) {
|
||||
$this->id = $id;
|
||||
$this->courseid = $courseid;
|
||||
@ -107,6 +111,7 @@ class discussion {
|
||||
$this->timestart = $timestart;
|
||||
$this->timeend = $timeend;
|
||||
$this->pinned = $pinned;
|
||||
$this->timelocked = $locked;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -228,6 +233,34 @@ class discussion {
|
||||
return $this->pinned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this discussion is pinned.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function get_locked() : int {
|
||||
return $this->timelocked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this discussion locked based on it's locked attribute
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_locked() : bool {
|
||||
return ($this->timelocked ? true : false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the locked timestamp
|
||||
*
|
||||
* @param int $timestamp
|
||||
*/
|
||||
public function toggle_locked_state(int $timestamp) {
|
||||
// If it is locked already then unlock else set it to the timestamp.
|
||||
$this->timelocked = ($this->timelocked ? 0 : $timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given post is the first post in this discussion.
|
||||
*
|
||||
|
@ -545,6 +545,10 @@ class forum {
|
||||
* @return bool
|
||||
*/
|
||||
public function is_discussion_locked(discussion_entity $discussion) : bool {
|
||||
if ($discussion->is_locked()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$this->has_lock_discussions_after()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -88,11 +88,13 @@ class discussion extends exporter {
|
||||
'modified' => ['type' => PARAM_INT],
|
||||
'start' => ['type' => PARAM_INT],
|
||||
'end' => ['type' => PARAM_INT],
|
||||
'locked' => ['type' => PARAM_INT],
|
||||
],
|
||||
],
|
||||
'userstate' => [
|
||||
'type' => [
|
||||
'subscribed' => ['type' => PARAM_BOOL],
|
||||
'locked' => ['type' => PARAM_BOOL],
|
||||
],
|
||||
],
|
||||
'capabilities' => [
|
||||
@ -100,7 +102,8 @@ class discussion extends exporter {
|
||||
'subscribe' => ['type' => PARAM_BOOL],
|
||||
'move' => ['type' => PARAM_BOOL],
|
||||
'pin' => ['type' => PARAM_BOOL],
|
||||
'post' => ['type' => PARAM_BOOL]
|
||||
'post' => ['type' => PARAM_BOOL],
|
||||
'manage' => ['type' => PARAM_BOOL],
|
||||
]
|
||||
],
|
||||
'urls' => [
|
||||
@ -186,15 +189,18 @@ class discussion extends exporter {
|
||||
'modified' => $discussion->get_time_modified(),
|
||||
'start' => $discussion->get_time_start(),
|
||||
'end' => $discussion->get_time_end(),
|
||||
'locked' => $discussion->get_locked()
|
||||
],
|
||||
'userstate' => [
|
||||
'subscribed' => \mod_forum\subscriptions::is_subscribed($user->id, $forumrecord, $discussion->get_id()),
|
||||
'locked' => $discussion->is_locked()
|
||||
],
|
||||
'capabilities' => [
|
||||
'subscribe' => $capabilitymanager->can_subscribe_to_discussion($user, $discussion),
|
||||
'move' => $capabilitymanager->can_move_discussion($user, $discussion),
|
||||
'pin' => $capabilitymanager->can_pin_discussion($user, $discussion),
|
||||
'post' => $capabilitymanager->can_post_in_discussion($user, $discussion)
|
||||
'post' => $capabilitymanager->can_post_in_discussion($user, $discussion),
|
||||
'manage' => $capabilitymanager->can_manage_forum($user)
|
||||
],
|
||||
'urls' => [
|
||||
'view' => $urlfactory->get_discussion_view_url_from_discussion($discussion)->out(false),
|
||||
|
@ -126,7 +126,8 @@ class entity {
|
||||
$record->usermodified,
|
||||
$record->timestart,
|
||||
$record->timeend,
|
||||
$record->pinned
|
||||
$record->pinned,
|
||||
$record->timelocked
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -201,6 +201,10 @@ class discussion {
|
||||
$exporteddiscussion['html']['pindiscussion'] = $this->get_pin_discussion_html();
|
||||
}
|
||||
|
||||
if ($capabilities['manage']) {
|
||||
$exporteddiscussion['html']['lockdiscussion'] = $this->get_lock_discussion_button_html();
|
||||
}
|
||||
|
||||
return $this->renderer->render_from_template('mod_forum/forum_discussion', $exporteddiscussion);
|
||||
}
|
||||
|
||||
@ -274,6 +278,24 @@ class discussion {
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTML to render the subscription button.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_lock_discussion_button_html() : string {
|
||||
global $PAGE;
|
||||
|
||||
$forumrecord = $this->forumrecord;
|
||||
$discussionrecord = $this->discussionrecord;
|
||||
|
||||
$html = html_writer::div(
|
||||
forum_get_lock_discussion_icon($forumrecord, $discussionrecord, null, true),
|
||||
'discussionlock'
|
||||
);
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTML to render the move discussion selector and button.
|
||||
*
|
||||
|
@ -125,4 +125,20 @@ class discussion extends db_table_vault {
|
||||
return $this->get_db()->count_records(self::TABLE, [
|
||||
'forum' => $forum->get_id()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the discussion
|
||||
*
|
||||
* @param discussion_entity $discussion
|
||||
* @return discussion_entity|null
|
||||
*/
|
||||
public function update_discussion($discussion) : ?discussion_entity {
|
||||
if ($this->get_db()->update_record('forum_discussions', $discussion)) {
|
||||
$records = $this->transform_db_records_to_entities([$discussion]);
|
||||
|
||||
return count($records) ? array_shift($records) : null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,7 @@
|
||||
<FIELD NAME="timestart" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
|
||||
<FIELD NAME="timeend" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
|
||||
<FIELD NAME="pinned" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
|
||||
<FIELD NAME="timelocked" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
|
@ -134,4 +134,14 @@ $functions = array(
|
||||
'ajax' => true,
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
|
||||
),
|
||||
|
||||
'mod_forum_set_lock_state' => array(
|
||||
'classname' => 'mod_forum_external',
|
||||
'methodname' => 'set_lock_state',
|
||||
'classpath' => 'mod/forum/externallib.php',
|
||||
'description' => 'Set the lock state for the discussion',
|
||||
'type' => 'write',
|
||||
'ajax' => true,
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
|
||||
),
|
||||
);
|
||||
|
@ -114,7 +114,6 @@ function xmldb_forum_upgrade($oldversion) {
|
||||
$dbman->add_field($table, $field);
|
||||
}
|
||||
|
||||
// Forum savepoint reached.
|
||||
upgrade_mod_savepoint(true, 2019031200, 'forum');
|
||||
}
|
||||
|
||||
@ -138,9 +137,22 @@ function xmldb_forum_upgrade($oldversion) {
|
||||
$dbman->add_field($table, $field);
|
||||
}
|
||||
|
||||
// Forum savepoint reached.
|
||||
upgrade_mod_savepoint(true, 2019040400, 'forum');
|
||||
}
|
||||
|
||||
if ($oldversion < 2019040401) {
|
||||
// Define field deleted to be added to forum_posts.
|
||||
$table = new xmldb_table('forum_discussions');
|
||||
$field = new xmldb_field('timelocked', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'pinned');
|
||||
|
||||
// Conditionally launch add field deleted.
|
||||
if (!$dbman->field_exists($table, $field)) {
|
||||
$dbman->add_field($table, $field);
|
||||
}
|
||||
|
||||
// Forum savepoint reached.
|
||||
upgrade_mod_savepoint(true, 2019040401, 'forum');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -636,7 +636,7 @@ class mod_forum_external extends external_api {
|
||||
$discussion->messageinlinefiles = $messageinlinefiles;
|
||||
}
|
||||
|
||||
$discussion->locked = forum_discussion_is_locked($forum, $discussion);
|
||||
$discussion->timelocked = forum_discussion_is_locked($forum, $discussion);
|
||||
$discussion->canreply = forum_user_can_post($forum, $discussion, $USER, $cm, $course, $modcontext);
|
||||
|
||||
if (forum_is_author_hidden($discussion, $forum)) {
|
||||
@ -1227,6 +1227,7 @@ class mod_forum_external extends external_api {
|
||||
$discussion->name = $discussion->subject;
|
||||
$discussion->timestart = 0;
|
||||
$discussion->timeend = 0;
|
||||
$discussion->timelocked = 0;
|
||||
$discussion->attachments = $options['attachmentsid'];
|
||||
|
||||
if (has_capability('mod/forum:pindiscussions', $context) && $options['discussionpinned']) {
|
||||
@ -1510,4 +1511,75 @@ class mod_forum_external extends external_api {
|
||||
public static function set_subscription_state_returns() {
|
||||
return \mod_forum\local\exporters\discussion::get_read_structure();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the lock state.
|
||||
*
|
||||
* @param int $forumid
|
||||
* @param int $discussionid
|
||||
* @param string $targetstate
|
||||
* @return \stdClass
|
||||
*/
|
||||
public static function set_lock_state($forumid, $discussionid, $targetstate) {
|
||||
global $DB, $PAGE, $USER;
|
||||
|
||||
$params = self::validate_parameters(self::set_lock_state_parameters(), [
|
||||
'forumid' => $forumid,
|
||||
'discussionid' => $discussionid,
|
||||
'targetstate' => $targetstate
|
||||
]);
|
||||
|
||||
$vaultfactory = mod_forum\local\container::get_vault_factory();
|
||||
$forumvault = $vaultfactory->get_forum_vault();
|
||||
$forum = $forumvault->get_from_id($params['forumid']);
|
||||
// If the targetstate(currentstate) is not 0 then it should be set to the current time.
|
||||
$targetstate = $targetstate ? 0 : time();
|
||||
self::validate_context($forum->get_context());
|
||||
|
||||
$managerfactory = mod_forum\local\container::get_manager_factory();
|
||||
$capabilitymanager = $managerfactory->get_capability_manager($forum);
|
||||
$discussionvault = $vaultfactory->get_discussion_vault();
|
||||
$discussion = $discussionvault->get_from_id($params['discussionid']);
|
||||
$legacydatamapperfactory = mod_forum\local\container::get_legacy_data_mapper_factory();
|
||||
$forumrecord = $legacydatamapperfactory->get_forum_data_mapper()->to_legacy_object($forum);
|
||||
|
||||
// If the current state doesn't equal the desired state then update the current
|
||||
// state to the desired state.
|
||||
if ($capabilitymanager->can_manage_forum($USER)) {
|
||||
$discussion->toggle_locked_state($targetstate);
|
||||
$discussionrecord = $legacydatamapperfactory->get_discussion_data_mapper()->to_legacy_object($discussion);
|
||||
$response = $discussionvault->update_discussion($discussionrecord);
|
||||
|
||||
$discussion = !$response ? $response : $discussion;
|
||||
}
|
||||
|
||||
$exporterfactory = mod_forum\local\container::get_exporter_factory();
|
||||
$exporter = $exporterfactory->get_discussion_exporter($USER, $forum, $discussion);
|
||||
return $exporter->export($PAGE->get_renderer('mod_forum'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method parameters.
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function set_lock_state_parameters() {
|
||||
return new external_function_parameters(
|
||||
[
|
||||
'forumid' => new external_value(PARAM_INT, 'Forum that the discussion is in'),
|
||||
'discussionid' => new external_value(PARAM_INT, 'The discussion to lock / unlock'),
|
||||
'targetstate' => new external_value(PARAM_INT, 'The timestamp for the lock state')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method result value.
|
||||
*
|
||||
* @return external_description
|
||||
*/
|
||||
public static function set_lock_state_returns() {
|
||||
return \mod_forum\local\exporters\discussion::get_read_structure();
|
||||
}
|
||||
}
|
||||
|
@ -85,6 +85,8 @@ $string['cannotupdatepost'] = 'You can not update this post';
|
||||
$string['cannotviewpostyet'] = 'You cannot read other students questions in this discussion yet because you haven\'t posted';
|
||||
$string['cannotviewusersposts'] = 'There are no posts made by this user that you are able to view.';
|
||||
$string['cleanreadtime'] = 'Mark old posts as read hour';
|
||||
$string['clicktolockdiscussion'] = 'Click to lock this discussion';
|
||||
$string['clicktounlockdiscussion'] = 'Click to unlock this discussion';
|
||||
$string['clicktounsubscribe'] = 'You are subscribed to this discussion. Click to unsubscribe.';
|
||||
$string['clicktosubscribe'] = 'You are not subscribed to this discussion. Click to subscribe.';
|
||||
$string['completiondiscussions'] = 'Student must create discussions:';
|
||||
@ -313,6 +315,7 @@ $string['lockdiscussionafter_help'] = 'Discussions may be automatically locked a
|
||||
|
||||
Users with the capability to reply to locked discussions can unlock a discussion by replying to it.';
|
||||
$string['longpost'] = 'Long post';
|
||||
$string['locked'] = 'Locked';
|
||||
$string['mailnow'] = 'Send forum post notifications with no editing-time delay';
|
||||
$string['manydiscussions'] = 'Discussions per page';
|
||||
$string['managesubscriptionsoff'] = 'Finish managing subscriptions';
|
||||
@ -403,6 +406,7 @@ $string['notexists'] = 'Discussion no longer exists';
|
||||
$string['nothingnew'] = 'Nothing new for {$a}';
|
||||
$string['notingroup'] = 'Sorry, but you need to be part of a group to see this forum.';
|
||||
$string['notinstalled'] = 'The forum module is not installed';
|
||||
$string['notlocked'] = 'Lock';
|
||||
$string['notpartofdiscussion'] = 'This post is not part of a discussion!';
|
||||
$string['notrackforum'] = 'Don\'t track unread posts';
|
||||
$string['noviewdiscussionspermission'] = 'You do not have the permission to view discussions in this forum';
|
||||
|
@ -1822,8 +1822,9 @@ function forum_get_discussions($cm, $forumsort="", $fullpost=true, $unused=-1, $
|
||||
$updatedsincesql = 'AND d.timemodified > ?';
|
||||
$params[] = $updatedsince;
|
||||
}
|
||||
$discussionfields = "d.id as discussionid, d.course, d.forum, d.name, d.firstpost, d.groupid, d.assessed," .
|
||||
" d.timemodified, d.usermodified, d.timestart, d.timeend, d.pinned";
|
||||
|
||||
$discussionfields = "d.id as discussionid, d.course, d.forum, d.name, d.firstpost, d.userid, d.groupid, d.assessed," .
|
||||
" d.timemodified, d.usermodified, d.timestart, d.timeend, d.pinned, d.locked";
|
||||
|
||||
$allnames = get_all_user_name_fields(true, 'u');
|
||||
$sql = "SELECT $postdata, $discussionfields,
|
||||
@ -2582,6 +2583,71 @@ function forum_print_discussion_header(&$post, $forum, $group = -1, $datestring
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the markup for the discussion lock toggling icon.
|
||||
* @param stdClass $forum forum record
|
||||
* @param stdClass $discussion discussion record
|
||||
* @param null $returnurl the return url to use
|
||||
* @param bool $includetext Whether or not to include the text with the icon
|
||||
* @return string
|
||||
* @throws coding_exception
|
||||
* @throws moodle_exception
|
||||
*/
|
||||
function forum_get_lock_discussion_icon($forum, $discussion, $returnurl = null, $includetext = false) {
|
||||
global $USER, $OUTPUT, $PAGE;
|
||||
|
||||
if ($returnurl === null && $PAGE->url) {
|
||||
$returnurl = $PAGE->url->out();
|
||||
}
|
||||
|
||||
$o = '';
|
||||
$discussionid = $discussion->id;
|
||||
$lockstatus = forum_discussion_is_locked($forum, $discussion);
|
||||
$subscriptionlink = new moodle_url('/mod/forum/lockdiscussion.php', array(
|
||||
'sesskey' => sesskey(),
|
||||
'id' => $forum->id,
|
||||
'd' => $discussion->id,
|
||||
'returnurl' => $returnurl,
|
||||
));
|
||||
|
||||
if ($includetext) {
|
||||
$o .= $lockstatus ? get_string('locked', 'mod_forum') : get_string('notlocked', 'mod_forum');
|
||||
}
|
||||
|
||||
if ($lockstatus) {
|
||||
$output = $OUTPUT->pix_icon('t/unlock', get_string('clicktounlockdiscussion', 'forum'), 'core');
|
||||
if ($includetext) {
|
||||
$output .= get_string('locked', 'mod_forum');
|
||||
}
|
||||
|
||||
return html_writer::link($subscriptionlink, $output, array(
|
||||
'title' => get_string('clicktounlockdiscussion', 'forum'),
|
||||
'class' => 'iconsmall',
|
||||
'data-forumid' => $forum->id,
|
||||
'data-discussionid' => $discussionid,
|
||||
'data-action' => 'toggle',
|
||||
'data-type' => 'lock-toggle',
|
||||
'data-state' => $discussion->locked
|
||||
));
|
||||
|
||||
} else {
|
||||
$output = $OUTPUT->pix_icon('t/lock', get_string('clicktolockdiscussion', 'forum'), 'core');
|
||||
if ($includetext) {
|
||||
$output .= get_string('notlocked', 'mod_forum');
|
||||
}
|
||||
|
||||
return html_writer::link("#", $output, array(
|
||||
'title' => get_string('clicktolockdiscussion', 'forum'),
|
||||
'class' => 'iconsmall',
|
||||
'data-forumid' => $forum->id,
|
||||
'data-discussionid' => $discussionid,
|
||||
'data-action' => 'toggle',
|
||||
'data-type' => 'lock-toggle',
|
||||
'data-state' => $discussion->locked
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the markup for the discussion subscription toggling icon.
|
||||
*
|
||||
|
@ -968,6 +968,7 @@ if ($mformpost->is_cancelled()) {
|
||||
|
||||
$discussion = $fromform;
|
||||
$discussion->name = $fromform->subject;
|
||||
$discussion->timelocked = 0;
|
||||
|
||||
$newstopic = false;
|
||||
if ($forum->type == 'news' && !$fromform->parent) {
|
||||
|
@ -301,13 +301,15 @@ span.unread {
|
||||
background: url([[pix:mod_forum|t/unsubscribed]]) no-repeat -9999px -9999px;
|
||||
}
|
||||
|
||||
.path-mod-forum .discussionsubscription {
|
||||
.path-mod-forum .discussionsubscription,
|
||||
.path-mod-forum .discussionlock {
|
||||
margin-top: -10px;
|
||||
text-align: right;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.path-mod-forum .discussionsubscription > a > img {
|
||||
.path-mod-forum .discussionsubscription > a > img,
|
||||
.path-mod-forum .discussionlock > a > img {
|
||||
width: 12px;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
59
mod/forum/templates/discussion_lock_toggle.mustache
Normal file
59
mod/forum/templates/discussion_lock_toggle.mustache
Normal file
@ -0,0 +1,59 @@
|
||||
{{!
|
||||
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 mod_forum/discussion_lock_toggle
|
||||
|
||||
Template to display the discussion subscription toggle.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Context variables required for this template:
|
||||
* TODO
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
}
|
||||
}}
|
||||
{{#capabilities.manage}}
|
||||
<a
|
||||
class="iconsmall"
|
||||
data-type="lock-toggle"
|
||||
data-action="toggle"
|
||||
data-discussionid="{{id}}"
|
||||
data-forumid="{{forumid}}"
|
||||
data-state="{{times.locked}}" href="#"
|
||||
{{#userstate.locked}}
|
||||
title="{{#str}}locked, forum{{/str}}"
|
||||
{{/userstate.locked}}
|
||||
{{^userstate.locked}}
|
||||
title="{{#str}}notlocked, forum{{/str}}"
|
||||
{{/userstate.locked}}
|
||||
>
|
||||
{{#userstate.locked}}
|
||||
{{#pix}}t/unlock, core, {{#str}}clicktounlockdiscussion, forum{{/str}}{{/pix}}{{#str}}locked, forum{{/str}}
|
||||
{{/userstate.locked}}
|
||||
{{^userstate.locked}}
|
||||
{{#pix}}t/lock, core, {{#str}}clicktolockdiscussion, forum{{/str}}{{/pix}}{{#str}}notlocked, forum{{/str}}
|
||||
{{/userstate.locked}}
|
||||
</a>
|
||||
{{/capabilities.manage}}
|
||||
|
||||
|
@ -32,7 +32,10 @@
|
||||
|
||||
<div id="discussion-container-{{uniqid}}" data-content="forum-discussion">
|
||||
{{#html}}
|
||||
{{{subscribe}}}
|
||||
<div class="d-flex flex-wrap flex-row-reverse m-b-1" data-container="discussion-tools" style="text-align: right;">
|
||||
<div class="pl-1">{{{lockdiscussion}}}</div>
|
||||
<div class="pl-1">{{{subscribe}}}</div>
|
||||
</div>
|
||||
{{{neighbourlinks}}}
|
||||
|
||||
<div class="d-flex flex-wrap mb-1">
|
||||
@ -52,10 +55,11 @@
|
||||
{{#html.neighbourlinks}}{{{.}}}{{/html.neighbourlinks}}
|
||||
</div>
|
||||
{{#js}}
|
||||
require(['jquery', 'mod_forum/discussion', 'mod_forum/posts_list'], function($, Discussion, PostsList) {
|
||||
require(['jquery', 'mod_forum/discussion', 'mod_forum/posts_list', 'mod_forum/lock_toggle'], function($, Discussion, PostsList, LockToggle) {
|
||||
var root = $("[data-content='forum-discussion']");
|
||||
Discussion.init(root);
|
||||
PostsList.init(root);
|
||||
var root = $('#discussion-container-{{uniqid}}');
|
||||
var root = $('[data-container="discussion-tools"]');
|
||||
LockToggle.init(root);
|
||||
});
|
||||
{{/js}}
|
||||
|
@ -193,6 +193,10 @@ class mod_forum_generator extends testing_module_generator {
|
||||
$record['pinned'] = FORUM_DISCUSSION_UNPINNED;
|
||||
}
|
||||
|
||||
if (!isset($record['locked'])) {
|
||||
$record['locked'] = "0";
|
||||
}
|
||||
|
||||
if (isset($record['mailed'])) {
|
||||
$mailed = $record['mailed'];
|
||||
}
|
||||
|
@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2019040400; // The current module version (Date: YYYYMMDDXX)
|
||||
$plugin->version = 2019040401; // The current module version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2018112800; // Requires this Moodle version
|
||||
$plugin->component = 'mod_forum'; // Full name of the plugin (used for diagnostics)
|
||||
|
@ -69,6 +69,7 @@ select {
|
||||
|
||||
thead .header th,
|
||||
tbody .discussion td {
|
||||
&.discussionlock,
|
||||
&.discussionsubscription {
|
||||
width: 16px;
|
||||
padding-left: 0.5em;
|
||||
@ -83,12 +84,14 @@ select {
|
||||
}
|
||||
|
||||
.discussionsubscription,
|
||||
.discussionlock,
|
||||
.replies {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.topic,
|
||||
.discussionsubscription,
|
||||
.discussionlock,
|
||||
.topic.starter,
|
||||
.replies,
|
||||
.lastpost {
|
||||
|
@ -15023,7 +15023,8 @@ select {
|
||||
.path-mod-forum .forumheaderlist thead .header.lastpost {
|
||||
text-align: right; }
|
||||
|
||||
.path-mod-forum .forumheaderlist thead .header th.discussionsubscription,
|
||||
.path-mod-forum .forumheaderlist thead .header th.discussionlock, .path-mod-forum .forumheaderlist thead .header th.discussionsubscription,
|
||||
.path-mod-forum .forumheaderlist tbody .discussion td.discussionlock,
|
||||
.path-mod-forum .forumheaderlist tbody .discussion td.discussionsubscription {
|
||||
width: 16px;
|
||||
padding-left: 0.5em;
|
||||
@ -15034,11 +15035,13 @@ select {
|
||||
white-space: normal; }
|
||||
|
||||
.path-mod-forum .forumheaderlist .discussion .discussionsubscription,
|
||||
.path-mod-forum .forumheaderlist .discussion .discussionlock,
|
||||
.path-mod-forum .forumheaderlist .discussion .replies {
|
||||
text-align: center; }
|
||||
|
||||
.path-mod-forum .forumheaderlist .discussion .topic,
|
||||
.path-mod-forum .forumheaderlist .discussion .discussionsubscription,
|
||||
.path-mod-forum .forumheaderlist .discussion .discussionlock,
|
||||
.path-mod-forum .forumheaderlist .discussion .topic.starter,
|
||||
.path-mod-forum .forumheaderlist .discussion .replies,
|
||||
.path-mod-forum .forumheaderlist .discussion .lastpost {
|
||||
|
@ -15280,7 +15280,8 @@ select {
|
||||
.path-mod-forum .forumheaderlist thead .header.lastpost {
|
||||
text-align: right; }
|
||||
|
||||
.path-mod-forum .forumheaderlist thead .header th.discussionsubscription,
|
||||
.path-mod-forum .forumheaderlist thead .header th.discussionlock, .path-mod-forum .forumheaderlist thead .header th.discussionsubscription,
|
||||
.path-mod-forum .forumheaderlist tbody .discussion td.discussionlock,
|
||||
.path-mod-forum .forumheaderlist tbody .discussion td.discussionsubscription {
|
||||
width: 16px;
|
||||
padding-left: 0.5em;
|
||||
@ -15291,11 +15292,13 @@ select {
|
||||
white-space: normal; }
|
||||
|
||||
.path-mod-forum .forumheaderlist .discussion .discussionsubscription,
|
||||
.path-mod-forum .forumheaderlist .discussion .discussionlock,
|
||||
.path-mod-forum .forumheaderlist .discussion .replies {
|
||||
text-align: center; }
|
||||
|
||||
.path-mod-forum .forumheaderlist .discussion .topic,
|
||||
.path-mod-forum .forumheaderlist .discussion .discussionsubscription,
|
||||
.path-mod-forum .forumheaderlist .discussion .discussionlock,
|
||||
.path-mod-forum .forumheaderlist .discussion .topic.starter,
|
||||
.path-mod-forum .forumheaderlist .discussion .replies,
|
||||
.path-mod-forum .forumheaderlist .discussion .lastpost {
|
||||
|
Loading…
x
Reference in New Issue
Block a user