Commit 3a4d4557 authored by Aaron Wells's avatar Aaron Wells Committed by Gerrit Code Review

Merge "Bug 1512147: Allow tag pieform element hook into autocomplete one"

parents 6d8bbfcc 333ccbd6
......@@ -301,7 +301,18 @@ function FileBrowser(idprefix, folderid, config, globalconfig) {
pieform_select_other($(self.id + '_edit_license'));
}
$(self.id + '_edit_allowcomments').checked = self.filedata[id].allowcomments;
$(self.id + '_edit_tags').value = self.filedata[id].tags.join(', ');
$(self.id + '_edit_tags').selectedIndex = -1;
tag_select2_clear(self.id + '_edit_tags');
if (self.filedata[id].tags) {
for (var x in self.filedata[id].tags) {
var option = document.createElement("option");
option.text = option.value = self.filedata[id].tags[x];
option.selected = "selected";
$(self.id + '_edit_tags').add(option);
}
}
replaceChildNodes($(self.id + '_edit_messages'));
forEach(getElementsByTagAndClassName('input', 'permission', self.id + '_edit_row'), function (elem) {
var perm = getNodeAttribute(elem, 'name').split(':');
......@@ -314,8 +325,8 @@ function FileBrowser(idprefix, folderid, config, globalconfig) {
});
// $(self.id + '_edit_artefact').value = id; // Changes button text in IE
setNodeAttribute(self.id + '_edit_artefact', 'name', self.id + '_update[' + id + ']');
var tags_control_elem = augment_tags_control(self.id + '_edit_tags', true);
swapDOM($(self.id + '_edit_tags').parentNode.firstChild, tags_control_elem);
tag_select2(self.id + '_edit_tags');
var edit_row = removeElement(self.id + '_edit_row');
var this_row = getFirstParentByTagAndClassName(this, 'tr');
insertSiblingNodesAfter(this_row, edit_row);
......@@ -337,7 +348,7 @@ function FileBrowser(idprefix, folderid, config, globalconfig) {
return false;
}
this.edit_init = function () { augment_tags_control(self.id + '_edit_tags'); }
this.edit_init = function () { }
this.browse_init = function () {
if (self.config.edit || self.config.editmeta) {
......
......@@ -241,13 +241,40 @@ forEach(getElementsByTagAndClassName('a', 'copytextboxnote', 'instconf'), functi
jQuery('#instconf_tags_description').removeClass('hidden');
});
});
augment_tags_control('instconf_tags');
if (jQuery('#instconf_license').length) {
jQuery('#instconf_license').removeClass('hidden');
}
if (jQuery('#instconf_license_advanced_container').length) {
removeElementClass(getFirstElementByTagAndClassName('div', null, 'instconf_license_advanced_container'), 'hidden');
}
jQuery(function() {
jQuery('#instconf_tags').on('change', function() {
updatetagbuttons();
});
updatetagbuttons();
function updatetagbuttons() {
jQuery('#instconf_tags_container ul button').on('click', function(e) {
e.stopPropagation();
e.preventDefault();
var li = jQuery(this).parent();
var data = jQuery('#instconf_tags').select2('data');
var value = null;
for (var x in data) {
if (li[0].title == data[x].text) {
value = data[x].id;
break;
}
}
var val = jQuery('#instconf_tags').select2('val');
var index = val.indexOf(value);
if (index > -1) {
val.splice(index, 1);
}
jQuery('#instconf_tags').select2('val', val);
});
}
});
EOF;
}
......
......@@ -781,73 +781,47 @@ function keepElementInViewport(element) {
}
}
// this function takes an existing input element and augments it
function augment_tags_control(elem, returnContainer) {
elem = getElement(elem);
var tagContainer = DIV({'class':'showtags'});
// setElementDimensions(tagContainer, {'w': getElementDimensions(elem).w});
var showLink = A({'href':''},get_string('showtags'));
appendChildNodes(tagContainer, showLink);
connect(showLink, 'onclick', function (e) {
e.stop();
replaceChildNodes(tagContainer, get_string('loading') + ' ', SPAN({'class': 'icon-spinner icon-pulse icon icon-lg'}));
sendjsonrequest(config.wwwroot + 'json/taglist.php', {}, 'GET', function (data) {
replaceChildNodes(tagContainer);
if (data.length == 0) {
appendChildNodes(tagContainer, get_string('youhavenottaggedanythingyet'));
}
else {
var tagData = [];
forEach(data, function(tag) {
var tagLink = A({'href':'', 'class':'tag'}, tag.tag);
connect(tagLink, 'onclick', function(e) {
e.stop();
if (typeof formchangemanager !== 'undefined') {
// Get the form which contains the tag input
var form = jQuery(elem).closest('form')[0];
formchangemanager.setFormState(form, FORM_CHANGED);
}
if (some(elem.value.split(/ *, */), function(t) { return t == tag.tag; })) {
// If at the start of the string, remove it and the comma/spaces after
elem.value = elem.value.replace(new RegExp('^' + escapeRegExp(tag.tag) + ',? *'), '');
// Otherwise, remove the comma/spaces before it
elem.value = elem.value.replace(new RegExp(', *' + escapeRegExp(tag.tag)), '');
return;
}
if (elem.value.match(/^ *$/) || elem.value.match(/, *$/)) {
elem.value += tag.tag;
}
else {
elem.value += ', ' + tag.tag;
}
});
tagData.push([tagLink, '\u00A0(', tag.count, ')']);
tagData.push(', ');
//appendChildNodes(tagContainer, tagLink, '\u00A0(', tag.count, ')');
});
// Remove the last comma
tagData.pop();
forEach(tagData, function(i) {
appendChildNodes(tagContainer, i);
});
}
});
});
if (typeof(returnContainer) == 'boolean' && returnContainer) {
return tagContainer;
function tag_select2_clear(id) {
var select2 = jQuery('#' + id).data('select2');
if (select2) {
jQuery('#' + id).select2();
}
jQuery('#' + id).find('option').remove();
}
var help = getFirstElementByTagAndClassName('span', 'help', elem.parentNode);
var newNode = DIV({'class':'tag-wrapper'});
swapDOM(elem, newNode);
appendChildNodes(newNode, tagContainer, elem, ' ', help);
};
function tag_select2(id) {
jQuery('#' + id).select2({
ajax: {
url: config.wwwroot + "json/taglist.php",
dataType: 'json',
type: 'POST',
delay: 250,
data: function(params) {
return {
'q': params.term,
'page': params.page || 0,
'sesskey': config.sesskey,
'offset': 0,
'limit': 10,
}
},
processResults: function(data, page) {
return {
results: data.results,
pagination: {
more: data.more
}
};
}
},
multiple: true,
width: "300px",
allowClear: false,
placeholder: "Type in a search term",
minimumInputLength: 1,
tags: true,
});
}
function progressbarUpdate(artefacttype, remove) {
if (! $('progressbarwrap')) {
......
......@@ -12,41 +12,42 @@
define('INTERNAL', 1);
define('JSON', 1);
require(dirname(dirname(__FILE__)) . '/init.php');
require_once(get_config('docroot') . 'lib/form/elements/tags.php');
if ($USER->is_logged_in()) {
$usertags = "";
$userid = $USER->get('id');
if ($USER->get('admin')) {
$usertags = "
UNION ALL
SELECT tag,COUNT(*) AS count FROM {usr_tag} t INNER JOIN {usr} u ON t.usr=u.id GROUP BY 1";
}
else if ($admininstitutions = $USER->get('admininstitutions')) {
$insql = "'" . join("','", $admininstitutions) . "'";
$usertags = "
UNION ALL
SELECT tag,COUNT(*) AS count FROM {usr_tag} t INNER JOIN {usr} u ON t.usr=u.id INNER JOIN {usr_institution} ui ON ui.usr=u.id WHERE ui.institution IN ($insql) GROUP BY 1";
}
$result = get_records_sql_array("
SELECT tag, SUM(count) AS count
FROM (
SELECT tag,COUNT(*) AS count FROM {artefact_tag} t INNER JOIN {artefact} a ON t.artefact=a.id WHERE a.owner=? GROUP BY 1
UNION ALL
SELECT tag,COUNT(*) AS count FROM {view_tag} t INNER JOIN {view} v ON t.view=v.id WHERE v.owner=? GROUP BY 1
UNION ALL
SELECT tag,COUNT(*) AS count FROM {collection_tag} t INNER JOIN {collection} c ON t.collection=c.id WHERE c.owner=? GROUP BY 1
" . $usertags . "
) tags
GROUP BY tag
ORDER BY LOWER(tag)
",
array($userid, $userid, $userid)
);
global $USER;
$request = param_variable('q');
$page = param_integer('page');
if ($page < 1) {
$page = 1;
}
$tagsperpage = 10;
$more = true;
$tmptag = array();
while ($more && count($tmptag) < $tagsperpage) {
$tags = get_all_tags_for_user($request, $tagsperpage, $tagsperpage * ($page - 1));
$more = $tags['count'] > $tagsperpage * $page;
if (empty($result)) {
$result = array();
if (!$tags['tags']) {
$tags['tags'] = array();
}
foreach ($tags['tags'] as $tag) {
if (count($tmptag) >= $tagsperpage) {
$more = true;
continue;
}
$tmptag[] = (object) array('id' => $tag->tag,
'text' => display_tag($tag->tag, $tags['tags'])
);
}
$page++;
}
json_headers();
print json_encode($result);
echo json_encode(array(
'more' => $more,
'results' => $tmptag,
));
......@@ -139,8 +139,8 @@ $string['select'] = 'Select';
// Tags
$string['tags'] = 'Tags';
$string['tagsdesc'] = 'Enter comma-separated tags for this item.';
$string['tagsdescprofile'] = 'Enter comma-separated tags for this item. Items tagged with \'profile\' are displayed in your sidebar.';
$string['tagsdesc'] = 'Search for/enter tags for this item.';
$string['tagsdescprofile'] = 'Search for/enter tags for this item. Items tagged with \'profile\' are displayed in your sidebar.';
$string['youhavenottaggedanythingyet'] = 'You have not tagged anything yet';
$string['mytags'] = 'My tags';
$string['Tag'] = 'Tag';
......
......@@ -561,7 +561,7 @@ function pieform_element_filebrowser_doupdate(Pieform $form, $element) {
'artefact' => $artefactid,
'title' => $edit_title,
'description' => param_variable($prefix . '_edit_description'),
'tags' => param_variable($prefix . '_edit_tags'),
'tags' => param_variable($prefix . '_edit_tags', ''),
'folder' => $element['folder'],
'allowcomments' => param_boolean($prefix . '_edit_allowcomments'),
);
......@@ -1169,7 +1169,7 @@ function pieform_element_filebrowser_update(Pieform $form, $element, $data) {
$artefact->set('allowcomments', (int) $data['allowcomments']);
$oldtags = $artefact->get('tags');
$newtags = preg_split("/\s*,\s*/", trim($data['tags']));
$newtags = $data['tags'];
$updatetags = $oldtags != $newtags;
if ($updatetags) {
$artefact->set('tags', $newtags);
......
<?php
require_once(get_config('docroot') . 'lib/form/elements/autocomplete.php');
/**
*
* @package mahara
......@@ -17,55 +18,114 @@
* @return string The HTML for the element
*/
function pieform_element_tags(Pieform $form, $element) {
$smarty = smarty_core();
$value = array();
if (isset($element['defaultvalue']) && is_array($element['defaultvalue'])) {
$value = $element['defaultvalue'];
}
if ($tempvalue = $form->get_value($element)) {
$value = $tempvalue;
}
$newelement = array(
'type' => 'autocomplete',
'title' => $element['title'],
'id' => $element['id'],
'name' => $element['name'],
'defaultvalue' => isset($element['defaultvalue']) ? $element['defaultvalue'] : null,
'description' => isset($element['description']) ? $element['description'] : null,
'help' => isset($element['help']) ? $element['help'] : false,
'ajaxurl' => get_config('wwwroot') . 'json/taglist.php',
'multiple' => true,
'allowclear' => false,
'initfunction' => 'translate_tags_to_names',
'ajaxextraparams' => array(),
'extraparams' => array('tags' => true),
'width' => '280px',
);
return pieform_element_autocomplete($form, $newelement);
}
if (isset($element['value']) && is_array($element['value'])) {
$value = $element['value'];
}
function translate_tags_to_names(array $ids) {
global $USER;
// for an empty list, the element '' is transmitted
$ids = array_diff($ids, array(''));
$results = array();
$alltags = get_all_tags_for_user();
if (!is_array($value)) {
$value = array();
foreach ($ids as $id) {
if (isset($alltags['tags'][$id])) {
$results[] = (object) array('id' => $id, 'text' => display_tag($id, $alltags['tags']));
}
else {
$results[] = (object) array('id' => $id, 'text' => hsc($id));
}
}
return $results;
}
if (!isset($element['size'])) {
$element['size'] = 60;
}
/**
* Display formatted tag
* Currently is tag name plus the usage count
*
* @param string $name Tag name
* @param string $alltags Array of tags to get the information from
* @return $tag Formatted tag
*/
function display_tag($name, $alltags) {
return $name . ' (' . $alltags[$name]->count . ')';
}
$smarty->assign('name', $element['name']);
$smarty->assign('size', $element['size']);
$smarty->assign('id', $form->get_name() . '_' . $element['id']);
$smarty->assign('value', join(', ', $value));
if (isset($element['description'])) {
$smarty->assign('describedby', $form->element_descriptors($element));
/**
* Get all tags created by this user
*
* @param string $query Search option
* @param int $limit
* @param int $offset
* @retun array $tags The tags this user has created
*/
function get_all_tags_for_user($query = null, $limit = null, $offset = null) {
global $USER;
if ($USER->is_logged_in()) {
$usertags = "";
$userid = $USER->get('id');
if ($USER->get('admin')) {
$usertags = "
UNION ALL
SELECT tag,COUNT(*) AS count FROM {usr_tag} t INNER JOIN {usr} u ON t.usr=u.id GROUP BY 1";
}
else if ($admininstitutions = $USER->get('admininstitutions')) {
$insql = "'" . join("','", $admininstitutions) . "'";
$usertags = "
UNION ALL
SELECT tag,COUNT(*) AS count FROM {usr_tag} t INNER JOIN {usr} u ON t.usr=u.id INNER JOIN {usr_institution} ui ON ui.usr=u.id WHERE ui.institution IN ($insql) GROUP BY 1";
}
$values = array($userid, $userid, $userid);
$querystr = '';
if ($query) {
$querystr = " WHERE tag LIKE '%' || ? || '%'";
$values[] = $query;
}
$sql = "
SELECT tag, SUM(count) AS count
FROM (
SELECT tag,COUNT(*) AS count FROM {artefact_tag} t INNER JOIN {artefact} a ON t.artefact=a.id WHERE a.owner=? GROUP BY 1
UNION ALL
SELECT tag,COUNT(*) AS count FROM {view_tag} t INNER JOIN {view} v ON t.view=v.id WHERE v.owner=? GROUP BY 1
UNION ALL
SELECT tag,COUNT(*) AS count FROM {collection_tag} t INNER JOIN {collection} c ON t.collection=c.id WHERE c.owner=? GROUP BY 1
" . $usertags . "
) tags
" . $querystr . "
GROUP BY tag
ORDER BY LOWER(tag)
";
$result = get_records_sql_assoc($sql, $values, $offset, $limit);
}
$results = !empty($result) ? $result : array();
$return = array('tags' => $results,
'count' => count($results),
);
$smarty->left_delimiter = '{{';
$smarty->right_delimiter = '}}';
return $return;
}
return $smarty->fetch('form/tags.tpl');
function pieform_element_tags_get_headdata($element) {
return pieform_element_autocomplete_get_headdata($element);
}
function pieform_element_tags_get_value(Pieform $form, $element) {
$name = $element['name'];
$global = ($form->get_property('method') == 'get') ? $_GET : $_POST;
if (!isset($global[$name])) {
return null;
}
$value = preg_split("/\s*,\s*/", trim($global[$name]));
$value = array_unique(array_filter($value, create_function('$v', 'return !empty($v);')));
return $value;
return pieform_element_autocomplete_get_value($form, $element);
}
......@@ -102,6 +102,15 @@ class BehatForms extends BehatBase {
$values = json_encode($values);
$this->getSession()->executeScript("jQuery('#{$field}').val({$values}).trigger('change');");
}
/**
* Clears the Select2 field
*
* @When /^(?:|I )clear the select2 field "(?P<field>(?:[^"]|\\")*)"$/
*/
public function iClearSelect2Field($field) {
$page = $this->getSession()->getPage();
$this->getSession()->executeScript("jQuery('#{$field}').val('').trigger('change');");
}
/**
* Fill Select2 input field
*
......@@ -160,6 +169,7 @@ class BehatForms extends BehatBase {
$select2Input->postValue(['value' => [$value]]);
$this->getSession()->wait(10000, "(jQuery('#select2-{$field}-results .loading-results').length === 0)");
}
/**
* Select value in choice list
*
......
......@@ -17,7 +17,11 @@
{/if}
<div class="tags form-group">
<label for="{$prefix}_edit_tags">{str tag=tags}</label>
<input name="{$prefix}_edit_tags" id="{$prefix}_edit_tags" class="text" type="text" value="{foreach from=$fileinfo->tags item=tag name=tags}{if !$.foreach.tags.first}, {/if}{$tag}{/foreach}" />
<select name="{$prefix}_edit_tags[]" id="{$prefix}_edit_tags" class="js-data-ajax" multiple="multiple">
{foreach from=$fileinfo->tags item=tag name=tags}
<option value="{$tag}">{$tag}</option>
{/foreach}
</select>
<span>{contextualhelp plugintype='artefact' pluginname='file' section='tags'}</span>
<div class="description">{str tag=tagsdescprofile}</div>
</div>
......
<input type="text" size="{{$size}}" id="{{$id}}" name="{{$name}}" value="{{$value}}" {{if $describedby}}aria-describedby="{{$describedby}}"{{/if}}>
<script type="application/javascript">
var tags_changed = false;
addLoadEvent(partial(augment_tags_control,'{{$id}}'))
</script>
\ No newline at end of file
......@@ -24,6 +24,25 @@ Feature: Mahara users can create their blogs
When I click on "Create journal"
And I fill in the following:
| title | My new journal |
| tags | blog |
And I fill in select2 input "newblog_tags" with "blog" and select "blog"
And I press "Create journal"
Then I should see "My new journal"
# Check that we can add the blog to tagged blogs block
Given I follow "My new journal"
And I follow "New entry"
And I set the following fields to these values:
| Title | Journal entry 1 |
| Entry | This is a test |
When I fill in select2 input "editpost_tags" with "blogentry" and select "blogentry"
And I press "Save entry"
And I choose "Pages" in "Portfolio"
And I press "Create page"
And I press "Save"
And I expand "Journals" node in the "div#content-editor-foldable" "css_element"
And I wait "1" seconds
And I follow "Tagged journal entries"
And I press "Add"
And I fill in select2 input "instconf_tagselect" with "blogentry" and select "blogentry"
And I press "Save"
Then I should see "Journal entries with tag \"blogentry\""
@javascript @core @core_content
Feature: Creating a journal and testing out tags
@javascript @core @core_content @core_artefact
Feature: Creating a journal
In order write in my journal
As an admin
I need to have a journal
......@@ -15,15 +15,16 @@ Background:
| Journal page | Page to contain the tagged journal block | user | userA |
Scenario: Creating a Journal, publishing a draft, using tagged entry block
# Create draft entry
Given I log in as "userA" with password "Kupuhipa1"
When I choose "Journals" in "Content"
And I follow "New entry"
And I set the following fields to these values:
| Title * | My diary entry one |
| Entry | I love my mum |
| Tags | mildred |
| Draft | 1 |
| Allow comments | 0 |
And I fill in select2 input "editpost_tags" with "mildred" and select "mildred"
And I press "Save entry"
Then I should see "Journal entry saved"
And I should see "Draft"
......@@ -32,16 +33,26 @@ Scenario: Creating a Journal, publishing a draft, using tagged entry block
Given I press "Publish"
Then I should see "Published"
# Add another entry
And I follow "New entry"
And I set the following fields to these values:
| Title * | My diary entry two |
| Entry | I love my dad |
| Tags | george |
| Draft | 0 |
| Allow comments | 0 |
And I fill in select2 input "editpost_tags" with "george" and select "george"
And I press "Save entry"
Then I should see "Journal entry saved"
# Remove tag from first journal and save
Given I click on "Edit" in "My diary entry one" row
And I wait "1" seconds
And I clear the select2 field "editpost_tags"
And I press "Save entry"
Then I should see "Journal entry saved"
And I should not see "mildred"
# Display tagged journals in block
When I follow "Portfolio"
And I follow "Edit \"Journal page\""
And I expand "Journals" node in the "div#content-editor-foldable" "css_element"
......
......@@ -13,22 +13,24 @@ Scenario: Adding tags to files (Bug 1426983)
# Creating a folder with a tag
When I choose "Files" in "Content"
And I set the following fields to these values:
|Create folder | folder1 |
| Create folder | folder1 |
# Pressing create folder button
And I press "Create folder"
# Editing the folder
And I press "Edit folder \"folder1\""
And I set the following fields to these values:
| Description | This is a subdirectory |
| Tags | folder |
And I fill in select2 input "files_filebrowser_edit_tags" with "folder" and select "folder"
And I press "Save changes"
#Creating a Journal with tag
And I choose "Journals" in "Content"
And I follow "New entry"
And I set the following fields to these values:
| Title * | Journal one |
| Tags | journal, test |
| Entry | This is a test |
And I fill in select2 input "editpost_tags" with "journal" and select "journal"
And I scroll to the base of id "editpost_tags_container"
And I fill in select2 input "editpost_tags" with "test" and select "test"
And I press "Save entry"
# Creating a Plan with a tag
And I choose "Plans" in "Content"
......@@ -36,35 +38,41 @@ Scenario: Adding tags to files (Bug 1426983)
And I fill in the following:
| Title * | Plan 9 from outer space |
| Description | Woooo |
| Tags | plan, test |
And I fill in select2 input "addplan_tags" with "plan" and select "plan"
And I fill in select2 input "addplan_tags" with "test" and select "test"
And I press "Save plan"
# Creating a Task with a tag
And I follow "New task"
And I fill in the following:
| Title * | Task one |
| Completion date * | 2020/12/31 |
| Tags | task, test |
And I fill in select2 input "addtasks_tags" with "task" and select "task"
And I scroll to the base of id "addtasks_tags_container"
And I fill in select2 input "addtasks_tags" with "test" and select "test"
And I press "Save task"
# Creating page 1 with a tag
And I follow "Portfolio"
And I press "Create page"
And I set the following fields to these values:
| Page title * | Test page 1 |
| Tags | page, test |
And I fill in select2 input "editview_tags" with "page" and select "page"
And I fill in select2 input "editview_tags" with "test" and select "test"
And I press "Save"
And I follow "Portfolio"
# Creating page 2 with a tag
And I press "Create page"
And I set the following fields to these values:
| Page title * | Testing page 2 |
| Tags | page, test |
And I fill in select2 input "editview_tags" with "page" and select "page"
And I fill in select2 input "editview_tags" with "test" and select "test"
And I press "Save"
# Creating a Note with a tag
And I expand "General" node
And I wait "1" seconds
And I follow "Note" in the "div#general" "css_element"
And I press "Add"
And I fill in "Tags" with "box, test"
And I fill in select2 input "instconf_tags" with "box" and select "box"
And I fill in select2 input "instconf_tags" with "test" and select "test"
And I press "Save"
And I go to "/view/index.php"
And I wait "1" seconds
......
......@@ -3,14 +3,15 @@ Feature: Creating a plan and adding a number of tasks to the plan
As a user
In order to test the pagination of the plan
Scenario: Creating a plan with 11 tasks
Scenario: Creating a plan with 11 tasks (Bug #1503036)
Given I log in as "admin" with password "Kupuhipa1"
And I choose "Plans" in "Content"
And I follow "New plan"
And I fill in the following:
| Title * | Plan 9 from outer space |
| Description | Woooo |
| Tags | plan, test |
And I fill in select2 input "addplan_tags" with "plan" and select "plan"
And I fill in select2 input "addplan_tags" with "test" and select "test"
And I press "Save plan"
And I follow "New task"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment