Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
MDL-57898 core_customfield: Custom fields API
This commit is part of work on Custom fields API,
to minimize commit history in moodle core the work of a team of developers was split
into several commits with different authors but the authorship of individual
lines of code may be different from the commit author.
  • Loading branch information
Toni Barberà Melià authored and marinaglancy committed Jan 18, 2019
1 parent c092f75 commit 1eeb465
Show file tree
Hide file tree
Showing 29 changed files with 3,034 additions and 1 deletion.
1 change: 1 addition & 0 deletions customfield/amd/build/form.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

202 changes: 202 additions & 0 deletions customfield/amd/src/form.js
@@ -0,0 +1,202 @@
// 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/>.

/**
* This module depends on the real jquery - and returns the non-global version of it.
*
* @module core_customfield/form
* @package core_customfield
* @copyright 2018 Toni Barbera
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define(['jquery', 'core/str', 'core/notification', 'core/ajax', 'core/templates', 'core/sortable_list'], function(
$, Str, Notification, Ajax, Templates, SortableList) {

/**
* Display confirmation dialogue
*
* @param {Number} id
* @param {String} type
* @param {String} component
* @param {String} area
* @param {Number} itemid
*/
var confirmDelete = function(id, type, component, area, itemid) {
Str.get_strings([
{'key': 'confirm'},
{'key': 'confirmdelete' + type, component: 'core_customfield'},
{'key': 'yes'},
{'key': 'no'},
]).done(function(s) {
Notification.confirm(s[0], s[1], s[2], s[3], function() {
var func = (type === 'field') ? 'core_customfield_delete_field' : 'core_customfield_delete_category';
Ajax.call([
{methodname: func, args: {id: id}},
{methodname: 'core_customfield_reload_template', args: {component: component, area: area, itemid: itemid}}
])[1].then(function(response) {
return Templates.render('core_customfield/list', response);
}).then(function(html, js) {
Templates.replaceNodeContents($('[data-region="list-page"]'), html, js);
return null;
}).fail(Notification.exception);
});
}).fail(Notification.exception);
};

/**
* Creates a new custom fields category with default name and updates the list
*
* @param {String} component
* @param {String} area
* @param {Number} itemid
*/
var createNewCategory = function(component, area, itemid) {
var promises = Ajax.call([
{methodname: 'core_customfield_create_category', args: {component: component, area: area, itemid: itemid}},
{methodname: 'core_customfield_reload_template', args: {component: component, area: area, itemid: itemid}}
]),
categoryid;

promises[0].then(function(response) {
categoryid = response;
return null;
}).fail(Notification.exception);

promises[1].then(function(response) {
return Templates.render('core_customfield/list', response);
}).then(function(html, js) {
Templates.replaceNodeContents($('[data-region="list-page"]'), html, js);
window.location.href = '#category-' + categoryid;
return null;
}).fail(Notification.exception);
};

