MDL-53254 tags: tags management inplace editable

This commit is contained in:
Marina Glancy 2016-02-27 15:55:26 +08:00
parent 352bfbf55c
commit 21d9596cca
14 changed files with 205 additions and 265 deletions

File diff suppressed because one or more lines are too long

View File

@ -61,80 +61,19 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
*/
initManagePage: function() {
var update_modified = function(el) {
var row = el.closest('tr').get(0);
if (row) {
var td = $(row).find('td.col-timemodified').get(0);
str.get_string('now').done(function(s) {
$(td).html(s);
});
// Set cell 'time modified' to 'now' when any of the element is updated in this row.
$('body').on('updated', '[data-inplaceeditable]', function(e) {
str.get_string('now').done(function(s) {
$(e.target).closest('tr').find('td.col-timemodified').html(s);
});
if (e.ajaxreturn.itemtype === 'tagflag') {
var row = $(e.target).closest('tr');
if (e.ajaxreturn.value === '0') {
row.removeClass('flagged-tag');
} else {
row.addClass('flagged-tag');
}
}
};
// Click handler for changing tag type.
$('.tag-management-table').delegate('.tagisstandard', 'click', function(e) {
e.preventDefault();
var target = $( this ),
tagid = target.attr('data-id'),
currentvalue = target.attr('data-value'),
isstandard = (currentvalue === "1") ? 0 : 1;
var promises = ajax.call([{
methodname: 'core_tag_update_tags',
args: { tags : [ { id : tagid , isstandard : isstandard } ] }
}, {
methodname: 'core_tag_get_tags',
args: { tags : [ { id : tagid } ] }
}], true);
$.when.apply($, promises)
.done( function(updateresult, data) {
if (updateresult.warnings[0] === undefined && data.tags[0] !== undefined) {
templates.render('core_tag/tagisstandard', data.tags[0]).done(function(html) {
update_modified(target);
var parent = target.parent();
target.replaceWith(html);
parent.find('.tagisstandard').get(0).focus();
});
}
});
});
// Click handler for flagging/resetting tag flag.
$('.tag-management-table').delegate('.tagflag', 'click', function(e) {
e.preventDefault();
var target = $( this ),
tagid = target.attr('data-id'),
currentvalue = target.attr('data-value'),
flag = (currentvalue === "0") ? 1 : 0;
var promises = ajax.call([{
methodname: 'core_tag_update_tags',
args: { tags : [ { id : tagid , flag : flag } ] }
}, {
methodname: 'core_tag_get_tags',
args: { tags : [ { id : tagid } ] }
}], true);
$.when.apply($, promises)
.done( function(updateresult, data) {
if (updateresult.warnings[0] === undefined && data.tags[0] !== undefined) {
var row = target.closest('tr').get(0);
if (row) {
if (data.tags[0].flag) {
$(row).addClass('flagged-tag');
} else {
$(row).removeClass('flagged-tag');
}
}
templates.render('core_tag/tagflag', data.tags[0]).done(function(html) {
update_modified(target);
var parent = target.parent();
target.replaceWith(html);
parent.find('.tagflag').get(0).focus();
});
}
});
});
// Confirmation for single tag delete link.
@ -184,7 +123,6 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
initManageCollectionsPage: function() {
$('body').on('updated', '[data-inplaceeditable]', function(e) {
var ajaxreturn = e.ajaxreturn,
oldvalue = e.oldvalue,
areaid, collid, isenabled;
if (ajaxreturn.component === 'core_tag' && ajaxreturn.itemtype === 'tagareaenable') {
areaid = $(this).attr('data-itemid');
@ -193,7 +131,8 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
if (isenabled === '1') {
$(this).closest('tr').removeClass('dimmed_text');
collid = $(this).closest('tr').find('[data-itemtype="tagareacollection"]').attr("data-value");
$(".tag-collections-table ul[data-collectionid="+collid+"] li[data-areaid="+areaid+"]").removeClass('hidden');
$(".tag-collections-table ul[data-collectionid="+collid+"] li[data-areaid="+areaid+"]")
.removeClass('hidden');
} else {
$(this).closest('tr').addClass('dimmed_text');
}
@ -204,7 +143,8 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
collid = $(this).attr('data-value');
isenabled = $(this).closest('tr').find('[data-itemtype="tagareaenable"]').attr("data-value");
if (isenabled === "1") {
$(".tag-collections-table ul[data-collectionid="+collid+"] li[data-areaid="+areaid+"]").removeClass('hidden');
$(".tag-collections-table ul[data-collectionid="+collid+"] li[data-areaid="+areaid+"]")
.removeClass('hidden');
}
}
});

View File

@ -35,7 +35,6 @@ class core_tag_collections_table extends html_table {
/**
* Constructor
* @global \core_renderer $OUTPUT
* @param string|moodle_url $pageurl
*/
public function __construct($pageurl) {

View File

@ -224,8 +224,6 @@ class core_tag_external extends external_api {
unset($rv->official);
}
unset($rv->flag);
unset($rv->changetypeurl);
unset($rv->changeflagurl);
}
$return[] = $rv;
}
@ -253,8 +251,6 @@ class core_tag_external extends external_api {
'whether this flag is standard (deprecated, use isstandard)', VALUE_OPTIONAL),
'isstandard' => new external_value(PARAM_INT, 'whether this flag is standard', VALUE_OPTIONAL),
'viewurl' => new external_value(PARAM_URL, 'URL to view'),
'changetypeurl' => new external_value(PARAM_URL, 'URL to change type (standard or not)', VALUE_OPTIONAL),
'changeflagurl' => new external_value(PARAM_URL, 'URL to set or reset flag', VALUE_OPTIONAL),
), 'information about one tag')
),
'warnings' => new external_warnings()
@ -306,6 +302,7 @@ class core_tag_external extends external_api {
$context = $params['ctx'] ? context::instance_by_id($params['ctx']) : context_system::instance();
require_login(null, false, null, false, true);
self::validate_context($context);
$PAGE->set_context(null);
$tag = core_tag_tag::get_by_name($params['tc'], $params['tag'], '*', MUST_EXIST);
$tagareas = core_tag_collection::get_areas($params['tc']);

View File

@ -180,7 +180,7 @@ class core_tag_manage_table extends table_sql {
public function col_name($tag) {
global $OUTPUT;
$tagoutput = new core_tag\output\tagname($tag);
return $OUTPUT->render_from_template('core/inplace_editable', $tagoutput->export_for_template($OUTPUT));
return $tagoutput->render($OUTPUT);
}
/**
@ -191,8 +191,8 @@ class core_tag_manage_table extends table_sql {
*/
public function col_flag($tag) {
global $OUTPUT;
$tagoutput = new core_tag\output\tag($tag);
return $OUTPUT->render_from_template('core_tag/tagflag', $tagoutput->export_for_template($OUTPUT));
$tagoutput = new core_tag\output\tagflag($tag);
return $tagoutput->render($OUTPUT);
}
/**
@ -226,8 +226,8 @@ class core_tag_manage_table extends table_sql {
*/
public function col_isstandard($tag) {
global $OUTPUT;
$tagoutput = new core_tag\output\tag($tag);
return $OUTPUT->render_from_template('core_tag/tagisstandard', $tagoutput->export_for_template($OUTPUT));
$tagoutput = new core_tag\output\tagisstandard($tag);
return $tagoutput->render($OUTPUT);
}
/**

View File

@ -94,17 +94,6 @@ class tag implements renderable, templatable {
$url = core_tag_tag::make_url($r->tagcollid, $r->rawname);
$r->viewurl = $url->out(false);
$manageurl = new moodle_url('/tag/manage.php', array('sesskey' => sesskey(),
'tagid' => $this->record->id));
$url = new moodle_url($manageurl);
$url->param('action', 'changetype');
$url->param('isstandard', $r->isstandard ? 0 : 1);
$r->changetypeurl = $url->out(false);
$url = new moodle_url($manageurl);
$url->param('action', $this->record->flag ? 'resetflag' : 'setflag');
$r->changeflagurl = $url->out(false);
return $r;
}
}

View File

@ -0,0 +1,89 @@
<?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/>.
/**
* Contains class core_tag\output\tagflag
*
* @package core_tag
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_tag\output;
use context_system;
use core_tag_tag;
/**
* Class to display tag flag toggle
*
* @package core_tag
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tagflag extends \core\output\inplace_editable {
/**
* Constructor.
*
* @param \stdClass|core_tag_tag $tag
*/
public function __construct($tag) {
$editable = has_capability('moodle/tag:manage', context_system::instance());
$value = (int)$tag->flag;
parent::__construct('core_tag', 'tagflag', $tag->id, $editable, $value, $value);
$this->set_type_toggle(array(0, $value ? $value : 1));
}
/**
* Export this data so it can be used as the context for a mustache template.
*
* @param \renderer_base $output
* @return \stdClass
*/
public function export_for_template(\renderer_base $output) {
if ($this->value) {
$this->edithint = get_string('resetflag', 'core_tag');
$this->displayvalue = $output->pix_icon('i/flagged', $this->edithint) .
" ({$this->value})";
} else {
$this->edithint = get_string('flagasinappropriate', 'core_tag');
$this->displayvalue = $output->pix_icon('i/unflagged', $this->edithint);
}
return parent::export_for_template($output);
}
/**
* Updates the value in database and returns itself, called from inplace_editable callback
*
* @param int $itemid
* @param mixed $newvalue
* @return \self
*/
public static function update($itemid, $newvalue) {
require_capability('moodle/tag:manage', context_system::instance());
$tag = core_tag_tag::get($itemid, '*', MUST_EXIST);
$newvalue = (int)clean_param($newvalue, PARAM_BOOL);
if ($newvalue) {
$tag->flag();
} else {
$tag->reset_flag();
}
return new self($tag);
}
}

View File

@ -0,0 +1,84 @@
<?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/>.
/**
* Contains class core_tag\output\tagisstandard
*
* @package core_tag
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_tag\output;
use context_system;
use core_tag_tag;
/**
* Class to display/toggle tag isstandard attribute
*
* @package core_tag
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tagisstandard extends \core\output\inplace_editable {
/**
* Constructor.
*
* @param \stdClass|core_tag_tag $tag
*/
public function __construct($tag) {
$editable = has_capability('moodle/tag:manage', context_system::instance());
$value = (int)(bool)$tag->isstandard;
parent::__construct('core_tag', 'tagisstandard', $tag->id, $editable, $value, $value);
$this->set_type_toggle();
}
/**
* Export this data so it can be used as the context for a mustache template.
*
* @param \renderer_base $output
* @return \stdClass
*/
public function export_for_template(\renderer_base $output) {
if ($this->value) {
$this->edithint = get_string('settypedefault', 'core_tag');
$this->displayvalue = $output->pix_icon('i/checked', $this->edithint);
} else {
$this->edithint = get_string('settypestandard', 'core_tag');
$this->displayvalue = $output->pix_icon('i/unchecked', $this->edithint);
}
return parent::export_for_template($output);
}
/**
* Updates the value in database and returns itself, called from inplace_editable callback
*
* @param int $itemid
* @param mixed $newvalue
* @return \self
*/
public static function update($itemid, $newvalue) {
require_capability('moodle/tag:manage', context_system::instance());
$tag = core_tag_tag::get($itemid, '*', MUST_EXIST);
$newvalue = (int)clean_param($newvalue, PARAM_BOOL);
$tag->update(array('isstandard' => $newvalue));
return new self($tag);
}
}

View File

@ -44,8 +44,6 @@ function tag_page_type_list($pagetype, $parentcontext, $currentcontext) {
/**
* Implements callback inplace_editable() allowing to edit values in-place
*
* @global moodle_database $DB
*
* @param string $itemtype
* @param int $itemid
* @param mixed $newvalue
@ -64,5 +62,9 @@ function core_tag_inplace_editable($itemtype, $itemid, $newvalue) {
return \core_tag\output\tagcollname::update($itemid, $newvalue);
} else if ($itemtype === 'tagcollsearchable') {
return \core_tag\output\tagcollsearchable::update($itemid, $newvalue);
} else if ($itemtype === 'tagflag') {
return \core_tag\output\tagflag::update($itemid, $newvalue);
} else if ($itemtype === 'tagisstandard') {
return \core_tag\output\tagisstandard::update($itemid, $newvalue);
}
}

View File

@ -77,7 +77,7 @@ switch($action) {
$name = required_param('name', PARAM_NOTAGS);
$searchable = required_param('searchable', PARAM_BOOL);
core_tag_collection::create(array('name' => $name, 'searchable' => $searchable));
redirect($manageurl); // TODO message
redirect($manageurl);
break;
case 'colldelete':
@ -120,36 +120,9 @@ switch($action) {
}
break;
case 'setflag':
require_sesskey();
if ($tagid) {
$tagobject->flag();
redirect($PAGE->url, get_string('flagged', 'core_tag'), null, \core\output\notification::NOTIFY_SUCCESS);
}
redirect($PAGE->url);
break;
case 'resetflag':
require_sesskey();
if ($tagid) {
$tagobject->reset_flag();
redirect($PAGE->url, get_string('resetflag', 'core_tag'), null, \core\output\notification::NOTIFY_SUCCESS);
}
redirect($PAGE->url);
break;
case 'changetype':
require_sesskey();
if ($tagid && $tagobject->update(
array('isstandard' => $isstandard ? 1 : 0))) {
redirect($PAGE->url, get_string('typechanged', 'core_tag'), null, \core\output\notification::NOTIFY_SUCCESS);
}
redirect($PAGE->url);
break;
case 'addstandardtag':
require_sesskey();
$tagobjects = null;
$tagobjects = array();
if ($tagcoll) {
$otagsadd = optional_param('otagsadd', '', PARAM_RAW);
$newtags = preg_split('/\s*,\s*/', trim($otagsadd), -1, PREG_SPLIT_NO_EMPTY);

View File

@ -1,48 +0,0 @@
{{!
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_tag/tagflag
Displays the tag flag in the tag management table
Classes required for JS:
* tagflag
Data attributes required for JS:
* data-id, data-value
Context variables required for this template:
* none
Example context (json):
{
"id" : "1",
"flag" : "1",
"changeflagurl" : "http://moodle.com/"
}
}}
{{#flag}}
<a href="{{changeflagurl}}" class="tagflag" data-id="{{id}}" data-value="{{flag}}" title="{{#str}}resetflag,tag{{/str}}">
{{#pix}}i/flagged,core,{{#str}}resetflag,tag{{/str}}{{/pix}} ({{flag}})
</a>
{{/flag}}
{{^flag}}
<a href="{{changeflagurl}}" class="tagflag" data-id="{{id}}" data-value="0" title="{{#str}}flagasinappropriate,tag{{/str}}">
{{#pix}}i/unflagged,core,{{#str}}flagasinappropriate,tag{{/str}}{{/pix}}
</a>
{{/flag}}

View File

@ -1,47 +0,0 @@
{{!
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_tag/tagisstandard
Displays the tag type (standard or not) in the tag management table
Classes required for JS:
* tagisstandard
Data attributes required for JS:
* data-id, data-value
Context variables required for this template:
* none
Example context (json):
{
"id" : "1",
"isstandard" : "1",
"changetypeurl" : "http://moodle.com/"
}
}}
{{#isstandard}}
<a href="{{changetypeurl}}" class="tagisstandard" data-id="{{id}}" data-value="1" title="{{#str}}settypedefault,core_tag{{/str}}">
{{#pix}}i/checked,core,{{#str}}settypedefault,core_tag{{/str}}{{/pix}}
</a>
{{/isstandard}}
{{^isstandard}}
<a href="{{changetypeurl}}" class="tagisstandard" data-id="{{id}}" data-value="0" title="{{#str}}settypestandard,core_tag{{/str}}">
{{#pix}}i/unchecked,core,{{#str}}settypestandard,core_tag{{/str}}{{/pix}}
</a>
{{/isstandard}}

View File

@ -43,28 +43,8 @@ Feature: Users can flag tags and manager can reset flags
And I should see "The person responsible will be notified"
And I log out
Scenario: Managing tag flags with javascript disabled
When I log in as "manager1"
And I navigate to "Manage tags" node in "Site administration > Appearance"
And I follow "Default collection"
Then "Sweartag" "link" should appear before "Badtag" "link"
And "Badtag" "link" should appear before "Nicetag" "link"
And "(2)" "text" should exist in the "//tr[contains(.,'Sweartag')]//td[contains(@class,'col-flag')]" "xpath_element"
And "(1)" "text" should exist in the "//tr[contains(.,'Badtag')]//td[contains(@class,'col-flag')]" "xpath_element"
And "(" "text" should not exist in the "//tr[contains(.,'Nicetag')]//td[contains(@class,'col-flag')]" "xpath_element"
And "(" "text" should not exist in the "//tr[contains(.,'Neverusedtag')]//td[contains(@class,'col-flag')]" "xpath_element"
And I click on "Reset flag" "link" in the "Sweartag" "table_row"
And I click on "Reset flag" "link" in the "Badtag" "table_row"
And I click on "Flag as inappropriate" "link" in the "Sweartag" "table_row"
And I click on "Flag as inappropriate" "link" in the "Nicetag" "table_row"
And "(1)" "text" should exist in the "//tr[contains(.,'Sweartag')]//td[contains(@class,'col-flag')]" "xpath_element"
And "(1)" "text" should exist in the "//tr[contains(.,'Nicetag')]//td[contains(@class,'col-flag')]" "xpath_element"
And "(" "text" should not exist in the "//tr[contains(.,'Badtag')]//td[contains(@class,'col-flag')]" "xpath_element"
And "(" "text" should not exist in the "//tr[contains(.,'Neverusedtag')]//td[contains(@class,'col-flag')]" "xpath_element"
And I log out
@javascript
Scenario: Managing tag flags with javascript enabled
Scenario: Managing tag flags
When I log in as "manager1"
And I navigate to "Manage tags" node in "Site administration > Appearance"
And I follow "Default collection"

View File

@ -45,26 +45,8 @@ Feature: Manager can add standard tags and change the tag type of existing tags
And "Remove from standard tags" "link" should exist in the "Tag5" "table_row"
And I log out
Scenario: Changing tag type with javascript disabled
When I log in as "manager1"
And I navigate to "Manage tags" node in "Site administration > Appearance"
And I follow "Default collection"
And I click on "Make standard" "link" in the "Tag0" "table_row"
And I should see "Tag type changed"
And I click on "Make standard" "link" in the "Tag1" "table_row"
And I should see "Tag type changed"
And I click on "Remove from standard tags" "link" in the "Tag0" "table_row"
And I should see "Tag type changed"
And I click on "Remove from standard tags" "link" in the "Tag3" "table_row"
And I should see "Tag type changed"
Then "Make standard" "link" should exist in the "Tag0" "table_row"
And "Remove from standard tags" "link" should exist in the "Tag1" "table_row"
And "Make standard" "link" should exist in the "Tag2" "table_row"
And "Make standard" "link" should exist in the "Tag3" "table_row"
And I log out
@javascript
Scenario: Changing tag type with javascript enabled
Scenario: Changing tag isstandard
When I log in as "manager1"
And I navigate to "Manage tags" node in "Site administration > Appearance"
And I follow "Default collection"
@ -87,7 +69,7 @@ Feature: Manager can add standard tags and change the tag type of existing tags
And "Make standard" "link" should exist in the "Tag3" "table_row"
And I log out
Scenario: Changing tag type in edit form
Scenario: Changing tag isstandard in edit form
When I log in as "manager1"
And I navigate to "Manage tags" node in "Site administration > Appearance"
And I follow "Default collection"