Skip to content

Commit

Permalink
MDL-49650 tool_templatelibrary: New tool for browsing mustache templates
Browse files Browse the repository at this point in the history
  • Loading branch information
Damyon Wiese committed Apr 9, 2015
1 parent bed022d commit 274d79c
Show file tree
Hide file tree
Showing 20 changed files with 935 additions and 1 deletion.
1 change: 1 addition & 0 deletions admin/tool/templatelibrary/amd/build/display.min.js

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

1 change: 1 addition & 0 deletions admin/tool/templatelibrary/amd/build/search.min.js

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

114 changes: 114 additions & 0 deletions admin/tool/templatelibrary/amd/src/display.js
@@ -0,0 +1,114 @@
// 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 adds ajax display functions to the template library page.
*
* @module tool_templatelibrary/display
* @package tool_templatelibrary
* @copyright 2015 Damyon Wiese <damyon@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates', 'core/config', 'core/str'],
function($, ajax, log, notification, templates, config, str) {

/**
* Handle a template loaded response.
*
* @param {String} templateName The template name
* @param {String} source The template source
*/
var templateLoaded = function(templateName, source) {
str.get_string('templateselected', 'tool_templatelibrary', templateName).done(function(s) {
$('[data-region="displaytemplateheader"]').text(s);
}).fail(notification.exception);

// Remove the GPL from the start of the template.

var sections = source.match(/{{!([\s\S]*?)}}/g);
var i = 0;

// Find the first non-empty comment that is not the GPL.
// If no sections match - show the entire file.
if (sections !== null) {
for (i = 0; i < sections.length; i++) {
var section = sections[i];
if ((section.trim() !== '') && (section.indexOf('GNU General Public License') === -1)) {
// Remove {{! and }} from start and end.
section = section.substr(3, section.length - 5);
source = section;
break;
}
}
}

$('[data-region="displaytemplatesource"]').text(source);

// Now search the text for a json example.

var example = source.match(/Example context \(json\):([\s\S]*)/);
var context = false;
if (example) {
var rawJSON = example[1].trim();
try {
context = $.parseJSON(rawJSON);
} catch (e) {
log.debug('Could not parse json example context for template.');
log.debug(e);
}
}
if (context) {
templates.render(templateName, context).done(function(html, js) {
$('[data-region="displaytemplateexample"]').empty();
$('[data-region="displaytemplateexample"]').append(html);
templates.runTemplateJS(js);
}).fail(notification.exception);
} else {
str.get_string('templatehasnoexample', 'tool_templatelibrary').done(function(s) {
$('[data-region="displaytemplateexample"]').text(s);
}).fail(notification.exception);
}
};

/**
* Load the a template source from Moodle.
* @param {String} templateName
*/
var loadTemplate = function(templateName) {
var parts = templateName.split('/');
var component = parts.shift();
var name = parts.shift();

ajax.call([{
methodname: 'core_output_load_template',
args:{
component: component,
template: name,
themename: config.theme
},
done: function(source) { templateLoaded(templateName, source); },
fail: notification.exception
}]);
};

// Add the event listeners.
$('[data-region="list-templates"]').on('click', '[data-templatename]', function() {
var templatename = $(this).data('templatename');
loadTemplate(templatename);
});

// This module does not expose anything.
return {};
});
89 changes: 89 additions & 0 deletions admin/tool/templatelibrary/amd/src/search.js
@@ -0,0 +1,89 @@
// 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 adds ajax search functions to the template library page.
*
* @module tool_templatelibrary/search
* @package tool_templatelibrary
* @copyright 2015 Damyon Wiese <damyon@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates'],
function($, ajax, log, notification, templates) {

/**
* The ajax call has returned with a new list of templates.
*
* @method reloadListTemplate
* @param String[] templates List of template ids.
*/
var reloadListTemplate = function(templateList) {
templates.render('tool_templatelibrary/search_results', { templates: templateList })
.done(function (result) {
$('[data-region="searchresults"]').replaceWith(result);
}).fail(notification.exception);
};

/**
* Get the current values for the form inputs and refresh the list of matching templates.
*
* @method refreshSearch
*/
var refreshSearch = function() {
var componentStr = $('[data-field="component"]').val();
var searchStr = $('[data-field="search"]').val();

// Trigger the search.

ajax.call([
{ methodname: 'tool_templatelibrary_list_templates',
args: { component: componentStr, search: searchStr },
done: reloadListTemplate,
fail: notification.exception }
]);
};

var throttle = null;

/**
* Call the specified function after a delay. If this function is called again before the function is executed,
* the function will only be executed once.
*
* @method queueRefresh
* @param function callback
* @param int delay The time in milliseconds to delay.
*/
var queueRefresh = function(callback, delay) {
if (throttle !== null) {
window.clearTimeout(throttle);
}

throttle = window.setTimeout(function() {
callback();
throttle = null;
}, delay);
};

var changeHandler = function() {
queueRefresh(refreshSearch, 400);
};
// Add change handlers to refresh the list.
$('[data-region="list-templates"]').on('change', '[data-field="component"]', changeHandler);
$('[data-region="list-templates"]').on('input', '[data-field="search"]', changeHandler);

refreshSearch();
return {};
});
92 changes: 92 additions & 0 deletions admin/tool/templatelibrary/classes/api.php
@@ -0,0 +1,92 @@
<?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/>.

/**
* Class for listing mustache templates.
*
* @package tool_templatelibrary
* @copyright 2015 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_templatelibrary;

use stdClass;
use core_component;
use coding_exception;
use required_capability_exception;

/**
* API exposed by tool_templatelibrary
*
* @copyright 2015 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class api {

/**
* Return a list of details about installed templates.
*
* @param string $component Filter the list to a single component.
* @param string $search Search string to optionally filter the list of templates.
* @return array[string] Where each template is in the form "component/templatename".
*/
public static function list_templates($component = '', $search = '') {
global $CFG;

$templatedirs = array();
$results = array();

if ($component != '') {
// Just look at one component for templates.
$dir = core_component::get_component_directory($component);
if (!$dir) {
return $templatedirs;
}

$templatedirs[$component] = $dir . '/templates';
} else {

// Look at all the templates dirs for all installed plugins.
$dir = $CFG->libdir . '/templates';
if (!empty($dir) && is_dir($dir)) {
$templatedirs['core'] = $dir;
}
$plugintypes = core_component::get_plugin_types();
foreach ($plugintypes as $type => $dir) {
$plugins = core_component::get_plugin_list_with_file($type, 'templates', false);
foreach ($plugins as $plugin => $dir) {
if (!empty($dir) && is_dir($dir)) {
$templatedirs[$type . '_' . $plugin] = $dir;
}
}
}
}

foreach ($templatedirs as $templatecomponent => $dir) {
// List it.
$files = glob($dir . '/*.mustache');

foreach ($files as $file) {
$templatename = basename($file, '.mustache');
if ($search == '' || strpos($templatename, $search) !== false) {
$results[] = $templatecomponent . '/' . $templatename;
}
}
}
return $results;
}

}

0 comments on commit 274d79c

Please sign in to comment.