return {
/**
* Initialise the custom fields manager
*/
init: function() {
var mainlist = $('#customfield_catlist'),
component = mainlist.attr('data-component'),
area = mainlist.attr('data-area'),
itemid = mainlist.attr('data-itemid');
$("[data-role=deletefield]").on('click', function(e) {
confirmDelete($(this).attr('data-id'), 'field', component, area, itemid);
e.preventDefault();
});
$("[data-role=deletecategory]").on('click', function(e) {
confirmDelete($(this).attr('data-id'), 'category', component, area, itemid);
e.preventDefault();
});
$('[data-role=addnewcategory]').on('click', function() {
createNewCategory(component, area, itemid);
});

var categoryName = function(element) {
return element
.closest('[data-category-id]')
.find('[data-inplaceeditable][data-itemtype=category][data-component=core_customfield]')
.attr('data-value');
};

// Sort category.
var sortCat = new SortableList(
'#customfield_catlist .categorieslist',
{moveHandlerSelector: '.movecategory [data-drag-type=move]'}
);

sortCat.getElementName = function(el) {
return $.Deferred().resolve(categoryName(el));
};

$('[data-category-id]').on('sortablelist-drop', function(evt, info) {
if (info.positionChanged) {
var promises = Ajax.call([
{
methodname: 'core_customfield_move_category',
args: {
id: info.element.data('category-id'),
beforeid: info.targetNextElement.data('category-id')
}

},
]);
promises[0].fail(Notification.exception);
}
evt.stopPropagation(); // Important for nested lists to prevent multiple targets.
});

// Sort fields.
var sort = new SortableList(
'#customfield_catlist .fieldslist tbody',
{moveHandlerSelector: '.movefield [data-drag-type=move]'}
);

sort.getDestinationName = function(parentElement, afterElement) {
if (!afterElement.length) {
return Str.get_string('totopofcategory', 'customfield', categoryName(parentElement));
} else if (afterElement.attr('data-field-name')) {
return Str.get_string('afterfield', 'customfield', afterElement.attr('data-field-name'));
} else {
return $.Deferred().resolve('');
}
};

$('[data-field-name]').on('sortablelist-drop', function(evt, info) {
evt.stopPropagation(); // Important for nested lists to prevent multiple targets.
if (info.positionChanged) {
var promises = Ajax.call([
{
methodname: 'core_customfield_move_field',
args: {
id: info.element.data('field-id'),
beforeid: info.targetNextElement.data('field-id'),
categoryid: Number(info.targetList.closest('[data-category-id]').attr('data-category-id'))
},
},
]);
promises[0].fail(Notification.exception);
}
}).on('sortablelist-drag', function(evt) {
evt.stopPropagation(); // Important for nested lists to prevent multiple targets.
// Refreshing fields tables.
Str.get_string('therearenofields', 'core_customfield').then(function(s) {
$('#customfield_catlist .categorieslist').children().each(function() {
var fields = $(this).find($('.field')),
nofields = $(this).find($('.nofields'));
if (!fields.length && !nofields.length) {
$(this).find('tbody').append(
'<tr class="nofields"><td colspan="5">' + s + '</td></tr>'
);
}
if (fields.length && nofields.length) {
nofields.remove();
}
});
return null;
}).fail(Notification.exception);
});

$('[data-category-id], [data-field-name]').on('sortablelist-dragstart',
function(evt, info) {
setTimeout(function() {
$('.sortable-list-is-dragged').width(info.element.width());
}, 501);
}
);

}
};
});
87 changes: 87 additions & 0 deletions customfield/classes/category.php
@@ -0,0 +1,87 @@
<?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/>.

/**
* Customfield category persistent class
*
* @package core_customfield
* @copyright 2018 Toni Barbera <toni@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

namespace core_customfield;

use core\persistent;

defined('MOODLE_INTERNAL') || die;

/**
* Class category
*
* @package core_customfield
* @copyright 2018 Toni Barbera <toni@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class category extends persistent {
/**
* Database table.
*/
const TABLE = 'customfield_category';

/**
* Return the definition of the properties of this model.
*
* @return array
*/
protected static function define_properties(): array {
return array(
'name' => [
'type' => PARAM_TEXT,
],
'description' => [
'type' => PARAM_RAW,
'optional' => true,
'default' => null,
'null' => NULL_ALLOWED
],
'descriptionformat' => [
'type' => PARAM_INT,
'default' => FORMAT_MOODLE,
'optional' => true
],
'component' => [
'type' => PARAM_COMPONENT
],
'area' => [
'type' => PARAM_COMPONENT
],
'itemid' => [
'type' => PARAM_INT,
'optional' => true,
'default' => 0
],
'contextid' => [
'type' => PARAM_INT,
'optional' => false
],
'sortorder' => [
'type' => PARAM_INT,
'optional' => true,
'default' => -1
],
);
}
}

0 comments on commit 1eeb465

Please sign in to comment.