mirror of
https://github.com/moodle/moodle.git
synced 2025-08-04 08:26:37 +02:00
MDL-61460 tool_componentlibrary: Documentation for Moodle UI components
- This tool is only available for admins - Before using this tool the hosting admin will need to have NPM installed and be able to run grunt - To create the docs pages for the library run "grunt componentlibrary" - After the pages are created the Library is available in Site adminstration > Development > UI Component Library
This commit is contained in:
parent
fa073102d3
commit
3de68ad434
140 changed files with 9501 additions and 2 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -51,3 +51,5 @@ moodle-plugin-ci.phar
|
|||
.eslintignore
|
||||
.stylelintignore
|
||||
/jsdoc
|
||||
/admin/tool/componentlibrary/docs
|
||||
/admin/tool/componentlibrary/hugo/site/data/my-index.json
|
||||
|
|
|
@ -129,6 +129,9 @@ module.exports = grunt => {
|
|||
},
|
||||
});
|
||||
|
||||
// Add the 'componentlibrary' task as a startup task.
|
||||
grunt.moodleEnv.startupTasks.push('componentlibrary');
|
||||
|
||||
return {
|
||||
docsBuild,
|
||||
cssBuild,
|
||||
|
|
|
@ -50,6 +50,7 @@ module.exports = grunt => {
|
|||
'theme/boost/style/moodle.css',
|
||||
'theme/classic/style/moodle.css',
|
||||
'jsdoc/styles/*.css',
|
||||
'admin/tool/componentlibrary/hugo/dist/css/docs.css',
|
||||
].concat(thirdPartyPaths);
|
||||
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n') + '\n');
|
||||
};
|
||||
|
|
2
admin/tool/componentlibrary/amd/build/clipboardwrapper.min.js
vendored
Normal file
2
admin/tool/componentlibrary/amd/build/clipboardwrapper.min.js
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
define ("tool_componentlibrary/clipboardwrapper",["exports","core/copy_to_clipboard","tool_componentlibrary/selectors","core/templates"],function(a,b,c,d){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.clipboardWrapper=void 0;c=e(c);d=e(d);function e(a){return a&&a.__esModule?a:{default:a}}function f(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function g(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var i=a.apply(b,c);function g(a){f(i,d,e,g,h,"next",a)}function h(a){f(i,d,e,g,h,"throw",a)}g(void 0)})}}var h=0,i=function(){var a=g(regeneratorRuntime.mark(function a(){return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:document.querySelectorAll(c.default.clipboardcontent).forEach(function(a){if(!a.id){a.id="tool_componentlibrary_content-".concat(h++)}d.default.renderForPromise("tool_componentlibrary/clipboardbutton",{clipboardtarget:"#".concat(a.id," code")}).then(function(b){var c=b.html,e=b.js;d.default.prependNodeContents(a,c,e);return}).catch()});case 1:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}();a.clipboardWrapper=i});
|
||||
//# sourceMappingURL=clipboardwrapper.min.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../src/clipboardwrapper.js"],"names":["idCounter","clipboardWrapper","document","querySelectorAll","selectors","clipboardcontent","forEach","element","id","Templates","renderForPromise","clipboardtarget","then","html","js","prependNodeContents","catch"],"mappings":"mPAwBA,OACA,O,qXAEIA,CAAAA,CAAS,CAAG,C,CAKHC,CAAgB,4CAAG,8FAC5BC,QAAQ,CAACC,gBAAT,CAA0BC,UAAUC,gBAApC,EAAsDC,OAAtD,CAA8D,SAAAC,CAAO,CAAI,CACrE,GAAI,CAACA,CAAO,CAACC,EAAb,CAAiB,CACbD,CAAO,CAACC,EAAR,yCAA8CR,CAAS,EAAvD,CACH,CACDS,UAAUC,gBAAV,CAA2B,uCAA3B,CAAoE,CAACC,eAAe,YAAMJ,CAAO,CAACC,EAAd,SAAhB,CAApE,EACCI,IADD,CACM,WAAgB,IAAdC,CAAAA,CAAc,GAAdA,IAAc,CAARC,CAAQ,GAARA,EAAQ,CAClBL,UAAUM,mBAAV,CAA8BR,CAA9B,CAAuCM,CAAvC,CAA6CC,CAA7C,EACA,MACH,CAJD,EAKCE,KALD,EAMH,CAVD,EAD4B,wCAAH,uD","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Interface to using clipboard.js\n *\n * @module tool_componentlibrary/clipboardwrapper\n * @package tool_componentlibrary\n * @copyright 2021 Bas Brands <bas@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport 'core/copy_to_clipboard';\nimport selectors from 'tool_componentlibrary/selectors';\nimport Templates from 'core/templates';\n\nlet idCounter = 0;\n\n/**\n * Initialise the clipboard button on all reusable code.\n */\nexport const clipboardWrapper = async() => {\n document.querySelectorAll(selectors.clipboardcontent).forEach(element => {\n if (!element.id) {\n element.id = `tool_componentlibrary_content-${idCounter++}`;\n }\n Templates.renderForPromise('tool_componentlibrary/clipboardbutton', {clipboardtarget: `#${element.id} code`})\n .then(({html, js}) => {\n Templates.prependNodeContents(element, html, js);\n return;\n })\n .catch();\n });\n};\n"],"file":"clipboardwrapper.min.js"}
|
2
admin/tool/componentlibrary/amd/build/jsrunner.min.js
vendored
Normal file
2
admin/tool/componentlibrary/amd/build/jsrunner.min.js
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
define ("tool_componentlibrary/jsrunner",["exports","tool_componentlibrary/selectors"],function(_exports,_selectors){"use strict";Object.defineProperty(_exports,"__esModule",{value:!0});_exports.jsRunner=void 0;_selectors=_interopRequireDefault(_selectors);function _interopRequireDefault(a){return a&&a.__esModule?a:{default:a}}var jsRunner=function(){var compLib=document.querySelector(_selectors.default.componentlibrary);compLib.querySelectorAll(_selectors.default.jscode).forEach(function(runjs){eval(runjs.innerHTML)})};_exports.jsRunner=jsRunner});
|
||||
//# sourceMappingURL=jsrunner.min.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../src/jsrunner.js"],"names":["jsRunner","compLib","document","querySelector","selectors","componentlibrary","querySelectorAll","jscode","forEach","runjs","eval","innerHTML"],"mappings":"mNAwBA,8C,wEAQO,GAAMA,CAAAA,QAAQ,CAAG,UAAM,CAC1B,GAAMC,CAAAA,OAAO,CAAGC,QAAQ,CAACC,aAAT,CAAuBC,mBAAUC,gBAAjC,CAAhB,CACAJ,OAAO,CAACK,gBAAR,CAAyBF,mBAAUG,MAAnC,EAA2CC,OAA3C,CAAmD,SAAAC,KAAK,CAAI,CACxDC,IAAI,CAACD,KAAK,CAACE,SAAP,CACP,CAFD,CAGH,CALM,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * This is called from to run any js code\n *\n * @module tool_componentlibrary/jsrunner\n * @package tool_componentlibrary\n * @copyright 2021 Bas Brands <bas@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport selectors from 'tool_componentlibrary/selectors';\n\n/**\n * The Hugo shortcodes changes the JavaScript in markdownfiles from\n * the Moodle mustache {{js}} code... {{/js}} syntax into a div with\n * attribute data-action='runjs'. See hugo/site/layouts/shortcodes/example.html.\n * This code fetches and runs the JavaScript content.\n */\nexport const jsRunner = () => {\n const compLib = document.querySelector(selectors.componentlibrary);\n compLib.querySelectorAll(selectors.jscode).forEach(runjs => {\n eval(runjs.innerHTML); // eslint-disable-line no-eval\n });\n};\n"],"file":"jsrunner.min.js"}
|
2
admin/tool/componentlibrary/amd/build/loader.min.js
vendored
Normal file
2
admin/tool/componentlibrary/amd/build/loader.min.js
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
define ("tool_componentlibrary/loader",["exports","./mustache","./jsrunner","./clipboardwrapper","./search"],function(a,b,c,d,e){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;a.init=function init(a){(0,b.mustache)();(0,c.jsRunner)();(0,d.clipboardWrapper)();(0,e.search)(a)}});
|
||||
//# sourceMappingURL=loader.min.js.map
|
1
admin/tool/componentlibrary/amd/build/loader.min.js.map
Normal file
1
admin/tool/componentlibrary/amd/build/loader.min.js.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../src/loader.js"],"names":["init","jsonFile"],"mappings":"oNAkCoB,QAAPA,CAAAA,IAAO,CAAAC,CAAQ,CAAI,CAC5B,iBACA,iBACA,yBACA,aAAOA,CAAP,CACH,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * This initialises the component library JS\n *\n * @module tool_componentlibrary/loader\n * @package tool_componentlibrary\n * @copyright 2021 Bas Brands <bas@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {mustache} from './mustache';\nimport {jsRunner} from './jsrunner';\nimport {clipboardWrapper} from './clipboardwrapper';\nimport {search} from './search';\n\n/**\n * Load all the component library JavaScript.\n *\n * @param {string} jsonFile Full path to the JSON file with the search DB.\n */\nexport const init = jsonFile => {\n mustache();\n jsRunner();\n clipboardWrapper();\n search(jsonFile);\n};\n"],"file":"loader.min.js"}
|
2
admin/tool/componentlibrary/amd/build/lunr.min.js
vendored
Normal file
2
admin/tool/componentlibrary/amd/build/lunr.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
admin/tool/componentlibrary/amd/build/lunr.min.js.map
Normal file
1
admin/tool/componentlibrary/amd/build/lunr.min.js.map
Normal file
File diff suppressed because one or more lines are too long
2
admin/tool/componentlibrary/amd/build/mustache.min.js
vendored
Normal file
2
admin/tool/componentlibrary/amd/build/mustache.min.js
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
define ("tool_componentlibrary/mustache",["exports","tool_componentlibrary/selectors","core/ajax","core/config","core/templates","core/log","core/notification"],function(a,b,c,d,e,f,g){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.mustache=void 0;b=h(b);c=h(c);d=h(d);e=h(e);f=h(f);g=h(g);function h(a){return a&&a.__esModule?a:{default:a}}function i(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function j(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var h=a.apply(b,c);function f(a){i(h,d,e,f,g,"next",a)}function g(a){i(h,d,e,f,g,"throw",a)}f(void 0)})}}var k=function(){var a=j(regeneratorRuntime.mark(function a(c,d,g){var h,i,j,k;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:try{g=JSON.parse(g)}catch(a){f.default.debug("Could not parse json example context for template.");f.default.debug(a)}a.next=3;return e.default.renderForPromise(d,g);case 3:h=a.sent;i=h.html;j=h.js;k=c.querySelector(b.default.mustacherendered);a.next=9;return e.default.replaceNodeContents(k,i,j);case 9:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}(),l=function(a){var e=a.querySelector(b.default.mustachesource),f=a.querySelector(b.default.mustachecontext),h=a.dataset.template,i=a.querySelector(b.default.mustacherawcontext).textContent,j=h.split("/"),l=j.shift(),m=j.join("/"),n={methodname:"core_output_load_template",args:{component:l,template:m,themename:d.default.theme,includecomments:!0}};c.default.call([n])[0].done(function(b){e.textContent=b;if(!i){var c=b.match(/Example context \(json\):([\s\S]+?)(}})/);i=c[1];var d=document.createElement("pre");d.innerHTML=JSON.stringify(JSON.parse(i),null,4);f.parentNode.appendChild(d);f.classList.add("d-none")}k(a,h,i)}).fail(g.default.exception)},m=function(){document.querySelectorAll(b.default.mustachecode).forEach(function(a){l(a)})};a.mustache=m});
|
||||
//# sourceMappingURL=mustache.min.js.map
|
File diff suppressed because one or more lines are too long
2
admin/tool/componentlibrary/amd/build/search.min.js
vendored
Normal file
2
admin/tool/componentlibrary/amd/build/search.min.js
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
define ("tool_componentlibrary/search",["exports","tool_componentlibrary/lunr","tool_componentlibrary/selectors","core/log","core/notification","core/key_codes"],function(a,b,c,d,e,f){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.search=void 0;b=g(b);c=g(c);d=g(d);e=g(e);function g(a){return a&&a.__esModule?a:{default:a}}function h(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function i(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var i=a.apply(b,c);function f(a){h(i,d,e,f,g,"next",a)}function g(a){h(i,d,e,f,g,"throw",a)}f(void 0)})}}var j=null,k=null,l=function(){var a=i(regeneratorRuntime.mark(function a(b){var c;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:a.next=2;return fetch(b);case 2:c=a.sent;if(!c.ok){d.default.debug("Error getting Hugo index file: ".concat(c.status))}a.next=6;return c.json();case 6:return a.abrupt("return",a.sent);case 7:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}(),m=function(a){l(a).then(function(a){k=a;j=(0,b.default)(function(){var b=this;this.ref("uri");this.field("title",{boost:10});this.field("content");this.field("tags",{boost:5});a.forEach(function(a){b.add(a)})});return null}).catch(e.default.exception)},n=function(){var a=document.querySelector(c.default.searchinput);a.addEventListener("keyup",function(a){var b=a.currentTarget.value;if(2>b.length){document.querySelector(c.default.dropdownmenu).classList.remove("show");return}p(o(b))});a.addEventListener("keydown",function(b){if(b.keyCode===f.enter){b.preventDefault()}if(b.keyCode===f.escape){a.value=""}})},o=function(a){return j.search(a+" "+a+"*").map(function(a){return k.filter(function(b){return b.uri===a.ref})[0]})},p=function(a){var b=document.querySelector(c.default.dropdownmenu);if(!a.length){b.classList.remove("show");return}b.innerHTML="";var d=M.cfg.wwwroot+"/admin/tool/componentlibrary/docspage.php";a.slice(0,10).forEach(function(a){var c=document.createElement("a"),e=a.uri.split("/")[1];c.appendChild(document.createTextNode("".concat(e," > ").concat(a.title)));c.classList.add("dropdown-item");c.href=d+a.uri;b.appendChild(c)});b.classList.add("show")};a.search=function search(a){m(a);n()}});
|
||||
//# sourceMappingURL=search.min.js.map
|
1
admin/tool/componentlibrary/amd/build/search.min.js.map
Normal file
1
admin/tool/componentlibrary/amd/build/search.min.js.map
Normal file
File diff suppressed because one or more lines are too long
2
admin/tool/componentlibrary/amd/build/selectors.min.js
vendored
Normal file
2
admin/tool/componentlibrary/amd/build/selectors.min.js
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
define ("tool_componentlibrary/selectors",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;a.default={clipboardbutton:".btn-clipboard",clipboardcontent:"figure.highlight, div.highlight",searchinput:"[data-region=\"docsearch\"] input",searchsubmit:"[data-region=\"docsearch\"] .btn-submit",dropdownmenu:"[data-region=\"docsearch\"] .dropdown-menu",componentlibrary:"[data-region=\"componentlibrary\"]",jscode:"[data-action=\"runjs\"]",mustachecode:"[data-region=\"mustachecode\"]",mustacherawcontext:"[data-region=\"rawcontext\"]",mustacherendered:"[data-region=\"mustacherendered\"]",mustachesource:"[data-region=\"mustachesource\"]",mustachecontext:"[data-region=\"mustachecontext\"]"};return a.default});
|
||||
//# sourceMappingURL=selectors.min.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../src/selectors.js"],"names":["clipboardbutton","clipboardcontent","searchinput","searchsubmit","dropdownmenu","componentlibrary","jscode","mustachecode","mustacherawcontext","mustacherendered","mustachesource","mustachecontext"],"mappings":"2JAwBe,CACXA,eAAe,CAAE,gBADN,CAEXC,gBAAgB,CAAE,iCAFP,CAGXC,WAAW,CAAE,mCAHF,CAIXC,YAAY,CAAE,yCAJH,CAKXC,YAAY,CAAE,4CALH,CAMXC,gBAAgB,CAAE,oCANP,CAOXC,MAAM,CAAE,yBAPG,CAQXC,YAAY,CAAE,gCARH,CASXC,kBAAkB,CAAE,8BATT,CAUXC,gBAAgB,CAAE,oCAVP,CAWXC,cAAc,CAAE,kCAXL,CAYXC,eAAe,CAAE,mCAZN,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Selectors for the component library\n *\n * @module tool_componentlibrary/selectors\n * @package tool_componentlibrary\n * @copyright 2021 Bas Brands <bas@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nexport default {\n clipboardbutton: '.btn-clipboard',\n clipboardcontent: 'figure.highlight, div.highlight',\n searchinput: '[data-region=\"docsearch\"] input',\n searchsubmit: '[data-region=\"docsearch\"] .btn-submit',\n dropdownmenu: '[data-region=\"docsearch\"] .dropdown-menu',\n componentlibrary: '[data-region=\"componentlibrary\"]',\n jscode: '[data-action=\"runjs\"]',\n mustachecode: '[data-region=\"mustachecode\"]',\n mustacherawcontext: '[data-region=\"rawcontext\"]',\n mustacherendered: '[data-region=\"mustacherendered\"]',\n mustachesource: '[data-region=\"mustachesource\"]',\n mustachecontext: '[data-region=\"mustachecontext\"]',\n};\n"],"file":"selectors.min.js"}
|
45
admin/tool/componentlibrary/amd/src/clipboardwrapper.js
Normal file
45
admin/tool/componentlibrary/amd/src/clipboardwrapper.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
// 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/>.
|
||||
|
||||
/**
|
||||
* Interface to using clipboard.js
|
||||
*
|
||||
* @module tool_componentlibrary/clipboardwrapper
|
||||
* @package tool_componentlibrary
|
||||
* @copyright 2021 Bas Brands <bas@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
import 'core/copy_to_clipboard';
|
||||
import selectors from 'tool_componentlibrary/selectors';
|
||||
import Templates from 'core/templates';
|
||||
|
||||
let idCounter = 0;
|
||||
|
||||
/**
|
||||
* Initialise the clipboard button on all reusable code.
|
||||
*/
|
||||
export const clipboardWrapper = async() => {
|
||||
document.querySelectorAll(selectors.clipboardcontent).forEach(element => {
|
||||
if (!element.id) {
|
||||
element.id = `tool_componentlibrary_content-${idCounter++}`;
|
||||
}
|
||||
Templates.renderForPromise('tool_componentlibrary/clipboardbutton', {clipboardtarget: `#${element.id} code`})
|
||||
.then(({html, js}) => {
|
||||
Templates.prependNodeContents(element, html, js);
|
||||
return;
|
||||
})
|
||||
.catch();
|
||||
});
|
||||
};
|
38
admin/tool/componentlibrary/amd/src/jsrunner.js
Normal file
38
admin/tool/componentlibrary/amd/src/jsrunner.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
// 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 is called from to run any js code
|
||||
*
|
||||
* @module tool_componentlibrary/jsrunner
|
||||
* @package tool_componentlibrary
|
||||
* @copyright 2021 Bas Brands <bas@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
import selectors from 'tool_componentlibrary/selectors';
|
||||
|
||||
/**
|
||||
* The Hugo shortcodes changes the JavaScript in markdownfiles from
|
||||
* the Moodle mustache {{js}} code... {{/js}} syntax into a div with
|
||||
* attribute data-action='runjs'. See hugo/site/layouts/shortcodes/example.html.
|
||||
* This code fetches and runs the JavaScript content.
|
||||
*/
|
||||
export const jsRunner = () => {
|
||||
const compLib = document.querySelector(selectors.componentlibrary);
|
||||
compLib.querySelectorAll(selectors.jscode).forEach(runjs => {
|
||||
eval(runjs.innerHTML); // eslint-disable-line no-eval
|
||||
});
|
||||
};
|
40
admin/tool/componentlibrary/amd/src/loader.js
Normal file
40
admin/tool/componentlibrary/amd/src/loader.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
// 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 initialises the component library JS
|
||||
*
|
||||
* @module tool_componentlibrary/loader
|
||||
* @package tool_componentlibrary
|
||||
* @copyright 2021 Bas Brands <bas@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
import {mustache} from './mustache';
|
||||
import {jsRunner} from './jsrunner';
|
||||
import {clipboardWrapper} from './clipboardwrapper';
|
||||
import {search} from './search';
|
||||
|
||||
/**
|
||||
* Load all the component library JavaScript.
|
||||
*
|
||||
* @param {string} jsonFile Full path to the JSON file with the search DB.
|
||||
*/
|
||||
export const init = jsonFile => {
|
||||
mustache();
|
||||
jsRunner();
|
||||
clipboardWrapper();
|
||||
search(jsonFile);
|
||||
};
|
3482
admin/tool/componentlibrary/amd/src/lunr.js
Normal file
3482
admin/tool/componentlibrary/amd/src/lunr.js
Normal file
File diff suppressed because it is too large
Load diff
106
admin/tool/componentlibrary/amd/src/mustache.js
Normal file
106
admin/tool/componentlibrary/amd/src/mustache.js
Normal file
|
@ -0,0 +1,106 @@
|
|||
// 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 is called from to render mustache templates
|
||||
*
|
||||
* @module tool_componentlibrary/mustache
|
||||
* @package tool_componentlibrary
|
||||
* @copyright 2021 Bas Brands <bas@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
import selectors from 'tool_componentlibrary/selectors';
|
||||
import Ajax from 'core/ajax';
|
||||
import Config from 'core/config';
|
||||
import Templates from 'core/templates';
|
||||
import Log from 'core/log';
|
||||
import Notification from 'core/notification';
|
||||
|
||||
/**
|
||||
* Handle a template loaded response.
|
||||
*
|
||||
* @param {String} container The template container
|
||||
* @param {String} templateName The template name
|
||||
* @param {String} context Data for the template.
|
||||
*/
|
||||
const renderTemplate = async(container, templateName, context) => {
|
||||
try {
|
||||
context = JSON.parse(context);
|
||||
} catch (e) {
|
||||
Log.debug('Could not parse json example context for template.');
|
||||
Log.debug(e);
|
||||
}
|
||||
|
||||
const {html, js} = await Templates.renderForPromise(templateName, context);
|
||||
|
||||
const rendercontainer = container.querySelector(selectors.mustacherendered);
|
||||
|
||||
// Load the rendered content in the renderer tab.
|
||||
await Templates.replaceNodeContents(rendercontainer, html, js);
|
||||
};
|
||||
|
||||
/**
|
||||
* Load the a template source from Moodle.
|
||||
*
|
||||
* @param {String} container The template container
|
||||
*/
|
||||
const loadTemplate = container => {
|
||||
const sourcecontainer = container.querySelector(selectors.mustachesource);
|
||||
const contextcontainer = container.querySelector(selectors.mustachecontext);
|
||||
const templateName = container.dataset.template;
|
||||
let context = container.querySelector(selectors.mustacherawcontext).textContent;
|
||||
|
||||
const parts = templateName.split('/');
|
||||
const component = parts.shift();
|
||||
const name = parts.join('/');
|
||||
|
||||
const request = {
|
||||
methodname: 'core_output_load_template',
|
||||
args: {
|
||||
component: component,
|
||||
template: name,
|
||||
themename: Config.theme,
|
||||
includecomments: true
|
||||
}
|
||||
};
|
||||
|
||||
Ajax.call([request])[0]
|
||||
.done((source) => {
|
||||
// Load the source template in Template tab.
|
||||
sourcecontainer.textContent = source;
|
||||
if (!context) {
|
||||
const example = source.match(/Example context \(json\):([\s\S]+?)(}})/);
|
||||
context = example[1];
|
||||
// Load the variables in the Variables tab.
|
||||
const precontainer = document.createElement("pre");
|
||||
precontainer.innerHTML = JSON.stringify(JSON.parse(context), null, 4);
|
||||
contextcontainer.parentNode.appendChild(precontainer);
|
||||
contextcontainer.classList.add('d-none');
|
||||
}
|
||||
renderTemplate(container, templateName, context);
|
||||
})
|
||||
.fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize module
|
||||
*
|
||||
*/
|
||||
export const mustache = () => {
|
||||
document.querySelectorAll(selectors.mustachecode).forEach((container) => {
|
||||
loadTemplate(container);
|
||||
});
|
||||
};
|
154
admin/tool/componentlibrary/amd/src/search.js
Normal file
154
admin/tool/componentlibrary/amd/src/search.js
Normal file
|
@ -0,0 +1,154 @@
|
|||
// 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/>.
|
||||
|
||||
/**
|
||||
* Interface to the Lunr search engines.
|
||||
*
|
||||
* @module tool_componentlibrary/search
|
||||
* @package tool_componentlibrary
|
||||
* @copyright 2021 Bas Brands <bas@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
import lunrJs from 'tool_componentlibrary/lunr';
|
||||
import selectors from 'tool_componentlibrary/selectors';
|
||||
import Log from 'core/log';
|
||||
import Notification from 'core/notification';
|
||||
import {enter, escape} from 'core/key_codes';
|
||||
|
||||
let lunrIndex = null;
|
||||
let pagesIndex = null;
|
||||
|
||||
/**
|
||||
* Get the jsonFile that is generated when the component library is build.
|
||||
*
|
||||
* @param {String} jsonFile the URL to the json file.
|
||||
* @retrun {Object}
|
||||
*/
|
||||
const fetchJson = async(jsonFile) => {
|
||||
const response = await fetch(jsonFile);
|
||||
|
||||
if (!response.ok) {
|
||||
Log.debug(`Error getting Hugo index file: ${response.status}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
};
|
||||
|
||||
/**
|
||||
* Initiate lunr on the data in the jsonFile and add the jsondata to the pagesIndex
|
||||
*
|
||||
* @param {String} jsonFile the URL to the json file.
|
||||
*/
|
||||
const initLunr = jsonFile => {
|
||||
fetchJson(jsonFile).then(jsondata => {
|
||||
pagesIndex = jsondata;
|
||||
// Using an arrow function here will break lunr on compile.
|
||||
lunrIndex = lunrJs(function() {
|
||||
this.ref('uri');
|
||||
this.field('title', {boost: 10});
|
||||
this.field('content');
|
||||
this.field('tags', {boost: 5});
|
||||
jsondata.forEach(p => {
|
||||
this.add(p);
|
||||
});
|
||||
});
|
||||
return null;
|
||||
}).catch(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Setup the eventlistener to listen on user input on the search field.
|
||||
*/
|
||||
const initUI = () => {
|
||||
const searchInput = document.querySelector(selectors.searchinput);
|
||||
searchInput.addEventListener('keyup', e => {
|
||||
const query = e.currentTarget.value;
|
||||
if (query.length < 2) {
|
||||
document.querySelector(selectors.dropdownmenu).classList.remove('show');
|
||||
return;
|
||||
}
|
||||
renderResults(searchIndex(query));
|
||||
});
|
||||
searchInput.addEventListener('keydown', e => {
|
||||
if (e.keyCode === enter) {
|
||||
e.preventDefault();
|
||||
}
|
||||
if (e.keyCode === escape) {
|
||||
searchInput.value = '';
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Trigger a search in lunr and transform the result.
|
||||
*
|
||||
* @param {String} query
|
||||
* @return {Array} results
|
||||
*/
|
||||
const searchIndex = query => {
|
||||
// Find the item in our index corresponding to the lunr one to have more info
|
||||
// Lunr result:
|
||||
// {ref: "/section/page1", score: 0.2725657778206127}
|
||||
// Our result:
|
||||
// {title:"Page1", href:"/section/page1", ...}
|
||||
|
||||
return lunrIndex.search(query + ' ' + query + '*').map(result => {
|
||||
return pagesIndex.filter(page => {
|
||||
return page.uri === result.ref;
|
||||
})[0];
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Display the 10 first results
|
||||
*
|
||||
* @param {Array} results to display
|
||||
*/
|
||||
const renderResults = results => {
|
||||
const dropdownMenu = document.querySelector(selectors.dropdownmenu);
|
||||
if (!results.length) {
|
||||
dropdownMenu.classList.remove('show');
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear out the results.
|
||||
dropdownMenu.innerHTML = '';
|
||||
|
||||
const baseUrl = M.cfg.wwwroot + '/admin/tool/componentlibrary/docspage.php';
|
||||
|
||||
// Only show the ten first results
|
||||
results.slice(0, 10).forEach(function(result) {
|
||||
const link = document.createElement("a");
|
||||
const chapter = result.uri.split('/')[1];
|
||||
link.appendChild(document.createTextNode(`${chapter} > ${result.title}`));
|
||||
link.classList.add('dropdown-item');
|
||||
link.href = baseUrl + result.uri;
|
||||
|
||||
dropdownMenu.appendChild(link);
|
||||
});
|
||||
|
||||
dropdownMenu.classList.add('show');
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize module.
|
||||
*
|
||||
* @param {String} jsonFile Full path to the search DB json file.
|
||||
*/
|
||||
export const search = jsonFile => {
|
||||
initLunr(jsonFile);
|
||||
initUI();
|
||||
};
|
38
admin/tool/componentlibrary/amd/src/selectors.js
Normal file
38
admin/tool/componentlibrary/amd/src/selectors.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
// 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/>.
|
||||
|
||||
/**
|
||||
* Selectors for the component library
|
||||
*
|
||||
* @module tool_componentlibrary/selectors
|
||||
* @package tool_componentlibrary
|
||||
* @copyright 2021 Bas Brands <bas@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
export default {
|
||||
clipboardbutton: '.btn-clipboard',
|
||||
clipboardcontent: 'figure.highlight, div.highlight',
|
||||
searchinput: '[data-region="docsearch"] input',
|
||||
searchsubmit: '[data-region="docsearch"] .btn-submit',
|
||||
dropdownmenu: '[data-region="docsearch"] .dropdown-menu',
|
||||
componentlibrary: '[data-region="componentlibrary"]',
|
||||
jscode: '[data-action="runjs"]',
|
||||
mustachecode: '[data-region="mustachecode"]',
|
||||
mustacherawcontext: '[data-region="rawcontext"]',
|
||||
mustacherendered: '[data-region="mustacherendered"]',
|
||||
mustachesource: '[data-region="mustachesource"]',
|
||||
mustachecontext: '[data-region="mustachecontext"]',
|
||||
};
|
302
admin/tool/componentlibrary/classes/exampleform.php
Normal file
302
admin/tool/componentlibrary/classes/exampleform.php
Normal file
|
@ -0,0 +1,302 @@
|
|||
<?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/>.
|
||||
|
||||
/**
|
||||
* Example form to showcase the rendering of form fields.
|
||||
*
|
||||
* @package tool_componentlibrary
|
||||
* @copyright 2021 Bas Brands <bas@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_componentlibrary;
|
||||
|
||||
/**
|
||||
* Example form to showcase the rendering of form fields.
|
||||
*
|
||||
* @copyright 2021 Bas Brands <bas@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class exampleform extends \moodleform {
|
||||
/**
|
||||
* Elements of the test form.
|
||||
*/
|
||||
public function definition() {
|
||||
$mform = $this->_form;
|
||||
|
||||
$required = optional_param('required', false, PARAM_BOOL);
|
||||
$help = optional_param('help', false, PARAM_BOOL);
|
||||
$mixed = optional_param('mixed', false, PARAM_BOOL);
|
||||
|
||||
// Text.
|
||||
$mform->addElement('text', 'textelement', 'Text');
|
||||
$mform->setType('textelement', 'text');
|
||||
if ($required) {
|
||||
$mform->addRule('textelement', null, 'required', null, 'client');
|
||||
}
|
||||
if ($help && !$mixed) {
|
||||
$mform->addHelpButton('textelement', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('textelement', true);
|
||||
|
||||
// Text with a long label.
|
||||
$mform->addElement('text', 'textelementtwo', 'Text element with a long label that can span multiple lines.
|
||||
The next field has no label. ');
|
||||
$mform->setType('textelementtwo', 'text');
|
||||
if ($required) {
|
||||
$mform->addRule('textelementtwo', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help) {
|
||||
$mform->addHelpButton('textelementtwo', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('textelementtwo', true);
|
||||
|
||||
// Text without label.
|
||||
$mform->addElement('text', 'textelementhree', '', '');
|
||||
$mform->setType('textelementhree', 'text');
|
||||
if ($required && !$mixed) {
|
||||
$mform->addRule('textelementhree', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help && !$mixed) {
|
||||
$mform->addHelpButton('textelementhree', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('textelementhree', true);
|
||||
|
||||
// Button.
|
||||
$mform->addElement('button', 'buttonelement', 'Button');
|
||||
if ($required) {
|
||||
$mform->addRule('buttonelement', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help) {
|
||||
$mform->addHelpButton('buttonelement', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('buttonelement', true);
|
||||
|
||||
// Date.
|
||||
$mform->addElement('date_selector', 'date', 'Date selector');
|
||||
if ($required && !$mixed) {
|
||||
$mform->addRule('date', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help) {
|
||||
$mform->addHelpButton('date', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('date', true);
|
||||
|
||||
// Date time.
|
||||
$mform->addElement('date_time_selector', 'datetimesel', 'Date time selector');
|
||||
if ($required) {
|
||||
$mform->addRule('datetimesel', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help && !$mixed) {
|
||||
$mform->addHelpButton('datetimesel', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('datetimesel', true);
|
||||
|
||||
// Duration (does not support required form fields).
|
||||
$mform->addElement('duration', 'duration', 'Duration');
|
||||
if ($help) {
|
||||
$mform->addHelpButton('duration', 'summary');
|
||||
}
|
||||
|
||||
// Editor.
|
||||
$mform->addElement('editor', 'editor', 'Editor');
|
||||
$mform->setType('editor', PARAM_RAW);
|
||||
if ($required) {
|
||||
$mform->addRule('editor', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help && !$mixed) {
|
||||
$mform->addHelpButton('editor', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('editor', true);
|
||||
|
||||
// Filepicker.
|
||||
$mform->addElement('filepicker', 'userfile', 'Filepicker', null, ['maxbytes' => 100, 'accepted_types' => '*']);
|
||||
if ($required) {
|
||||
$mform->addRule('userfile', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help) {
|
||||
$mform->addHelpButton('userfile', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('userfile', true);
|
||||
|
||||
// Html.
|
||||
$mform->addElement('html', '<div class="text-success h2 ">The HTML only formfield</div>');
|
||||
|
||||
// Passwords.
|
||||
$mform->addElement('passwordunmask', 'passwordunmask', 'Passwordunmask');
|
||||
if ($required && !$mixed) {
|
||||
$mform->addRule('passwordunmask', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help && !$mixed) {
|
||||
$mform->addHelpButton('passwordunmask', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('passwordunmask', true);
|
||||
|
||||
// Radio.
|
||||
$mform->addElement('radio', 'radio', 'Radio', 'Radio label', 'choice_value');
|
||||
if ($required) {
|
||||
$mform->addRule('radio', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help && !$mixed) {
|
||||
$mform->addHelpButton('radio', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('radio', true);
|
||||
|
||||
// Checkbox.
|
||||
$mform->addElement('checkbox', 'checkbox', 'Checkbox', 'Checkbox Text');
|
||||
if ($required) {
|
||||
$mform->addRule('checkbox', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help) {
|
||||
$mform->addHelpButton('checkbox', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('checkbox', true);
|
||||
|
||||
// Select.
|
||||
$mform->addElement('select', 'auth', 'Select', ['cow', 'crow', 'dog', 'cat']);
|
||||
if ($required && !$mixed) {
|
||||
$mform->addRule('auth', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help) {
|
||||
$mform->addHelpButton('auth', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('auth', true);
|
||||
|
||||
// Yes No.
|
||||
$mform->addElement('selectyesno', 'selectyesno', 'Selectyesno');
|
||||
if ($required && !$mixed) {
|
||||
$mform->addRule('selectyesno', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help) {
|
||||
$mform->addHelpButton('selectyesno', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('selectyesno', true);
|
||||
|
||||
// Static.
|
||||
$mform->addElement('static', 'static', 'Static', 'static description');
|
||||
|
||||
// Float.
|
||||
$mform->addElement('float', 'float', 'Floating number');
|
||||
if ($required) {
|
||||
$mform->addRule('float', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help) {
|
||||
$mform->addHelpButton('float', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('float', true);
|
||||
|
||||
// Textarea.
|
||||
$mform->addElement('textarea', 'textarea', 'Text area', 'wrap="virtual" rows="20" cols="50"');
|
||||
if ($required && !$mixed) {
|
||||
$mform->addRule('textarea', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help && !$mixed) {
|
||||
$mform->addHelpButton('textarea', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('textarea', true);
|
||||
|
||||
// Recaptcha. (does not support required).
|
||||
$mform->addElement('recaptcha', 'recaptcha', 'Recaptcha');
|
||||
if ($help) {
|
||||
$mform->addHelpButton('recaptcha', 'summary');
|
||||
}
|
||||
|
||||
// Tags.
|
||||
$mform->addElement('tags', 'tags', 'Tags', ['itemtype' => 'course_modules', 'component' => 'core']);
|
||||
if ($required && !$mixed) {
|
||||
$mform->addRule('tags', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help && !$mixed) {
|
||||
$mform->addHelpButton('tags', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('tags', true);
|
||||
|
||||
// Filetypes. (does not support required).
|
||||
$mform->addElement('filetypes', 'filetypes', 'Allowedfiletypes', ['onlytypes' => ['document', 'image'],
|
||||
'allowunknown' => true]);
|
||||
if ($help) {
|
||||
$mform->addHelpButton('filetypes', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('filetypes', true);
|
||||
|
||||
// Advanced checkbox.
|
||||
$mform->addElement('advcheckbox', 'advcheckbox', 'Advanced checkbox', 'Advanced checkbox name', ['group' => 1],
|
||||
[0, 1]);
|
||||
if ($required) {
|
||||
$mform->addRule('advcheckbox', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help) {
|
||||
$mform->addHelpButton('advcheckbox', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('advcheckbox', true);
|
||||
|
||||
// Autocomplete.
|
||||
$searchareas = \core_search\manager::get_search_areas_list(true);
|
||||
$areanames = [];
|
||||
foreach ($searchareas as $areaid => $searcharea) {
|
||||
$areanames[$areaid] = $searcharea->get_visible_name();
|
||||
}
|
||||
$options = [
|
||||
'multiple' => true,
|
||||
'noselectionstring' => get_string('allareas', 'search'),
|
||||
];
|
||||
$mform->addElement('autocomplete', 'autocomplete', get_string('searcharea', 'search'), $areanames, $options);
|
||||
if ($required) {
|
||||
$mform->addRule('autocomplete', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help && !$mixed) {
|
||||
$mform->addHelpButton('autocomplete', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('autocomplete', true);
|
||||
|
||||
// Group.
|
||||
$radiogrp = [
|
||||
$mform->createElement('text', 'rtext', 'Text'),
|
||||
$mform->createElement('radio', 'rradio', 'Radio label', 'After one ', 1),
|
||||
$mform->createElement('checkbox', 'rchecbox', 'Checkbox label', 'After two ', 2)
|
||||
];
|
||||
$mform->setType('rtext', PARAM_RAW);
|
||||
$mform->addGroup($radiogrp, 'group', 'Group', ' ', false);
|
||||
if ($required) {
|
||||
$mform->addRule('group', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help) {
|
||||
$mform->addHelpButton('group', 'summary');
|
||||
}
|
||||
$mform->setAdvanced('group', true);
|
||||
|
||||
$group = $mform->getElement('group');
|
||||
|
||||
// Group of groups.
|
||||
$group = [];
|
||||
$group[] = $mform->createElement('select', 'profilefield', '', [0 => 'Username', 1 => 'Email']);
|
||||
$elements = [];
|
||||
$elements[] = $mform->createElement('select', 'operator', null, [0 => 'equal', 1 => 'not equal']);
|
||||
$elements[] = $mform->createElement('text', 'value', null);
|
||||
$elements[] = $mform->createElement('static', 'desc', 'Just a static text', 'Just a static text');
|
||||
$mform->setType('value', PARAM_RAW);
|
||||
$group[] = $mform->createElement('group', 'fieldvalue', '', $elements, '', false);
|
||||
$mform->addGroup($group, 'fieldsgroup', 'Group containing another group', '', false);
|
||||
if ($required) {
|
||||
$mform->addRule('fieldsgroup', 'This element is required', 'required', null, 'client');
|
||||
}
|
||||
if ($help) {
|
||||
$mform->addHelpButton('fieldsgroup', 'summary');
|
||||
}
|
||||
|
||||
$this->add_action_buttons();
|
||||
}
|
||||
}
|
36
admin/tool/componentlibrary/classes/privacy/provider.php
Normal file
36
admin/tool/componentlibrary/classes/privacy/provider.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?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/>.
|
||||
|
||||
namespace tool_componentlibrary\privacy;
|
||||
|
||||
/**
|
||||
* Privacy Subsystem for tool_componentlibrary implementing null_provider.
|
||||
*
|
||||
* @package tool_componentlibrary
|
||||
* @copyright 2021 Bas Brands <bas@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider {
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
85
admin/tool/componentlibrary/cli/fetchicons.php
Normal file
85
admin/tool/componentlibrary/cli/fetchicons.php
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?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/>.
|
||||
|
||||
/**
|
||||
* Moodle Component Library
|
||||
*
|
||||
* @package tool_componentlibrary
|
||||
* @copyright 2021 Bas Brands <bas@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
define('CLI_SCRIPT', 1);
|
||||
|
||||
require_once(__DIR__ . '/../../../../config.php');
|
||||
require_once($CFG->libdir.'/clilib.php');
|
||||
require_once($CFG->dirroot . '/lib/filelib.php');
|
||||
|
||||
list($options, $unrecognized) = cli_get_params(array(
|
||||
'help' => false,
|
||||
), array('h' => 'help'));
|
||||
|
||||
if ($options['help']) {
|
||||
$help = <<<EOL
|
||||
Generate a json file with all core icons for the component library.
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help.
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/tool/componentlibrary/cli/fetchicons.php\n
|
||||
EOL;
|
||||
echo $help;
|
||||
die;
|
||||
}
|
||||
|
||||
$admin = get_admin();
|
||||
if (!$admin) {
|
||||
mtrace("Error: No admin account was found");
|
||||
die;
|
||||
}
|
||||
|
||||
$CFG->themedesignermode = true;
|
||||
|
||||
$output = $PAGE->get_renderer('core');
|
||||
$isfontawesome = \core\output\icon_system::instance(\core\output\icon_system::FONTAWESOME);
|
||||
$isstandard = \core\output\icon_system::instance(\core\output\icon_system::STANDARD);
|
||||
$map = $isfontawesome->get_icon_name_map();
|
||||
$icons = [];
|
||||
foreach ($map as $name => $icon) {
|
||||
$parts = explode(':', $name);
|
||||
if ($parts[0] === 'theme') {
|
||||
continue;
|
||||
}
|
||||
$imageicon = new image_icon($parts[1], $name, $parts[0], []);
|
||||
$i = new \stdClass();
|
||||
$i->name = $name;
|
||||
$i->icon = $icon;
|
||||
if ($imageicon) {
|
||||
$i->standardicon = str_replace($CFG->wwwroot, 'MOODLESITE', $isstandard->render_pix_icon($output, $imageicon));
|
||||
}
|
||||
$icons[] = $i;
|
||||
}
|
||||
$jsonfile = $CFG->dirroot . '/admin/tool/componentlibrary/hugo/site/data/fontawesomeicons.json';
|
||||
if (($fh = @fopen($jsonfile, 'w')) !== false) {
|
||||
fwrite($fh, json_encode($icons));
|
||||
fclose($fh);
|
||||
exit(0);
|
||||
} else {
|
||||
echo 'Could not write to ' . $jsonfile;
|
||||
exit(1);
|
||||
}
|
73
admin/tool/componentlibrary/config.yml
Normal file
73
admin/tool/componentlibrary/config.yml
Normal file
|
@ -0,0 +1,73 @@
|
|||
languageCode: "en"
|
||||
title: "Moodle Component Library"
|
||||
baseURL: "http://MOODLEROOT/"
|
||||
enableInlineShortcodes: true
|
||||
pygmentsUseClasses: true
|
||||
|
||||
markup:
|
||||
goldmark:
|
||||
renderer:
|
||||
unsafe: true
|
||||
|
||||
markup:
|
||||
goldmark:
|
||||
extensions:
|
||||
definitionList: true
|
||||
footnote: true
|
||||
linkify: true
|
||||
strikethrough: true
|
||||
table: true
|
||||
taskList: true
|
||||
typographer: true
|
||||
parser:
|
||||
attribute: true
|
||||
autoHeadingID: true
|
||||
autoHeadingIDType: github
|
||||
renderer:
|
||||
hardWraps: false
|
||||
unsafe: true
|
||||
xHTML: false
|
||||
highlight:
|
||||
codeFences: true
|
||||
guessSyntax: true
|
||||
hl_Lines: ""
|
||||
lineNoStart: 1
|
||||
lineNos: false
|
||||
lineNumbersInTable: true
|
||||
noClasses: true
|
||||
style: monokailight
|
||||
tabWidth: 4
|
||||
|
||||
buildDrafts: false
|
||||
buildFuture: true
|
||||
|
||||
enableRobotsTXT: true
|
||||
metaDataFormat: "yaml"
|
||||
|
||||
disableKinds: ["404", "taxonomy", "taxonomyTerm", "RSS"]
|
||||
|
||||
blackfriday:
|
||||
fractions: false
|
||||
|
||||
relativeURLs: true
|
||||
|
||||
publishDir: "./admin/tool/componentlibrary/docs"
|
||||
archetypeDir: "./admin/tool/componentlibrary/hugo/archetypes"
|
||||
assetDir: "./admin/tool/componentlibrary/hugo/assets"
|
||||
contentDir: "./admin/tool/componentlibrary/content"
|
||||
dataDir: "./admin/tool/componentlibrary/hugo/site/data"
|
||||
layoutDir: "./admin/tool/componentlibrary/hugo/site/layouts"
|
||||
staticDir: "./admin/tool/componentlibrary/content/static"
|
||||
|
||||
params:
|
||||
moodleroot: "MOODLEROOT"
|
||||
|
||||
current_version: "4.6.0"
|
||||
current_ruby_version: "4.6.0"
|
||||
docs_version: "4.6"
|
||||
boostrap_docs: "https://getbootstrap.com/docs/4.6"
|
||||
repo: "https://github.com/twbs/bootstrap"
|
||||
|
||||
cdn:
|
||||
# See https://www.srihash.org for info on how to generate the hashes
|
||||
popper: "https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
|
13
admin/tool/componentlibrary/content/404.md
Normal file
13
admin/tool/componentlibrary/content/404.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
title: "404 - File not found"
|
||||
layout: 404
|
||||
description: ""
|
||||
url: /404.html
|
||||
robots: noindex,follow
|
||||
sitemap_exclude: true
|
||||
---
|
||||
|
||||
<div class="text-center py-5">
|
||||
<h1 class="display-1">404</h1>
|
||||
<h2>File not found</h2>
|
||||
</div>
|
6
admin/tool/componentlibrary/content/library/_index.md
Normal file
6
admin/tool/componentlibrary/content/library/_index.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: "Component library"
|
||||
date: 2017-10-17T15:26:15Z
|
||||
draft: false
|
||||
weight: 20
|
||||
---
|
53
admin/tool/componentlibrary/content/library/adding-images.md
Normal file
53
admin/tool/componentlibrary/content/library/adding-images.md
Normal file
|
@ -0,0 +1,53 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Adding images"
|
||||
date: 2020-02-04T09:40:32+01:00
|
||||
draft: false
|
||||
weight: 2
|
||||
---
|
||||
|
||||
## Images
|
||||
|
||||
Images that need to be show in the component library should be placed in a separate folder for each new page.
|
||||
|
||||
The Markdown file for this page is located here:
|
||||
|
||||
```
|
||||
└── content
|
||||
└── moodle
|
||||
└── getting-started
|
||||
└── adding-images.md
|
||||
```
|
||||
|
||||
To access images for this page create a new folder here.
|
||||
|
||||
```
|
||||
└── static
|
||||
└── moodle
|
||||
└── getting-started
|
||||
└── adding-images
|
||||
```
|
||||
|
||||
Place your images in this new folder:
|
||||
|
||||
```
|
||||
└── static
|
||||
└── moodle
|
||||
└── getting-started
|
||||
└── adding-images
|
||||
├── wildebeest-1200.jpg
|
||||
├── kitten1.png
|
||||
└── kitten2.png
|
||||
```
|
||||
|
||||
To use images use this syntax:
|
||||
|
||||
Syntax for markdown (.md) files:
|
||||
|
||||
```
|
||||
{{</* image "wildebeest-1200.jpg" "Image of a Wildebeest" */>}}
|
||||
```
|
||||
|
||||
Rendered result on this page:
|
||||
|
||||
{{< image "wildebeest-1200.jpg" "Image of a Wildebeest">}}
|
68
admin/tool/componentlibrary/content/library/adding-pages.md
Normal file
68
admin/tool/componentlibrary/content/library/adding-pages.md
Normal file
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Adding pages"
|
||||
date: 2020-03-02T10:13:29+01:00
|
||||
draft: false
|
||||
weight: 2
|
||||
---
|
||||
|
||||
## Adding or editing a page in the component library
|
||||
|
||||
In this step-by-step guide you will create a new page called Breadcrumb navigation and compile it from a markdown text file to a HTML page in the component library.
|
||||
|
||||
To add a page to the component library on your local machine navigate open your editor or file manager and create a new markdown text file in folder /content/moodle/components/breadcrumbs.md
|
||||
|
||||
|
||||
```
|
||||
└── content
|
||||
└── moodle
|
||||
└── components
|
||||
└── breadcrumbs.md
|
||||
```
|
||||
|
||||
Open the file in your favourite editor and start it with some metadata, we call this syntax [frontmatter](https://gohugo.io/content-management/front-matter/).
|
||||
|
||||
```
|
||||
---
|
||||
layout: docs
|
||||
title: "Breadcrumb navigation"
|
||||
date: 2020-03-02T10:13:29+01:00
|
||||
draft: false
|
||||
---
|
||||
```
|
||||
|
||||
Make sure you add these characters `---` before and after your metadata. You can change the title and date to match your document.
|
||||
|
||||
## Run the component library Grunt task.
|
||||
|
||||
In your terminal run the command `npm install` and then `grunt componentlibrary` in your Moodle root folder. This will install all required resources and compile the componentlibrary pages. If you do not have npm installed on your system please visit [npmjs.com](https://www.npmjs.com/get-npm) to learn how to get a working setup.
|
||||
|
||||
|
||||
The output should be similar to this:
|
||||
|
||||
```
|
||||
Running "componentlibrary:docsBuild" task
|
||||
Building sites …
|
||||
| EN
|
||||
+------------------+-----+
|
||||
Pages | 113
|
||||
Paginator pages | 0
|
||||
Non-page files | 18
|
||||
Static files | 18
|
||||
Processed images | 0
|
||||
Aliases | 7
|
||||
Sitemaps | 1
|
||||
Cleaned | 0
|
||||
|
||||
Total in 913 ms
|
||||
Running "componentlibrary:cssBuild" task
|
||||
Rendering Complete, saving .css file...
|
||||
Wrote CSS to /var/www/repositories/cl_master/moodle/admin/tool/componentlibrary/hugo/dist/css/docs.css
|
||||
Wrote Source Map to /var/www/repositories/cl_master/moodle/admin/tool/componentlibrary/hugo/dist/css/docs.css.map
|
||||
Running "componentlibrary:indexBuild" task
|
||||
|
||||
Done.
|
||||
|
||||
```
|
||||
|
||||
The grunt watch task will pick up changes in the componentlibrary Markdown files and Scss files. So run `grunt watch` if you want to edit the pages.
|
|
@ -0,0 +1,65 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Component Library Backend"
|
||||
date: 2021-05-27T15:43:07+01:00
|
||||
group: moodle-components
|
||||
draft: false
|
||||
---
|
||||
|
||||
## Creating new Pages
|
||||
|
||||
Pages for the component library are written in [Markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) and a number of [Hugo](https://gohugo.io) powered tools.
|
||||
|
||||
To add a page simply create a Markdown file in content/moodle/[foldername]/
|
||||
|
||||
## Generating the HTML versions of the Markdown files
|
||||
|
||||
The HTML pages for this library are created in the docs/ folder of the componentlibrary
|
||||
|
||||
Please run `npm install` in the $moodleroot folder to fetch all requirements for contributing to this library.
|
||||
|
||||
Once all requirements are installed you all you need to do is run `grunt componentlibrary` to create the component library pages.
|
||||
|
||||
## Location of Markdown files
|
||||
|
||||
```
|
||||
└── content
|
||||
├─ bootstrap
|
||||
└─ moodle
|
||||
```
|
||||
|
||||
## HTML output folder
|
||||
|
||||
```
|
||||
├── docs
|
||||
```
|
||||
|
||||
## Page setup using the Hugo static site builder
|
||||
|
||||
The hugo config file can be found in /admin/tool/componentlibrary/config.yml
|
||||
|
||||
The HTML and CSS for the component library pages are found here:
|
||||
|
||||
```
|
||||
└─── hugo
|
||||
├── archetypes
|
||||
├── dist
|
||||
├── scss
|
||||
└─- site
|
||||
```
|
||||
|
||||
`archetypes` are template markdown files used when creating a new hugo page.
|
||||
|
||||
`dist` CSS and JavaScript for use in Hugo pages
|
||||
|
||||
`scss` The SCSS used to generate the docs css for the Component Library.
|
||||
|
||||
`site` The page templates for hugo that include the left hand menu, navbar etc. And the templates to render example code shown in this component library.
|
||||
|
||||
|
||||
## Creating a new docs page
|
||||
|
||||
Find the example page in `/admin/tool/componentlibrary/content/moodle/components/example.md` and use it as a template for your new
|
||||
page. In the top part of the example.md file you will find the `frontmatter` configuration between the `---` characters. This part is used when hugo generates the page name and description. Change it to describe the new page you are creating.
|
||||
|
||||
The document setup is not fixed at all, the example page is just there for inspiration when starting to describe a Moodle component.
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Getting started"
|
||||
date: 2020-01-28T10:13:29+01:00
|
||||
group: library
|
||||
draft: false
|
||||
weight: 1
|
||||
---
|
||||
<style>
|
||||
.bd-title {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<div class="d-flex">
|
||||
<div class="w-50 ml-auto mr-auto">
|
||||
{{< image "logo.png" "The Moodle logo">}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## The Moodle UI Component library
|
||||
|
||||
The Moodle UI component library is the central location for documenting frequently used User Interface components used in Moodle. Moodle UI components are used to represent distinct UI elements, such as tables, buttons, dialogs, and others.
|
||||
The main purpose of this library is to provide documentation for designers and developers when doing frontend development of new features.
|
||||
|
||||
This library allows you to create user interfaces more efficiently, it is a tool for visual designers, front-end developers, ux developers and anybody creating core Moodle code or Moodle extensions.
|
||||
|
||||
Whenever a new Moodle feature is created or updated the building blocks for the UI of the feature should be documented in this library.
|
||||
|
||||
## Bootstrap docs
|
||||
|
||||
A large part of this library contains information about [Bootstrap](http://getbootstrap.com) components which are shipped with every Moodle installation. Bootstrap contains a lot of useful components and utilities which can safely be used for frontend development. For example, instead of adding custom CSS to add some padding in a box you should really look at the [spacing](/moodle-3.9/utilities/spacing) utilities from Bootstrap instead.
|
||||
|
||||
## Build with Hugo
|
||||
|
||||
This page and all other pages in the Component library are build using [Hugo](http://gohugo.io), a static site generator that can turn documentation written in Markdown into nice pages like the one you are looking at right now.
|
|
@ -0,0 +1,44 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Moodle JavaScript"
|
||||
date: 2020-01-14T13:38:37+01:00
|
||||
group: moodle-components
|
||||
draft: false
|
||||
menu: "main"
|
||||
---
|
||||
|
||||
## Running AMD modules
|
||||
|
||||
When using this (shortcode) syntax you can showcase your HTML and add some RequireJS style Javascript that will call core AMD modules.
|
||||
|
||||
In order for this to work you need to use the JavaScript syntax used in core Mustache templates. See the ```{{js}}``` tags in this example below:
|
||||
|
||||
{{< example >}}
|
||||
<div id="toasttest" role="alert" aria-live="assertive" aria-atomic="true" class="toast" data-autohide="false">
|
||||
<div class="toast-header">
|
||||
<img src="http://placekitten.com/50/50" class="rounded mr-2" alt="PlaceKitten">
|
||||
<strong class="mr-auto">Bootstrap</strong>
|
||||
<small>11 mins ago</small>
|
||||
<button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="toast-body">
|
||||
Hello, world! This is a toast message.
|
||||
</div>
|
||||
</div>
|
||||
{{#js}}
|
||||
require(
|
||||
[
|
||||
'jquery',
|
||||
'theme_boost/toast',
|
||||
],
|
||||
function(
|
||||
$,
|
||||
Toast
|
||||
) {
|
||||
var root = $('#toasttest');
|
||||
root.toast('show');
|
||||
});
|
||||
{{/js}}
|
||||
{{< /example >}}
|
|
@ -0,0 +1,54 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Moodle templates"
|
||||
date: 2020-01-14T13:38:37+01:00
|
||||
group: moodle-components
|
||||
draft: false
|
||||
menu: "main"
|
||||
---
|
||||
|
||||
## Moodle templates
|
||||
|
||||
[Moodle templates](https://docs.moodle.org/dev/Templates) are use to write HTML and Javascript using mustache files.
|
||||
|
||||
If you are creating your own pages in the UI Component library you can load core templates using this (shortcode) syntax:
|
||||
|
||||
```
|
||||
{{</* mustache template="core/notification_error" */>}}
|
||||
{{</* /mustache */>}}
|
||||
```
|
||||
|
||||
This is the result of adding the core/notification template on this page:
|
||||
|
||||
{{< mustache template="core/notification_error" >}}
|
||||
{{< /mustache >}}
|
||||
|
||||
This allows you to document any mustache template in the component library.
|
||||
|
||||
## Moodle templates with custom data
|
||||
|
||||
Not all templates found in Moodle core are will documented with example JSON formatted data (see the variables tab for the notification_error). To use custom Json data please use this (shortcode) syntax:
|
||||
|
||||
```
|
||||
{{</* mustache template="core/notification_error" */>}}
|
||||
{
|
||||
"message": "Your pants are awesome!",
|
||||
"closebutton": 1,
|
||||
"announce": 1,
|
||||
"extraclasses": "foo bar"
|
||||
}
|
||||
{{</* /mustache */>}}
|
||||
```
|
||||
|
||||
|
||||
This is the result of adding the core/notification template on this page:
|
||||
|
||||
{{< mustache template="core/notification_error" >}}
|
||||
{
|
||||
"message": "Your pants are awesome!",
|
||||
"closebutton": 1,
|
||||
"announce": 1,
|
||||
"extraclasses": "foo bar"
|
||||
}
|
||||
{{< /mustache >}}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Syntax highlighting"
|
||||
description: Use Hugo shortcodes for Syntax highlighting.
|
||||
date: 2020-02-04T09:40:32+01:00
|
||||
draft: false
|
||||
weight: 3
|
||||
---
|
||||
|
||||
## Using Shortcodes for syntax
|
||||
|
||||
Using this (shortcode) syntax you can higlight programming syntax in the component library
|
||||
|
||||
## HTML highlighting
|
||||
|
||||
Syntax for markdown (.md) files:
|
||||
|
||||
```
|
||||
{{</* highlight html */>}}
|
||||
<div class="myclass">
|
||||
This is an example.
|
||||
</div>
|
||||
{{</* /highlight */>}}
|
||||
```
|
||||
Rendered result on this page:
|
||||
|
||||
{{< highlight html >}}
|
||||
<div class="myclass">
|
||||
This is an example.
|
||||
</div>
|
||||
{{< /highlight >}}
|
||||
|
||||
## PHP shortcode
|
||||
|
||||
Syntax for markdown (.md) files:
|
||||
|
||||
```
|
||||
{{</* php */>}}
|
||||
$mform->addElement('passwordunmask', 'password', get_string('label'), $attributes);
|
||||
{{</* /php */>}}
|
||||
```
|
||||
Rendered result on this page:
|
||||
|
||||
{{< php >}}
|
||||
$mform->addElement('passwordunmask', 'password', get_string('label'), $attributes);
|
||||
{{< /php >}}
|
||||
|
||||
## Highlight shortcode
|
||||
|
||||
Syntax for markdown (.md) files:
|
||||
|
||||
```
|
||||
{{</* highlight js */>}}
|
||||
var config = {
|
||||
test: null,
|
||||
selector: '[data-drag-type=move]'
|
||||
};
|
||||
{{</* /highlight */>}}
|
||||
```
|
||||
Rendered result on this page:
|
||||
|
||||
{{< highlight js >}}
|
||||
var config = {
|
||||
test: null,
|
||||
selector: '[data-drag-type=move]'
|
||||
};
|
||||
{{< /highlight >}}
|
||||
|
||||
|
||||
## Example shortcode
|
||||
|
||||
The example shortcode shows the HTML source with syntax highlighting and renders it on the page. This shortcode takes the following arguments:
|
||||
|
||||
show_markup="true/false"
|
||||
show_preview="true/false"
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
{{</* example */>}}
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" placeholder="Search">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-primary" type="button">
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{#js}}
|
||||
window.console.log('hello');
|
||||
{{/js}}
|
||||
{{</* /example */>}}
|
||||
```
|
||||
|
||||
{{< example >}}
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" placeholder="Search">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-primary" type="button">
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{< /example >}}
|
6
admin/tool/componentlibrary/content/moodle/_index.md
Normal file
6
admin/tool/componentlibrary/content/moodle/_index.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: "Moodle"
|
||||
date: 2017-10-17T15:26:15Z
|
||||
draft: false
|
||||
weight: 1
|
||||
---
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: "Accessibility"
|
||||
date: 2020-02-03T15:26:15Z
|
||||
draft: false
|
||||
weight: 40
|
||||
---
|
|
@ -0,0 +1,63 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Colour contrast"
|
||||
description: "Colour contrast for Moodle UI components"
|
||||
date: 2021-03-30T09:40:32+01:00
|
||||
draft: false
|
||||
tags:
|
||||
- 3.9
|
||||
---
|
||||
|
||||
## Accessibile colours
|
||||
|
||||
In WCAG 2, contrast is a measure of the difference in perceived "luminance" or brightness between two colors (the phrase "color contrast" is never used). This brightness difference is expressed as a ratio ranging from 1:1 (e.g. white on white) to 21:1 (e.g., black on a white).
|
||||
|
||||
## Common colour contrast issues
|
||||
|
||||
Most contrast issue, where the ratio is below 4.5:1 in Moodle are found on pages that using a background colour with text on top. For example a striped table with light text. Contrast issues should be qualified as bugs and reported on the Moodle tracker.
|
||||
|
||||
Moodle's colour set is designed to provide high contrast and maximum brightness. If the Moodle colours are changed using a custom theme make sure you test the contrast of pages like the enrolment table, reports and Moodle activities.
|
||||
|
||||
To test colour contrast you can use the inbuild functionality of your browser, my favourite extension is the "WCAG Colour contrast checker" for Chrome.
|
||||
|
||||
## Tables with links
|
||||
|
||||
This table with links should show no colour contrast issues.
|
||||
|
||||
{{< example show_markup="false" >}}
|
||||
<table class="flexible table table-striped table-hover generaltable generalbox">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Email</th>
|
||||
<th scope="col">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr >
|
||||
<th scope="row"><input type="checkbox" class="m-1" value="" data-action="toggle" data-toggle="master" data-togglegroup="participants-table" data-toggle-selectall="Select all" data-toggle-deselectall="Deselect all"></th>
|
||||
<td><a href="#">Bas Brands</a></td>
|
||||
<td>bas@example.com</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><input type="checkbox" class="m-1" value="" data-action="toggle" data-toggle="master" data-togglegroup="participants-table" data-toggle-selectall="Select all" data-toggle-deselectall="Deselect all"></th>
|
||||
<td><a href="#">Chris Cross</a></td>
|
||||
<td>chris@example.com</td>
|
||||
<td>
|
||||
Active
|
||||
</td>
|
||||
</tr>
|
||||
<tr >
|
||||
<th scope="row"><input type="checkbox" class="m-1" value="" data-action="toggle" data-toggle="master" data-togglegroup="participants-table" data-toggle-selectall="Select all" data-toggle-deselectall="Deselect all"></th>
|
||||
<td>
|
||||
<a class="linktest-1" href="#">Irene Ipsum</a><br>
|
||||
</td>
|
||||
<td>irene@example.com</td>
|
||||
<td>@blab</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{{< /example >}}
|
|
@ -0,0 +1,71 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Keyboard access"
|
||||
description: "Guidelines for create keyboard accessible User interfaces"
|
||||
date: 2020-02-04T09:40:32+01:00
|
||||
draft: false
|
||||
tags:
|
||||
- MDL-64494
|
||||
- MDL-67874
|
||||
- 3.9
|
||||
---
|
||||
|
||||
## Keyboard navigation
|
||||
|
||||
Keyboard accessibility is one of the most important aspects of web accessibility. Many users with motor disabilities rely on a keyboard. Blind users also typically use a keyboard for navigation. Some people have tremors which don't allow for fine muscle control. Others have little or no use of their hands. Some people simply do not have hands, whether due to a birth defect, an accident, or amputation. In addition to traditional keyboards, some users may use modified keyboards or other hardware that mimics the functionality of a keyboard. For more info visit the [Keyboard Accessibility](https://webaim.org/techniques/keyboard/) page on WebAIM.
|
||||
|
||||
## Moodle focus outline
|
||||
|
||||
A keyboard user typically uses the Tab key to navigate through interactive elements on a web page—links, buttons, fields for inputting text, etc. When an item has keyboard "focus", it can be activated or manipulated with the keyboard. A sighted keyboard user must be provided with a visual indicator of the element that currently has keyboard focus.
|
||||
|
||||
The focus outline contrast must meet the WCAG colour contrast guidelines, to ensure focus visibility of buttons the standard Bootstrap button focus colours are used. For links the focus colour was changed in [MDL-67874](https://tracker.moodle.org/browse/MDL-67874)
|
||||
|
||||
## Link focus colours
|
||||
The focus outlines colours in Moodle have been made more accessible in [MDL-67874](https://tracker.moodle.org/browse/MDL-67874). Typically your OS or browser has default values for the focus outline colours. In some cases the colour contrast of these outlines is not enough so the outline colours for links has changed to a darker shade.
|
||||
|
||||
## Example focus outlines
|
||||
{{< example show_markup="false">}}
|
||||
<div id="focusexamples">
|
||||
<p> Normal buttons</p>
|
||||
<div>
|
||||
<span class="mr-2"><button class="btn btn-primary">Primary</button></span>
|
||||
<span class="mr-2"><button class="btn btn-secondary">Secondary</button></span>
|
||||
<span class="mr-2"><button class="btn btn-danger">Danger</button></span>
|
||||
<span class="mr-2"><button class="btn btn-outline-secondary">Outline</button></span>
|
||||
<span class=""><a href="#" class="aalink">clickable link</a></span>
|
||||
</div>
|
||||
<p class="mt-4"> keyboard focus</p>
|
||||
<div>
|
||||
<span class="mr-2"><button class="focusloop btn btn-primary">Primary</button></span>
|
||||
<span class="mr-2"><button class="focusloop btn btn-secondary">Secondary</button></span>
|
||||
<span class="mr-2"><button class="focusloop btn btn-danger">Danger</button></span>
|
||||
<span class="mr-2"><button class="focusloop btn btn-outline-secondary">Outline</button></span>
|
||||
<span class=""><a href="#" class="focusloop aalink">clickable link</a></span>
|
||||
</div>
|
||||
<button id="showfocus" class="btn btn-success btn-large mt-5" type="button">Show focus</button>
|
||||
</div>
|
||||
{{#js}}
|
||||
var exampleContainer = document.querySelector('#focusexamples');
|
||||
|
||||
document.getElementById("showfocus").addEventListener('click', function(){
|
||||
var elements = exampleContainer.querySelectorAll('.focusloop');
|
||||
elements.forEach(function(item) {
|
||||
item.focus();
|
||||
item.classList.add('focus');
|
||||
});
|
||||
});
|
||||
|
||||
exampleContainer.querySelectorAll('.aalink').forEach(function (link) {
|
||||
window.console.log(link);
|
||||
link.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
{{/js}}
|
||||
{{< /example >}}
|
||||
|
||||
## Tab focus order.
|
||||
The focus order when navigating a Moodle page needs to be logical.
|
||||
An example of logical focus order would be starting at the main menu before then following through to the main content and finally the footer. To achieve this the navdrawer menu has been relocate in the DOM to be positioned right after the navdrawer in [MDL-67863](https://tracker.moodle.org/browse/MDL-67863).
|
||||
|
||||
Testing with a keyboard is essential when evaluating the accessibility of your compoment, You should never be able to tab to hidden items and there should always be a visual que to your current location in the page.
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: "Moodle Components"
|
||||
date: 2020-02-03T15:26:15Z
|
||||
draft: false
|
||||
weight: 20
|
||||
---
|
165
admin/tool/componentlibrary/content/moodle/components/buttons.md
Normal file
165
admin/tool/componentlibrary/content/moodle/components/buttons.md
Normal file
|
@ -0,0 +1,165 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Buttons"
|
||||
description: "Button types used in Moodle"
|
||||
date: 2020-01-14T16:32:24+01:00
|
||||
draft: false
|
||||
weight: 10
|
||||
tags:
|
||||
- Available
|
||||
---
|
||||
|
||||
|
||||
## How to use buttons
|
||||
|
||||
Button components are available as part of a Moodle form, as a single button functioning as a form submit or triggering a JavaScript action. Buttons used in Moodle are based on the [Bootstrap buttons]({{< docsref "/components/buttons" >}}).
|
||||
|
||||
The most used buttons types in Moodle are:
|
||||
|
||||
## Example
|
||||
|
||||
{{< example >}}
|
||||
<button type="button" class="btn btn-primary">Primary Button</button>
|
||||
<button type="button" class="btn btn-secondary">Secondary Button</button>
|
||||
<button type="button" class="btn btn-danger">Danger Button</button>
|
||||
<button type="button" class="btn btn-outline-secondary">Outline Button</button>
|
||||
{{< /example >}}
|
||||
|
||||
### Primary buttons
|
||||
|
||||
{{< example show_markup="false">}}
|
||||
<button type="button" class="btn btn-primary">Primary Button</button>
|
||||
{{< /example >}}
|
||||
|
||||
For the primary/most used action on the page use a primary button.
|
||||
For each for or UI component there should only be one primary button.
|
||||
|
||||
### Secondary buttons
|
||||
|
||||
{{< example show_markup="false">}}
|
||||
<button type="button" class="btn btn-secondary">Primary Button</button>
|
||||
{{< /example >}}
|
||||
|
||||
Secondary buttons are used for the the cancel options on a form or as a button that is always visible (blocks editing on)
|
||||
|
||||
### Danger buttons.
|
||||
|
||||
{{< example show_markup="false">}}
|
||||
<button type="button" class="btn btn-danger">Primary Button</button>
|
||||
{{< /example >}}
|
||||
|
||||
Use a danger button when the primary action is a potentially dangerous action, like deleting a contact in the messaging interface.
|
||||
|
||||
### Outline buttons
|
||||
|
||||
{{< example show_markup="false">}}
|
||||
<button type="button" class="btn btn-outline-secondary">Primary Button</button>
|
||||
{{< /example >}}
|
||||
|
||||
Outline buttons are used for buttons that controll part of the user interface, like filters on a table or the display type on the user dashboard. Outline buttons look more subtle than secondary buttons and do not distract the user from the main user interface too much.
|
||||
|
||||
## Adding buttons to a page
|
||||
|
||||
### Using the single_select renderer
|
||||
|
||||
The ```single_select()``` renderer allows you to quickly add a button with an action to a page without having to write a template for the page. Single select buttons are added as miniature forms that can pass custom form data.
|
||||
|
||||
{{< php >}}
|
||||
$url = new moodle_url("$CFG->wwwroot/my/index.php", $params);
|
||||
$button = $OUTPUT->single_button($url, $editstring);
|
||||
$PAGE->set_button($resetbutton . $button);
|
||||
{{< / php >}}
|
||||
|
||||
### Button links
|
||||
|
||||
Links can be style to look like buttons, the action for this button is to simply navigate to some other page
|
||||
|
||||
{{< example >}}
|
||||
<a href="#next" class="btn btn-secondary">Next Page</a>
|
||||
{{< /example >}}
|
||||
|
||||
### Action buttons
|
||||
|
||||
Action buttons have a data-action and are usually linked to a JavaScript eventlistener that will do something on button click.
|
||||
|
||||
{{< example >}}
|
||||
<button data-action="show-fun-thing" class="btn btn-secondary">Click me</button>
|
||||
{{< /example >}}
|
||||
|
||||
|
||||
### UX tips
|
||||
|
||||
Primary buttons have a higher visual weight and attracts most attention it should be used for the default action on a page.
|
||||
|
||||
Use primary buttons for the positive action on the page, for example "Save" or "Submit" when working on an assignment
|
||||
|
||||
{{< example >}}
|
||||
<div class="row">
|
||||
<div class="col-5">
|
||||
<div class="card mb-2">
|
||||
<div class="card-body">
|
||||
<strong>Save Changes?</strong>
|
||||
<div class="d-flex">
|
||||
<button type="button" class="btn btn-secondary mr-1">Cancel</button>
|
||||
<button type="button" class="btn btn-primary mr-1">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-5">
|
||||
<div class="card mb-2">
|
||||
<div class="card-body">
|
||||
<strong>Delete profile</strong>
|
||||
<div class="d-flex">
|
||||
<button type="button" class="btn btn-primary mr-1">Cancel</button>
|
||||
<button type="button" class="btn btn-secondary">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{< /example >}}
|
||||
|
||||
In case of more dangerous actions, like deleting something the having stiling the Cancel button as the primary button could be a good choice
|
||||
|
||||
Bootstrap classes are used to style Buttons, the most used styles are:
|
||||
|
||||
{{< example >}}
|
||||
<button type="button" class="btn btn-primary">Primary buttons</button>
|
||||
<button type="button" class="btn btn-secondary">Secondary buttons</button>
|
||||
{{< /example >}}
|
||||
|
||||
### Button text
|
||||
|
||||
The meaning of buttons must be very clear.
|
||||
|
||||
{{< example show_markup="false">}}
|
||||
<div class="row">
|
||||
<div class="col-5">
|
||||
<div class="card mb-2">
|
||||
<div class="card-body">
|
||||
<strong>Save Changes?</strong>
|
||||
<p>Would you like to not save your changes before exiting?</p>
|
||||
<div class="d-flex">
|
||||
<button type="button" class="btn btn-primary mr-1">Yes</button>
|
||||
<button type="button" class="btn btn-secondary">No</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert alert-warning">Avoid generic 'OK' or 'Yes', avoid confusing phrases</div>
|
||||
</div>
|
||||
<div class="col-5">
|
||||
<div class="card mb-2">
|
||||
<div class="card-body">
|
||||
<strong>Save Changes</strong>
|
||||
<p>Would you like to save your changes before exiting?</p>
|
||||
<div class="d-flex">
|
||||
<button type="button" class="btn btn-primary mr-1">Save</button>
|
||||
<button type="button" class="btn btn-secondary">Discard</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert alert-success">Avoid generic 'OK' or 'Yes', avoid confusing phrases</div>
|
||||
</div>
|
||||
</div>
|
||||
{{< /example >}}
|
|
@ -0,0 +1,151 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Course cards"
|
||||
description: "Course cards are easy to access clickable components used in collections to navigate to the course home page."
|
||||
date: 2020-01-14T16:32:24+01:00
|
||||
draft: false
|
||||
weight: 20
|
||||
toc: true
|
||||
tags:
|
||||
- Available
|
||||
---
|
||||
|
||||
## How to use course cards
|
||||
|
||||
Course cards are rendered using a shared template found in `course/templates/coursecard.mustache`. They are loaded throught JavaScript or PHP on pages like the user dashboard.
|
||||
|
||||
Course cards should always contain an image, if no image is provided by the backend a placeholder image is used. The card image and title should be clickable and should always link you to a course page.
|
||||
|
||||
Course cards should always show
|
||||
|
||||
* Course image
|
||||
* Course full name
|
||||
* Course category
|
||||
* If a course is favourited
|
||||
|
||||
## Example
|
||||
|
||||
{{< mustache template="core_course/view-cards">}}
|
||||
{
|
||||
"courses": [
|
||||
{
|
||||
"viewurl": "https://moodlesite/course/view.php?id=2",
|
||||
"courseimage": "https://placekitten.com/300/500",
|
||||
"fullname": "Mathematics Year One",
|
||||
"isfavourite": true,
|
||||
"coursecategory": "Miscellaneous",
|
||||
"showcoursecategory": true,
|
||||
"visible": true
|
||||
}
|
||||
]
|
||||
}
|
||||
{{< /mustache >}}
|
||||
|
||||
## Sources
|
||||
|
||||
A deck of course cards:
|
||||
`core_course/view-cards.mustache`
|
||||
|
||||
A single card:
|
||||
`course/templates/coursecard.mustache`
|
||||
|
||||
## Exporter
|
||||
The data structure for course cards are provided by the exporter class:
|
||||
`course/classes/external/course_summary_exporter.php`
|
||||
|
||||
## Usage
|
||||
|
||||
Course cards can be used in any place that lists courses, it helps users quickly scan the available content and find a course based on the remembered course image or the course name. Guidelines for using course cards are:
|
||||
|
||||
* Keep them simple
|
||||
* Minimize the number of actions on a card
|
||||
* Use images smartly
|
||||
|
||||
The example below show a deck of cards as used on the starred courses block
|
||||
|
||||
{{< mustache template="core_course/view-cards" >}}
|
||||
{
|
||||
"courses": [
|
||||
{
|
||||
"viewurl": "https://moodlesite/course/view.php?id=2",
|
||||
"courseimage": "https://placekitten.com/300/500",
|
||||
"fullname": "Mathematics Year One",
|
||||
"isfavourite": true,
|
||||
"coursecategory": "Miscellaneous",
|
||||
"showcoursecategory": true,
|
||||
"visible": true
|
||||
},
|
||||
{
|
||||
"viewurl": "https://moodlesite/course/view.php?id=3",
|
||||
"courseimage": "https://placekitten.com/330/500",
|
||||
"fullname": "Health and Safety",
|
||||
"isfavourite": false,
|
||||
"coursecategory": "Business",
|
||||
"showcoursecategory": true,
|
||||
"visible": true
|
||||
},
|
||||
{
|
||||
"viewurl": "https://moodlesite/course/view.php?id=4",
|
||||
"courseimage": "https://placekitten.com/360/500",
|
||||
"fullname": "French Advanced",
|
||||
"isfavourite": false,
|
||||
"coursecategory": "Languages",
|
||||
"showcoursecategory": true,
|
||||
"visible": true
|
||||
},
|
||||
{
|
||||
"viewurl": "https://moodlesite/course/view.php?id=4",
|
||||
"courseimage": "https://placekitten.com/360/400",
|
||||
"fullname": "French Year one",
|
||||
"isfavourite": false,
|
||||
"coursecategory": "Languages",
|
||||
"showcoursecategory": true,
|
||||
"visible": true
|
||||
}
|
||||
]
|
||||
}
|
||||
{{< /mustache >}}
|
||||
|
||||
|
||||
## Placeholder images
|
||||
|
||||
Cards usually don't really look great without images. That's why we show a placeholder image when no course image is provided. Placeholder images are rendered in core using a library that generates a uniqueish svg's from idnumbers.
|
||||
|
||||
{{< php >}}
|
||||
$OUTPUT->get_generated_image_for_id($id);
|
||||
{{< /php >}}
|
||||
|
||||
{{< example show_markup="false">}}
|
||||
<div class="card-deck">
|
||||
{{< root.inline >}}
|
||||
{{- $pl1 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-1.txt" -}}
|
||||
{{- $pl2 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-2.txt" -}}
|
||||
{{- $pl3 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-3.txt" -}}
|
||||
{{- $pl4 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-4.txt" -}}
|
||||
{{- $pl5 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-5.txt" -}}
|
||||
{{- $pl6 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-6.txt" -}}
|
||||
{{- $pl7 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-7.txt" -}}
|
||||
{{- $pl8 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-8.txt" -}}
|
||||
{{- $pl9 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-9.txt" -}}
|
||||
|
||||
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl1 -}}')">
|
||||
</div>
|
||||
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl2 -}}')">
|
||||
</div>
|
||||
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl3 -}}')">
|
||||
</div>
|
||||
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl4 -}}')">
|
||||
</div>
|
||||
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl5 -}}')">
|
||||
</div>
|
||||
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl6 -}}')">
|
||||
</div>
|
||||
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl7 -}}')">
|
||||
</div>
|
||||
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl8 -}}')">
|
||||
</div>
|
||||
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl9 -}}')">
|
||||
</div>
|
||||
{{< /root.inline >}}
|
||||
</div>
|
||||
{{< /example >}}
|
|
@ -0,0 +1,57 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Example"
|
||||
description: "This is an example page describing the example component"
|
||||
date: 2020-01-28T10:13:29+01:00
|
||||
draft: true
|
||||
weight: 30
|
||||
---
|
||||
|
||||
## How it works
|
||||
|
||||
The EXAMPLE is used to [...] . It can be found in Moodle on pages where [...]
|
||||
|
||||
## Example
|
||||
|
||||
Show what the example looks like in Moodle, if your component includes and JavaScript backend please describe how it is initiated.
|
||||
|
||||
{{< example >}}
|
||||
|
||||
<div class="example w-25 border border-secondary p-3">
|
||||
<button class="btn btn-primary btn-block" id="clickme">
|
||||
Click me
|
||||
<span id="waiting" class="spinner-grow-sm" role="status" aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{{#js}}
|
||||
require(['jquery'], function($) {
|
||||
$('#clickme').on('click', function() {
|
||||
$('#waiting').toggleClass('spinner-grow');
|
||||
});
|
||||
});
|
||||
{{/js}}
|
||||
{{< /example >}}
|
||||
|
||||
## Example explained
|
||||
|
||||
How can you use this example?
|
||||
Are there any example pages in Moodle?
|
||||
What are the different options you have for different contexts (places in Moodle)?
|
||||
What colours can be used?
|
||||
Can it be called from PHP and JavaScript
|
||||
|
||||
## JavaScript behavior
|
||||
|
||||
Showcase the different ways this buttons can behave:
|
||||
|
||||
Does it trigger any events, does it listen to events?
|
||||
Does it require any core AMD modules?
|
||||
Is there a webservice backend required?
|
||||
|
||||
## Accessibility
|
||||
|
||||
Descripbe the `aria-something` parts of the element. Are there any possible accessibility issues using this example?
|
||||
What are the considerations for keyboard navigation?
|
||||
What accessibile colors can be used?
|
||||
How to test its accessibility?
|
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Footer"
|
||||
description: Moodle footer HTML and required code injected in the page footer
|
||||
date: 2020-03-02T16:32:24+01:00
|
||||
draft: false
|
||||
weight: 40
|
||||
tags:
|
||||
- available
|
||||
- needs review
|
||||
---
|
||||
|
||||
## How are footers implemented in Moodle?
|
||||
|
||||
The page footer is shown at the bottom of every page in Moodle, typically a Moodle footer contains links to:
|
||||
|
||||
* A link to the Moodle docs for the current page
|
||||
* resetting user tours
|
||||
* user login information
|
||||
* a link to the Moodle homepage
|
||||
|
||||
When the setting ```perfdebug``` is turned on (Site Administration > Development > Debugging) additional performance info is shown in the page footer.
|
||||
|
||||
## Footer styling
|
||||
|
||||
Since footers are repeated on all pages they are styled distinctly using a dark background colour and light fonts. Links need to be underlined and use light fonts too.
|
||||
|
||||
The page footer should always stick to the bottom of the page and never overlap any page content.
|
||||
|
||||
### Minimal footer requirements
|
||||
|
||||
The page footer is required to inject the page JavaScript, show the reset user tours link and show user info and (if avaliable) the contents of the user configure theme custom menu.
|
||||
|
||||
{{< example >}}
|
||||
<footer id="page-footer" class="py-3 bg-dark text-light">
|
||||
<div class="container">
|
||||
<p class="helplink"><a href="#">Moodle docs for this page</a></p>
|
||||
You are logged in as <a href="#">Test User</a> (<a href="#">logout</a>)
|
||||
<a href="#">Home</a>
|
||||
<div class="tool_usertours-resettourcontainer"></div>
|
||||
</div>
|
||||
</footer>
|
||||
{{< /example >}}
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Form elements"
|
||||
description: "Custom form elements for Moodle"
|
||||
date: 2020-01-14T16:32:24+01:00
|
||||
draft: false
|
||||
weight: 30
|
||||
tags:
|
||||
- In development
|
||||
---
|
||||
|
||||
## How to use moodle forms
|
||||
|
||||
Forms are constructed using lib/formslib.php. Using the addElement methods in php a set of different form element types can be added to a form. For more info visit the [Moodledocs](https://docs.moodle.org/dev/lib/formslib.php_Form_Definition) page for forms
|
||||
|
||||
{{< php >}}
|
||||
$mform->addElement('button', 'intro', get_string("buttonlabel"));
|
||||
{{< / php >}}
|
||||
|
||||
Form elements are styled using Moodle templates which are rendered through PHP. Themes can override these templates.
|
||||
|
||||
Form elements are styled using the .form-control class, see the [Bootstrap](/bootstrap-4.3/forms/input-group/) docs for more info.
|
||||
|
||||
## Example form elements
|
||||
|
||||
The example form below is showing an ifram with an actual Moodle form. Use the toggle options to display the different states for the form.
|
||||
|
||||
|
||||
<iframe src="../../../../formfields.php" style="overflow:hidden;height:4000px;width:100%;border:0" title="Moodle formfields"></iframe>
|
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Icons"
|
||||
description: "Moodle icons are rendered with fontawesome or as small images"
|
||||
weight: 40
|
||||
date: 2020-02-04T09:40:32+01:00
|
||||
draft: false
|
||||
tags:
|
||||
- available
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
Most Moodle icons are rendered using the 4.7 verions of [Fontawesome](https://fontawesome.com/v4.7.0/). Iconnames are mapped from the Moodle icon name to the fontawesome icon names in `/lib/classes/output/icon_system_fontawesome.php`
|
||||
|
||||
If needed a theme can override this map and provide its own mapping.
|
||||
|
||||
## Rendering icons in Mustache Templates
|
||||
|
||||
Icons can be rendered in moodle templates using this notation:
|
||||
|
||||
```{{#pix}} i/edit, core {{/pix}}```
|
||||
|
||||
## Rendering icons in Php
|
||||
|
||||
Use the pix_icon method to retreive the HTML for an icon.
|
||||
|
||||
{{< php >}}
|
||||
$icon = $OUTPUT->pix_icon('i/edit', 'Edit me', 'moodle');
|
||||
{{< / php >}}
|
||||
|
||||
Options:
|
||||
|
||||
## Stacking fontawesome icons
|
||||
|
||||
{{< example >}}
|
||||
<span class="fa-stack fa-lg">
|
||||
<i class="fa fa-comment fa-stack-2x"></i>
|
||||
<i class="fa fa-thumbs-o-up fa-stack-1x fa-inverse"></i>
|
||||
</span>
|
||||
{{< /example >}}
|
||||
## List of mapped font-awesome icons
|
||||
|
||||
The top title of each cards displayse the name of the icon. The icon shown left is the font-awesome icons. The icon shown on the right is the old image base icon.
|
||||
|
||||
{{< moodleicons >}}
|
|
@ -0,0 +1,110 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Notifications"
|
||||
description: "Moodle notifications"
|
||||
date: 2020-02-04T09:40:32+01:00
|
||||
draft: false
|
||||
weight: 50
|
||||
tags:
|
||||
- Available
|
||||
- Needs review
|
||||
---
|
||||
|
||||
## How it works
|
||||
|
||||
Notifications are coupled with actions and provide instant feedback to the action results. Moodle notifications are shown right above the actionable content or overlaying the user interface for JavaScript related actions.
|
||||
|
||||
## Example
|
||||
|
||||
{{< example show_markup="false">}}
|
||||
<div class="alert alert-info alert-block fade in foo bar" role="alert" data-aria-autofocus="true" id="yui_3_17_2_1_1599746674354_24">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
Hello
|
||||
</div>
|
||||
{{< /example >}}
|
||||
|
||||
## Source files
|
||||
|
||||
* `lib/amd/src/notification.js`
|
||||
* `lib/templates/notification_info.mustache`
|
||||
* `lib/templates/notification_success.mustache`
|
||||
* `lib/templates/notification_warning.mustache`
|
||||
* `lib/templates/notification_error.mustache`
|
||||
|
||||
## Core renderer
|
||||
|
||||
Notifications can be added in PHP using the core renderer notification method
|
||||
|
||||
{{< php >}}
|
||||
$OUTPUT->notification('message', 'info');
|
||||
{{< / php >}}
|
||||
|
||||
## Notification templates
|
||||
|
||||
{{< mustache template="core/notification_info" >}}
|
||||
{{< /mustache >}}
|
||||
|
||||
{{< mustache template="core/notification_success" >}}
|
||||
{
|
||||
"message": "Your pants are on awesome!",
|
||||
"closebutton": 1,
|
||||
"announce": 1,
|
||||
"extraclasses": "foo bar"
|
||||
}
|
||||
{{< /mustache >}}
|
||||
|
||||
{{< mustache template="core/notification_warning" >}}
|
||||
{
|
||||
"message": "Your pants are on down!",
|
||||
"closebutton": 1,
|
||||
"announce": 1,
|
||||
"extraclasses": "foo bar"
|
||||
}
|
||||
{{< /mustache >}}
|
||||
|
||||
{{< mustache template="core/notification_error" >}}
|
||||
{
|
||||
"message": "Your pants are on fire!",
|
||||
"closebutton": 1,
|
||||
"announce": 1,
|
||||
"extraclasses": "foo bar"
|
||||
}
|
||||
{{< /mustache >}}
|
||||
|
||||
## JavaScript Notifications
|
||||
|
||||
{{< example >}}
|
||||
<button class="btn btn-secondary" data-action="shownotification">Show JS Notification</button>
|
||||
{{#js}}
|
||||
require(
|
||||
[
|
||||
'core/notification'
|
||||
],
|
||||
function(
|
||||
Notification
|
||||
) {
|
||||
document.querySelector('[data-action="shownotification"]').addEventListener('click', function() {
|
||||
Notification.alert('Notification message', 'Extra content for notification message');
|
||||
});
|
||||
});
|
||||
{{/js}}
|
||||
{{< /example >}}
|
||||
|
||||
## Toast Notifications
|
||||
|
||||
{{< example >}}
|
||||
<button class="btn btn-secondary" data-action="showtoastnotification">Show Toast Notification</button>
|
||||
{{#js}}
|
||||
require(
|
||||
[
|
||||
'core/toast'
|
||||
],
|
||||
function(
|
||||
Toast
|
||||
) {
|
||||
document.querySelector('[data-action="showtoastnotification"]').addEventListener('click', function() {
|
||||
Toast.add('Toast message');
|
||||
});
|
||||
});
|
||||
{{/js}}
|
||||
{{< /example >}}
|
|
@ -0,0 +1,124 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Search input"
|
||||
description: "find items in a collection of data"
|
||||
date: 2020-08-26T16:32:24+01:00
|
||||
draft: false
|
||||
weight: 60
|
||||
tags:
|
||||
- Introduced in Moodle 3.10
|
||||
- MDL-69454
|
||||
---
|
||||
|
||||
## How it works
|
||||
|
||||
Single searches allow the user the quickly search a collection of data. A search is input in the search field and the results are shown immediately (using JS) or after the search has been posted to Moodle.
|
||||
|
||||
Searches are used in the page navbar, blocks, module pages, settings, the contentbank etc.
|
||||
|
||||
## Example
|
||||
|
||||
<div class="small">
|
||||
Default search input.
|
||||
</div>
|
||||
{{< mustache template="core/search_input" >}}
|
||||
{
|
||||
"action": "https://moodle.local/admin/search.php",
|
||||
"extraclasses": "my-2",
|
||||
"inputname": "search",
|
||||
"inform": false,
|
||||
"searchstring": "Search something",
|
||||
"hiddenfields": [
|
||||
{
|
||||
"name": "context",
|
||||
"value": "11"
|
||||
}
|
||||
]
|
||||
}
|
||||
{{< /mustache >}}
|
||||
<div class="mt-3 small">
|
||||
Emphasized search input using .btn-primary
|
||||
</div>
|
||||
{{< mustache template="core/search_input" >}}
|
||||
{
|
||||
"action": "https://moodle.local/admin/search.php",
|
||||
"extraclasses": "my-2",
|
||||
"uniqid": "Unique string",
|
||||
"inputname": "search",
|
||||
"inform": false,
|
||||
"btnclass": "btn-primary",
|
||||
"searchstring": "Search something",
|
||||
"hiddenfields": [
|
||||
{
|
||||
"name": "context",
|
||||
"value": "11"
|
||||
}
|
||||
]
|
||||
}
|
||||
{{< /mustache >}}
|
||||
|
||||
**Use**
|
||||
|
||||
Use a default search input when searching is not expected to be the primary action on this page. Use the emphasized search when it is the default action AND the only search input found on the page. (except the navbar search).
|
||||
|
||||
**Variables**
|
||||
|
||||
* action: used to specify the form (get) action
|
||||
* extraclasses: add these css classes to the search wrapper
|
||||
* uniqid: Unique string
|
||||
* inputname: form field name for search input
|
||||
* inform: search is part of a larger form
|
||||
* query: current search value from user input
|
||||
* btnclass: use a btn class for the btn design, (btn-secondary, btn-primary)
|
||||
* searchstring: string describing current search for placeholder and aria-label
|
||||
* hiddenfields: array with name valua pairs for extra hidden form fields
|
||||
|
||||
<div class="my-5"></div>
|
||||
|
||||
### Auto search input with clear option
|
||||
|
||||
{{< mustache template="core/search_input_auto" >}}
|
||||
{
|
||||
"placeholder": "Search settings",
|
||||
"uniqid": "45"
|
||||
}
|
||||
{{< /mustache >}}
|
||||
|
||||
**Use**
|
||||
|
||||
This search option is used when the search imput immediately triggers updating data displayed below the search, for example: a table of usernames. It includes a clear button that clears the input on typeing.
|
||||
|
||||
**Variables**
|
||||
|
||||
* uniqid: Unique string
|
||||
* placeholder: search placeholder
|
||||
|
||||
<div class="my-5"></div>
|
||||
|
||||
### Navbar search form
|
||||
|
||||
{{< mustache template="core/search_input_navbar" >}}
|
||||
{
|
||||
"action": "https://moodle.local/admin/search.php",
|
||||
"inputname": "search",
|
||||
"searchstring": "Search",
|
||||
"hiddenfields": [
|
||||
{
|
||||
"name": "cmid",
|
||||
"value": "11"
|
||||
}
|
||||
]
|
||||
}
|
||||
{{< /mustache >}}
|
||||
|
||||
**Use**
|
||||
|
||||
This search should be used once on the page and triggers a global site search. It uses a minimal amount of space to prevent breakage on mobile use.
|
||||
|
||||
**Features**
|
||||
|
||||
* click search button to start typing
|
||||
* click close button to hide search
|
||||
* click enter after input to post the form
|
||||
* uses very little space
|
||||
* overlaps navbar when viewed on mobile.
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: "JavaScript"
|
||||
date: 2020-02-03T15:26:15Z
|
||||
draft: false
|
||||
weight: 30
|
||||
---
|
|
@ -0,0 +1,86 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Moodle Charts"
|
||||
date: 2020-01-14T16:32:24+01:00
|
||||
draft: false
|
||||
---
|
||||
|
||||
## How it works
|
||||
|
||||
The core chart_builder interface for the ChartJS library that allows you to create a nice visual presentation of your data.
|
||||
|
||||
## Source files
|
||||
|
||||
* `lib/amd/src/chart_builder.js`
|
||||
* `lib/amd/src/chart_*.js`
|
||||
* `lib/templates/chart.mustache`
|
||||
|
||||
## Core api
|
||||
|
||||
Create a new instance of your required chart type
|
||||
|
||||
{{< php >}}
|
||||
$chart1 = new chart_bar();
|
||||
$series1 = new chart_series('Data type', $data);
|
||||
$chart1->add_series($series1);
|
||||
$OUTPUT->render($chart1);
|
||||
{{< / php >}}
|
||||
|
||||
|
||||
### JavaScript
|
||||
|
||||
{{< mustache template="core/chart" >}}
|
||||
{
|
||||
"chartdata": "{\u0022type\u0022:\u0022pie\u0022,\u0022series\u0022:[{\u0022label\u0022:\u0022Sales\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[1000,1170,660,1030],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null}],\u0022labels\u0022:[\u00222004\u0022,\u00222005\u0022,\u00222006\u0022,\u00222007\u0022],\u0022title\u0022:\u0022PIE CHART\u0022,\u0022axes\u0022:{\u0022x\u0022:[],\u0022y\u0022:[]},\u0022config_colorset\u0022:null,\u0022doughnut\u0022:null}",
|
||||
"withtable": true
|
||||
}
|
||||
{{< /mustache >}}
|
||||
|
||||
{{< mustache template="core/chart" >}}
|
||||
{
|
||||
"chartdata": "{\u0022type\u0022:\u0022pie\u0022,\u0022series\u0022:[{\u0022label\u0022:\u0022Sales\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[1000,1170,660,1030],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null}],\u0022labels\u0022:[\u00222004\u0022,\u00222005\u0022,\u00222006\u0022,\u00222007\u0022],\u0022title\u0022:\u0022DOUGHNUT CHART\u0022,\u0022axes\u0022:{\u0022x\u0022:[],\u0022y\u0022:[]},\u0022config_colorset\u0022:null,\u0022doughnut\u0022:true}",
|
||||
"withtable": true
|
||||
}
|
||||
{{< /mustache >}}
|
||||
|
||||
{{< mustache template="core/chart" >}}
|
||||
{
|
||||
"chartdata": "{\u0022type\u0022:\u0022line\u0022,\u0022series\u0022:[{\u0022label\u0022:\u0022Sales\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[1000,1170,660,1030],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null},{\u0022label\u0022:\u0022Expenses\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[400,460,1120,540],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null}],\u0022labels\u0022:[\u00222004\u0022,\u00222005\u0022,\u00222006\u0022,\u00222007\u0022],\u0022title\u0022:\u0022TENSIONED LINES CHART\u0022,\u0022axes\u0022:{\u0022x\u0022:[],\u0022y\u0022:[]},\u0022config_colorset\u0022:null,\u0022smooth\u0022:false}",
|
||||
"withtable": true
|
||||
}
|
||||
{{< /mustache >}}
|
||||
|
||||
{{< mustache template="core/chart" >}}
|
||||
{
|
||||
"chartdata": "{\u0022type\u0022:\u0022line\u0022,\u0022series\u0022:[{\u0022label\u0022:\u0022Sales\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[1000,1170,660,1030],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null},{\u0022label\u0022:\u0022Expenses\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[400,460,1120,540],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null}],\u0022labels\u0022:[\u00222004\u0022,\u00222005\u0022,\u00222006\u0022,\u00222007\u0022],\u0022title\u0022:\u0022SMOOTH LINES CHART\u0022,\u0022axes\u0022:{\u0022x\u0022:[],\u0022y\u0022:[]},\u0022config_colorset\u0022:null,\u0022smooth\u0022:true}",
|
||||
"withtable": true
|
||||
}
|
||||
{{< /mustache >}}
|
||||
|
||||
{{< mustache template="core/chart" >}}
|
||||
{
|
||||
"chartdata": "{\u0022type\u0022:\u0022bar\u0022,\u0022series\u0022:[{\u0022label\u0022:\u0022Sales\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[1000,1170,660,1030],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null},{\u0022label\u0022:\u0022Expenses\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[400,460,1120,540],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null}],\u0022labels\u0022:[\u00222004\u0022,\u00222005\u0022,\u00222006\u0022,\u00222007\u0022],\u0022title\u0022:\u0022BAR CHART\u0022,\u0022axes\u0022:{\u0022x\u0022:[],\u0022y\u0022:[{\u0022label\u0022:null,\u0022labels\u0022:null,\u0022max\u0022:null,\u0022min\u0022:0,\u0022position\u0022:null,\u0022stepSize\u0022:null}]},\u0022config_colorset\u0022:null,\u0022horizontal\u0022:false,\u0022stacked\u0022:null}",
|
||||
"withtable": true
|
||||
}
|
||||
{{< /mustache >}}
|
||||
|
||||
{{< mustache template="core/chart" >}}
|
||||
{
|
||||
"chartdata": "{\u0022type\u0022:\u0022bar\u0022,\u0022series\u0022:[{\u0022label\u0022:\u0022Sales\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[1000,1170,660,1030],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null},{\u0022label\u0022:\u0022Expenses\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[400,460,1120,540],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null}],\u0022labels\u0022:[\u00222004\u0022,\u00222005\u0022,\u00222006\u0022,\u00222007\u0022],\u0022title\u0022:\u0022HORIZONTAL BAR CHART\u0022,\u0022axes\u0022:{\u0022x\u0022:[],\u0022y\u0022:[{\u0022label\u0022:null,\u0022labels\u0022:null,\u0022max\u0022:null,\u0022min\u0022:0,\u0022position\u0022:null,\u0022stepSize\u0022:null}]},\u0022config_colorset\u0022:null,\u0022horizontal\u0022:true,\u0022stacked\u0022:null}",
|
||||
"withtable": true
|
||||
}
|
||||
{{< /mustache >}}
|
||||
|
||||
{{< mustache template="core/chart" >}}
|
||||
{
|
||||
"chartdata": "{\u0022type\u0022:\u0022bar\u0022,\u0022series\u0022:[{\u0022label\u0022:\u0022Sales\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[1000,1170,660,1030],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null},{\u0022label\u0022:\u0022Expenses\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[400,460,1120,540],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null}],\u0022labels\u0022:[\u00222004\u0022,\u00222005\u0022,\u00222006\u0022,\u00222007\u0022],\u0022title\u0022:\u0022STACKED BAR CHART\u0022,\u0022axes\u0022:{\u0022x\u0022:[],\u0022y\u0022:[{\u0022label\u0022:null,\u0022labels\u0022:null,\u0022max\u0022:null,\u0022min\u0022:0,\u0022position\u0022:null,\u0022stepSize\u0022:null}]},\u0022config_colorset\u0022:null,\u0022horizontal\u0022:false,\u0022stacked\u0022:true}",
|
||||
"withtable": true
|
||||
}
|
||||
{{< /mustache >}}
|
||||
|
||||
{{< mustache template="core/chart" >}}
|
||||
{
|
||||
"chartdata": "{\u0022type\u0022:\u0022bar\u0022,\u0022series\u0022:[{\u0022label\u0022:\u0022Expenses\u0022,\u0022labels\u0022:null,\u0022type\u0022:\u0022line\u0022,\u0022values\u0022:[400,460,1120,540],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null},{\u0022label\u0022:\u0022Sales\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[1000,1170,660,1030],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null}],\u0022labels\u0022:[\u00222004\u0022,\u00222005\u0022,\u00222006\u0022,\u00222007\u0022],\u0022title\u0022:\u0022BAR CHART COMBINED WITH LINE CHART\u0022,\u0022axes\u0022:{\u0022x\u0022:[],\u0022y\u0022:[{\u0022label\u0022:null,\u0022labels\u0022:null,\u0022max\u0022:null,\u0022min\u0022:0,\u0022position\u0022:null,\u0022stepSize\u0022:null}]},\u0022config_colorset\u0022:null,\u0022horizontal\u0022:false,\u0022stacked\u0022:null}",
|
||||
"withtable": true
|
||||
}
|
||||
{{< /mustache >}}
|
|
@ -0,0 +1,63 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Emojipicker"
|
||||
date: 2020-02-04T09:40:32+01:00
|
||||
draft: false
|
||||
tags:
|
||||
- MDL-65896
|
||||
- 3.8
|
||||
---
|
||||
|
||||
## How it works
|
||||
|
||||
The emoji picker is used in the Moodle messaging interface and in Atto. It allows you to select an emoji which then is returned for use in your input element.
|
||||
|
||||
## Source files
|
||||
|
||||
* `lib/amd/src/emoji/picker.js`
|
||||
* `lib/templates/emoji/picker.mustache`
|
||||
|
||||
## Examples
|
||||
|
||||
{{< example >}}
|
||||
<div class="row">
|
||||
<div data-region="emojipickertest" class="col-md-9">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<h4>Emoji picker result:<h4>
|
||||
<div data-region="emojivalue" style="font-size: 3rem"></div>
|
||||
</div>
|
||||
|
||||
{{#js}}
|
||||
require(
|
||||
[
|
||||
'jquery',
|
||||
'core/templates',
|
||||
'core/emoji/picker'
|
||||
],
|
||||
function(
|
||||
$,
|
||||
templates,
|
||||
emojiPicker
|
||||
) {
|
||||
var emojiCallback = function(emoji) {
|
||||
$('[data-region="emojivalue"]').html(emoji);
|
||||
}
|
||||
|
||||
var testArea = $('[data-region="emojipickertest"]');
|
||||
templates.render('core/emoji/picker', {}).done(function(html, js) {
|
||||
templates.replaceNodeContents(testArea, html, js);
|
||||
emojiPicker(testArea[0], emojiCallback);
|
||||
});
|
||||
|
||||
});
|
||||
{{/js}}
|
||||
{{< /example >}}
|
||||
|
||||
## Usage
|
||||
|
||||
Fetch / render the core template ```core/emoji/picker.mustache``` and load the ```core/emoji/picker.js```. Render the template and run the js on the new domnode.
|
||||
|
||||
{{< highlight js >}}
|
||||
emojiPicker(domNode, callback);
|
||||
{{< /highlight >}}
|
|
@ -0,0 +1,124 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Sortable list"
|
||||
description: "A reusable list component for sorting"
|
||||
date: 2020-02-04T09:40:32+01:00
|
||||
draft: false
|
||||
tags:
|
||||
- MDL-51803
|
||||
- 3.7
|
||||
---
|
||||
|
||||
## How it works
|
||||
|
||||
The sortable lists can be used for horizontal and vertical ordering of list elements. The key element of using a sortable list is to provide drag handles to list items. These can be included using the core drag_handle template.
|
||||
|
||||
## Source files
|
||||
|
||||
* `/lib/amd/src/sortable_lists.js`
|
||||
* `/lib/templates/drag_handle.mustache`
|
||||
|
||||
## Usage
|
||||
|
||||
The sortable list AMD module can be loaded in your template or via a amd init call. The list to be sorted is passed as the first argument to
|
||||
|
||||
{{< highlight js >}}
|
||||
// Default config, this variable is optional.
|
||||
var config = {
|
||||
targetListSelector: null,
|
||||
moveHandlerSelector: '[data-drag-type=move]',
|
||||
isHorizontal: false,
|
||||
autoScroll: true
|
||||
};
|
||||
new SortableList(domElement, config);
|
||||
{{< /highlight >}}
|
||||
|
||||
The events listed below can be used to connect the sortable list to a webserver handling changed positions of your sortable list items.
|
||||
|
||||
## Events
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 150px;">Event type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>SortableList.EVENTS.DRAGSTART</td>
|
||||
<td>This event fires immediately when user started dragging a list element.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SortableList.EVENTS.DRAG</td>
|
||||
<td>This event is fired when user dragged a list element to a new position.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SortableList.EVENTS.DROP</td>
|
||||
<td>This event is fired when user dropped a list element</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SortableList.EVENTS.DROPEND</td>
|
||||
<td>This event is fired when user finished dragging - either fired right after dropping or if "Esc" was pressed during dragging</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Examples
|
||||
|
||||
{{< example>}}
|
||||
<div class="row w-50">
|
||||
<div class="col-md-6">
|
||||
<ul class="list-group my-draggable-list-ex">
|
||||
<li class="list-group-item">
|
||||
<span tabindex="0" role="button" aria-haspopup="true" data-drag-type="move" title="1. Cras justo odio">
|
||||
<i class="fa fa-arrows"></i>
|
||||
</span>
|
||||
1. Cras justo odio
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span tabindex="0" role="button" aria-haspopup="true" data-drag-type="move" title="2. Dapibus ac facilisis in">
|
||||
<i class="fa fa-arrows"></i>
|
||||
</span>
|
||||
2. Dapibus ac facilisis in
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span tabindex="0" role="button" aria-haspopup="true" data-drag-type="move" title="3. Morbi leo risus">
|
||||
<i class="fa fa-arrows"></i>
|
||||
</span>
|
||||
3. Morbi leo risus
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span tabindex="0" role="button" aria-haspopup="true" data-drag-type="move" title="4. Porta ac consectetur ac">
|
||||
<i class="fa fa-arrows"></i>
|
||||
</span>
|
||||
4. Porta ac consectetur ac
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span tabindex="0" role="button" aria-haspopup="true" data-drag-type="move" title="5. Vestibulum at eros">
|
||||
<i class="fa fa-arrows"></i>
|
||||
</span>
|
||||
5. Vestibulum at eros
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#js}}
|
||||
require(
|
||||
[
|
||||
'jquery',
|
||||
'core/sortable_list',
|
||||
],
|
||||
function(
|
||||
$,
|
||||
SortableList
|
||||
) {
|
||||
new SortableList('ul.my-draggable-list-ex');
|
||||
|
||||
$('ul.my-draggable-list-ex > *').on(SortableList.EVENTS.DROP, function(evt, info) {
|
||||
console.log(info);
|
||||
});
|
||||
});
|
||||
{{/js}}
|
||||
{{< /example >}}
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: "Themes"
|
||||
date: 2020-02-03T15:26:15Z
|
||||
draft: false
|
||||
weight: 40
|
||||
---
|
77
admin/tool/componentlibrary/content/moodle/themes/colours.md
Normal file
77
admin/tool/componentlibrary/content/moodle/themes/colours.md
Normal file
|
@ -0,0 +1,77 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Colours"
|
||||
date: 2020-02-04T09:40:32+01:00
|
||||
draft: false
|
||||
weight: 1
|
||||
---
|
||||
|
||||
## The Moodle colour scheme:
|
||||
|
||||
Moodle colours are slighty different from standard Bootstrap colours. Custom moodle colours are usually defined in a theme preset. For example `theme/boost/scss/preset/default.scss`
|
||||
|
||||
{{< example show_markup=false >}}
|
||||
<div class="card-deck">
|
||||
{{< colors.inline >}}
|
||||
{{- range (index $.Site.Data "colors") }}
|
||||
<div class="card mb-2 justify-content-center align-items-center d-flex" style="flex: 0 0 20%; height: 150px">
|
||||
<div class="card-body bg-{{ .name }} w-100" style="height: 100px">
|
||||
</div>
|
||||
<div class="card-footer w-100">
|
||||
<span>{{ .name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{{- end -}}
|
||||
{{< /colors.inline >}}
|
||||
</div>
|
||||
{{< /example >}}
|
||||
|
||||
## The standard Bootstrap colour scheme:
|
||||
|
||||
{{< example show_markup=false >}}
|
||||
<div class="card-deck">
|
||||
{{< colors.inline >}}
|
||||
{{- range (index $.Site.Data "colors") }}
|
||||
<div class="card mb-2 justify-content-center align-items-center d-flex" style="flex: 0 0 20%; height: 150px">
|
||||
<div class="card-body w-100" style="height: 100px; background-color: {{ .hex }}">
|
||||
</div>
|
||||
<div class="card-footer w-100">
|
||||
<span>{{ .name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{{- end -}}
|
||||
{{< /colors.inline >}}
|
||||
</div>
|
||||
{{< /example >}}
|
||||
|
||||
These colours are used throughout Moodle in text, buttons
|
||||
|
||||
{{< example show_markup=false >}}
|
||||
<p>
|
||||
<span class="badge badge-success">Badges</span>
|
||||
</p>
|
||||
<p>
|
||||
<button class="btn btn-success">Buttons</button>
|
||||
</p>
|
||||
<p>
|
||||
<div class="border border-success">Borders</div>
|
||||
</p>
|
||||
|
||||
{{< /example >}}
|
||||
|
||||
## Customizing moodle colours
|
||||
|
||||
Use the $theme-colours Scss array to customize colours in theme/boost/scss/preset/default.scss.
|
||||
|
||||
{{< highlight scss >}}
|
||||
$theme-colors: map-merge((
|
||||
primary: #1177d1,
|
||||
secondary: #ced4da,
|
||||
success: #398439,
|
||||
info: #5bc0de,
|
||||
warning: #f0ad4e,
|
||||
danger: #d43f3a,
|
||||
light: #f8f9fa,
|
||||
dark: #373a3c
|
||||
), $theme-colors);
|
||||
{{< /highlight >}}
|
75
admin/tool/componentlibrary/content/moodle/themes/grids.md
Normal file
75
admin/tool/componentlibrary/content/moodle/themes/grids.md
Normal file
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Grids"
|
||||
descriptions: Using grids in Moodle
|
||||
date: 2020-02-04T09:40:32+01:00
|
||||
draft: false
|
||||
weight: 1
|
||||
---
|
||||
|
||||
Use the bootstrap grid column classes to create responsive grids. Rules to follow:
|
||||
|
||||
* Always wrap rows in a container
|
||||
* Combine column classes to create responsive grids
|
||||
* Keep the context in mind, modals behave different from #region-main
|
||||
* Don't add to much styles to the grid container, us an inner div
|
||||
|
||||
|
||||
{{< example>}}
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
|
||||
<div class="inner h-100 border p-1">
|
||||
Lorem ipsum dolor sit amet
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
|
||||
<div class="inner h-100 border p-1">
|
||||
Lonsectetuer adipiscing elit. Aenean commodo ligula eget dolor.
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
|
||||
<div class="inner h-100 border p-1">
|
||||
Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim.
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
|
||||
<div class="inner h-100 border p-1">
|
||||
ascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu.
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
|
||||
<div class="inner h-100 border p-1">
|
||||
Lretium quis, sem. Nulla consequat massa quis enim.
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
|
||||
<div class="inner h-100 border p-1">
|
||||
Aenean commodo massa quis enim.
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
|
||||
<div class="inner h-100 border p-1">
|
||||
Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem.
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
|
||||
<div class="inner h-100 border p-1">
|
||||
Aenean commodo ligula eget dolor. Aenean massa. Cu quis enim.
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
|
||||
<div class="inner h-100 border p-1">
|
||||
Loltricies nec, pellentesque eu, quis enim.
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
|
||||
<div class="inner h-100 border p-1">
|
||||
Ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{< /example >}}
|
||||
|
||||
If needed
|
|
@ -0,0 +1,76 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Icon Sizes"
|
||||
date: 2020-04-27T09:40:32+01:00
|
||||
draft: false
|
||||
weight: 5
|
||||
---
|
||||
|
||||
Moodle icons are usually rendered using the template ```{{pix}}``` helper.
|
||||
|
||||
For example:
|
||||
|
||||
```{{#pix}}t/up, moodle, {{#str}} up, moodle {{/str}}{{/pix}}```
|
||||
|
||||
which results in
|
||||
|
||||
{{< example show_preview=true >}}
|
||||
<i class="icon fa fa-arrow-up fa-fw " title="Up" aria-label="Up"></i>
|
||||
{{< /example >}}
|
||||
|
||||
## Controlling the icon size
|
||||
|
||||
Use the ```icon-size-x``` classes to control the icon sizes.
|
||||
|
||||
{{< example show_markup=false >}}
|
||||
<div class="d-flex">
|
||||
<div class="icon-size-1 card bg-light mr-2">
|
||||
<div class="card-body d-flex justify-content-center align-items-center">
|
||||
<i class="fa fa-arrow-up icon"></i>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
icon-size-1<br>4px
|
||||
</div>
|
||||
</div>
|
||||
<div class="icon-size-2 card bg-light mr-2">
|
||||
<div class="card-body d-flex justify-content-center align-items-center">
|
||||
<i class="fa fa-arrow-up icon"></i>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
icon-size-2<br>8px
|
||||
</div>
|
||||
</div>
|
||||
<div class="icon-size-3 card bg-light mr-2">
|
||||
<div class="card-body d-flex justify-content-center align-items-center">
|
||||
<i class="fa fa-arrow-up icon"></i>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
icon-size-3<br>16px (default)
|
||||
</div>
|
||||
</div>
|
||||
<div class="icon-size-4 card bg-light mr-2">
|
||||
<div class="card-body d-flex justify-content-center align-items-center">
|
||||
<i class="fa fa-arrow-up icon"></i>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
icon-size-4<br>24px
|
||||
</div>
|
||||
</div>
|
||||
<div class="icon-size-5 card bg-light mr-2">
|
||||
<div class="card-body d-flex justify-content-center align-items-center">
|
||||
<i class="fa fa-arrow-up icon"></i>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
icon-size-5<br>32px
|
||||
</div>
|
||||
</div>
|
||||
<div class="icon-size-6 card bg-light mr-2">
|
||||
<div class="card-body d-flex justify-content-center align-items-center">
|
||||
<i class="fa fa-arrow-up icon"></i>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
icon-size-6<br>40px
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{< /example >}}
|
31
admin/tool/componentlibrary/content/moodle/themes/layout.md
Normal file
31
admin/tool/componentlibrary/content/moodle/themes/layout.md
Normal file
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Layout"
|
||||
description: "Moodle page layouts for themes"
|
||||
date: 2019-12-10T13:53:41+01:00
|
||||
draft: false
|
||||
---
|
||||
|
||||
## High level templates
|
||||
|
||||
Theme layouts are the highest level templates found in Moodle. They construct the Moodle Page users see when interacting with Moodle.
|
||||
|
||||
Layout files define the location of page elements like the primary and secondary navigation, the main content, Moodle blocks and the footer.
|
||||
|
||||
Theme layouts are defined in a themes config.php and themes can serve different layout files depending on the page type, example layouts are
|
||||
|
||||
* frontpage
|
||||
* course page
|
||||
* activity page
|
||||
* secure page
|
||||
* login page
|
||||
|
||||
## Accessibility considerations
|
||||
|
||||
When interacting with a theme the layout needs to be constructed with a logical DOM order: First render the primary navigation, then the secondary navigation then the page content, then the footer.
|
||||
|
||||
## Responsiveness
|
||||
|
||||
Use [Bootstrap grids]({{< docsref "/layout/grid" >}}) to create a responsive design. Make sure the primary and secondary navigation can be found easily on a mobile device.
|
||||
|
||||
Always try themes on all different theme layouts and ensure font-sizes, paddings and margins are used correctly. Especially for frequently used pages like courses and activities.
|
|
@ -0,0 +1,55 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Positioning"
|
||||
description: The use of Bootstraps flexbox utilities to position items on the screen.
|
||||
date: 2020-02-04T09:40:32+01:00
|
||||
draft: false
|
||||
weight: 3
|
||||
---
|
||||
##
|
||||
## Position an single item at the right
|
||||
|
||||
Use the ```.justify-content-end``` class to position on item in a ```.d-flex``` container to the right
|
||||
|
||||
{{< example >}}
|
||||
<div class="d-flex justify-content-end">
|
||||
<button class="btn btn-success">OK</button>
|
||||
</div>
|
||||
{{< /example >}}
|
||||
|
||||
|
||||
## Position on item in a group of items to the right
|
||||
|
||||
Use the ```.ml-auto``` to move the last item in ad ```.d-flex``` container to the right.
|
||||
|
||||
{{< example >}}
|
||||
<div class="d-flex">
|
||||
<button class="btn btn-secondary mr-1">Ha!</button>
|
||||
<button class="btn btn-secondary mr-1">Jay</button>
|
||||
<button class="btn btn-secondary mr-1">Wow</button>
|
||||
<button class="ml-auto btn btn-success">OK</button>
|
||||
</div>
|
||||
{{< /example >}}
|
||||
|
||||
### Center items
|
||||
|
||||
Use the ```align-items-center``` class to align items horizontally in a container.
|
||||
|
||||
{{< example >}}
|
||||
<div class="d-flex align-items-center p-2 bg-light">
|
||||
<div class="bg-success mr-2" style="width: 35px; height: 35px;"></div>
|
||||
<div class="bg-warning mr-2" style="width: 48px; height: 48px;"></div>
|
||||
<div class="bg-info mr-2" style="width: 20px; height: 20px;"></div>
|
||||
</div>
|
||||
{{< /example >}}
|
||||
|
||||
### Middle of the container
|
||||
|
||||
Combine the ```align-items-center``` with the ```justify-content-center``` class to position an element in the middle of a container.
|
||||
|
||||
{{< example >}}
|
||||
<div class="d-flex align-items-center justify-content-center p-3 bg-light" style="height:100px;">
|
||||
<div class="bg-warning mr-2" style="width: 48px; height: 48px;"></div>
|
||||
</div>
|
||||
{{< /example >}}
|
||||
|
59
admin/tool/componentlibrary/content/moodle/themes/spacing.md
Normal file
59
admin/tool/componentlibrary/content/moodle/themes/spacing.md
Normal file
|
@ -0,0 +1,59 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Spacing"
|
||||
description: Moodle spacing
|
||||
date: 2020-02-04T09:40:32+01:00
|
||||
draft: false
|
||||
weight: 4
|
||||
---
|
||||
|
||||
## How it works
|
||||
|
||||
Moodle's spacing classes build on Bootstrap spacing classes which can be set for margins and paddings on different screen breakpoints. Using these classes is preferred over setting custom spacing on UI elements using CSS.
|
||||
|
||||
### example class pt-3
|
||||
|
||||
class: ```pt-3:```
|
||||
|
||||
result: padding-top-three
|
||||
|
||||
css:
|
||||
{{< highlight css >}}
|
||||
.pt-3 {
|
||||
padding-top: 1rem; /** 16px **/
|
||||
}
|
||||
{{< /highlight >}}
|
||||
|
||||
The classes are named using the format `{property}{sides}-{size}` for `xs` and `{property}{sides}-{breakpoint}-{size}` for `sm`, `md`, `lg`, and `xl`.
|
||||
|
||||
### Moodle spacing values
|
||||
|
||||
Moodle add's a 6th spacing value on top of the Bootstrap default spacing.
|
||||
|
||||
* `0` - for classes that eliminate the `margin` or `padding` by setting it to `0`
|
||||
* `1` - (by default) for classes that set the `margin` or `padding` to `$spacer * .25`
|
||||
* `2` - (by default) for classes that set the `margin` or `padding` to `$spacer * .5`
|
||||
* `3` - (by default) for classes that set the `margin` or `padding` to `$spacer`
|
||||
* `4` - (by default) for classes that set the `margin` or `padding` to `$spacer * 1.5`
|
||||
* `5` - (by default) for classes that set the `margin` or `padding` to `$spacer * 2`
|
||||
* `6` - (by default) for classes that set the `margin` or `padding` to `$spacer * 3`
|
||||
* `auto` - for classes that set the `margin` to auto
|
||||
|
||||
### Example of paddings
|
||||
|
||||
{{< example>}}
|
||||
<div class="d-flex align-items-center justify-content-center">
|
||||
<div class="p-6 bg-dark">
|
||||
<div class="p-5 bg-white">
|
||||
<div class="p-4 bg-info">
|
||||
<div class="p-3 bg-success">
|
||||
<div class="p-2 bg-warning">
|
||||
<div class="p-1 bg-danger">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{< /example >}}
|
76
admin/tool/componentlibrary/content/moodle/themes/text.md
Normal file
76
admin/tool/componentlibrary/content/moodle/themes/text.md
Normal file
|
@ -0,0 +1,76 @@
|
|||
---
|
||||
layout: docs
|
||||
title: "Text"
|
||||
description: "Moodle text utility classes"
|
||||
date: 2019-12-10T13:53:41+01:00
|
||||
draft: false
|
||||
---
|
||||
|
||||
## Heading sizes with native heading tags
|
||||
{{< example >}}
|
||||
<h1>h1 heading</h1>
|
||||
<h2>h2 heading</h2>
|
||||
<h3>h3 heading</h3>
|
||||
<h4>h4 heading</h4>
|
||||
<h5>h5 heading</h5>
|
||||
<h6>h6 heading</h6>
|
||||
{{< /example >}}
|
||||
|
||||
## Heading sizes with heading classes
|
||||
|
||||
tip: you can use heading classes to style a native heading tag differently.
|
||||
|
||||
{{< example >}}
|
||||
<p class="h1">h1 heading</p>
|
||||
<p class="h2">h2 heading</p>
|
||||
<h1 class="h3">h3 heading</h1>
|
||||
<p class="h4">h4 heading</p>
|
||||
<p class="h5">h5 heading</p>
|
||||
<p class="h6">h6 heading</p>
|
||||
{{< /example >}}
|
||||
|
||||
## Native text tags
|
||||
|
||||
{{< example >}}
|
||||
<p>You can use the mark tag to <mark>highlight</mark> text.</p>
|
||||
<p><del>This line of text is meant to be treated as deleted text.</del></p>
|
||||
<p><s>This line of text is meant to be treated as no longer accurate.</s></p>
|
||||
<p><ins>This line of text is meant to be treated as an addition to the document.</ins></p>
|
||||
<p><u>This line of text will render as underlined</u></p>
|
||||
<p><small>This line of text is meant to be treated as fine print.</small></p>
|
||||
<p><strong>This line rendered as bold text.</strong></p>
|
||||
<p><em>This line rendered as italicized text.</em></p>
|
||||
{{< /example >}}
|
||||
|
||||
## Custom text tags
|
||||
|
||||
{{< example >}}
|
||||
<p class="text-lowercase">Lowercased text.</p>
|
||||
<p class="text-uppercase">Uppercased text.</p>
|
||||
<p class="font-weight-bold">Bold text.</p>
|
||||
<p class="font-weight-normal">Normal weight text.</p>
|
||||
<p class="font-italic">Italic text.</p>
|
||||
|
||||
<p class="text-muted">
|
||||
Muted text with a <a href="#" class="text-reset">reset link</a>.
|
||||
</p>
|
||||
{{< /example >}}
|
||||
|
||||
## For screenreaders
|
||||
|
||||
<h2 class="sr-only">Title for screen readers</h2>
|
||||
<a class="sr-only-focusable" href="#content">Skip to main content</a>
|
||||
|
||||
## Text truncation
|
||||
|
||||
<!-- Block level -->
|
||||
<div class="row">
|
||||
<div class="col-2 text-truncate">
|
||||
Praeterea iter est quasdam res quas ex communi.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Inline level -->
|
||||
<span class="d-inline-block text-truncate" style="max-width: 150px;">
|
||||
Praeterea iter est quasdam res quas ex communi.
|
||||
</span>
|
|
@ -0,0 +1,13 @@
|
|||
# https://github.com/browserslist/browserslist#readme
|
||||
|
||||
>= 1%
|
||||
last 1 major version
|
||||
not dead
|
||||
Chrome >= 45
|
||||
Firefox >= 38
|
||||
Edge >= 12
|
||||
Explorer >= 10
|
||||
iOS >= 9
|
||||
Safari >= 9
|
||||
Android >= 4.4
|
||||
Opera >= 30
|
Binary file not shown.
After Width: | Height: | Size: 225 KiB |
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
|||
data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MTMiIGhlaWdodD0iNDEzIj48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJyZ2IoMCwgMTg0LCAxNDgpIiAvPjxyZWN0IHg9IjAiIHk9IjYiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjE2IiBvcGFjaXR5PSIwLjExNTMzMzMzMzMzMzMzIiBmaWxsPSIjMjIyIiAvPjxyZWN0IHg9IjAiIHk9IjMzIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSI5IiBvcGFjaXR5PSIwLjA1NDY2NjY2NjY2NjY2NyIgZmlsbD0iI2RkZCIgLz48cmVjdCB4PSIwIiB5PSI1MiIgd2lkdGg9IjEwMCUiIGhlaWdodD0iOCIgb3BhY2l0eT0iMC4wNDYiIGZpbGw9IiMyMjIiIC8+PHJlY3QgeD0iMCIgeT0iNzMiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjE0IiBvcGFjaXR5PSIwLjA5OCIgZmlsbD0iIzIyMiIgLz48cmVjdCB4PSIwIiB5PSI5NCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iOSIgb3BhY2l0eT0iMC4wNTQ2NjY2NjY2NjY2NjciIGZpbGw9IiNkZGQiIC8+PHJlY3QgeD0iMCIgeT0iMTE1IiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSI4IiBvcGFjaXR5PSIwLjA0NiIgZmlsbD0iIzIyMiIgLz48cmVjdCB4PSIwIiB5PSIxMzgiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjkiIG9wYWNpdHk9IjAuMDU0NjY2NjY2NjY2NjY3IiBmaWxsPSIjZGRkIiAvPjxyZWN0IHg9IjAiIHk9IjE1OCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTIiIG9wYWNpdHk9IjAuMDgwNjY2NjY2NjY2NjY3IiBmaWxsPSIjMjIyIiAvPjxyZWN0IHg9IjAiIHk9IjE4OCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iNSIgb3BhY2l0eT0iMC4wMiIgZmlsbD0iI2RkZCIgLz48cmVjdCB4PSIwIiB5PSIyMDUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjgiIG9wYWNpdHk9IjAuMDQ2IiBmaWxsPSIjMjIyIiAvPjxyZWN0IHg9IjAiIHk9IjIyNSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iNyIgb3BhY2l0eT0iMC4wMzczMzMzMzMzMzMzMzMiIGZpbGw9IiNkZGQiIC8+PHJlY3QgeD0iMCIgeT0iMjUwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSI5IiBvcGFjaXR5PSIwLjA1NDY2NjY2NjY2NjY2NyIgZmlsbD0iI2RkZCIgLz48cmVjdCB4PSIwIiB5PSIyNjkiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjE5IiBvcGFjaXR5PSIwLjE0MTMzMzMzMzMzMzMzIiBmaWxsPSIjZGRkIiAvPjxyZWN0IHg9IjAiIHk9IjMwNCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iNSIgb3BhY2l0eT0iMC4wMiIgZmlsbD0iI2RkZCIgLz48cmVjdCB4PSIwIiB5PSIzMTkiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjE1IiBvcGFjaXR5PSIwLjEwNjY2NjY2NjY2NjY3IiBmaWxsPSIjZGRkIiAvPjxyZWN0IHg9IjAiIHk9IjM1MCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTciIG9wYWNpdHk9IjAuMTI0IiBmaWxsPSIjZGRkIiAvPjxyZWN0IHg9IjAiIHk9IjM3NCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iNSIgb3BhY2l0eT0iMC4wMiIgZmlsbD0iI2RkZCIgLz48cmVjdCB4PSIwIiB5PSIzODciIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjYiIG9wYWNpdHk9IjAuMDI4NjY2NjY2NjY2NjY3IiBmaWxsPSIjMjIyIiAvPjxyZWN0IHg9IjAiIHk9IjQwNCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iOSIgb3BhY2l0eT0iMC4wNTQ2NjY2NjY2NjY2NjciIGZpbGw9IiNkZGQiIC8+PHJlY3QgeD0iNiIgeT0iMCIgd2lkdGg9IjE2IiBoZWlnaHQ9IjEwMCUiIG9wYWNpdHk9IjAuMTE1MzMzMzMzMzMzMzMiIGZpbGw9IiMyMjIiIC8+PHJlY3QgeD0iMzMiIHk9IjAiIHdpZHRoPSI5IiBoZWlnaHQ9IjEwMCUiIG9wYWNpdHk9IjAuMDU0NjY2NjY2NjY2NjY3IiBmaWxsPSIjZGRkIiAvPjxyZWN0IHg9IjUyIiB5PSIwIiB3aWR0aD0iOCIgaGVpZ2h0PSIxMDAlIiBvcGFjaXR5PSIwLjA0NiIgZmlsbD0iIzIyMiIgLz48cmVjdCB4PSI3MyIgeT0iMCIgd2lkdGg9IjE0IiBoZWlnaHQ9IjEwMCUiIG9wYWNpdHk9IjAuMDk4IiBmaWxsPSIjMjIyIiAvPjxyZWN0IHg9Ijk0IiB5PSIwIiB3aWR0aD0iOSIgaGVpZ2h0PSIxMDAlIiBvcGFjaXR5PSIwLjA1NDY2NjY2NjY2NjY2NyIgZmlsbD0iI2RkZCIgLz48cmVjdCB4PSIxMTUiIHk9IjAiIHdpZHRoPSI4IiBoZWlnaHQ9IjEwMCUiIG9wYWNpdHk9IjAuMDQ2IiBmaWxsPSIjMjIyIiAvPjxyZWN0IHg9IjEzOCIgeT0iMCIgd2lkdGg9IjkiIGhlaWdodD0iMTAwJSIgb3BhY2l0eT0iMC4wNTQ2NjY2NjY2NjY2NjciIGZpbGw9IiNkZGQiIC8+PHJlY3QgeD0iMTU4IiB5PSIwIiB3aWR0aD0iMTIiIGhlaWdodD0iMTAwJSIgb3BhY2l0eT0iMC4wODA2NjY2NjY2NjY2NjciIGZpbGw9IiMyMjIiIC8+PHJlY3QgeD0iMTg4IiB5PSIwIiB3aWR0aD0iNSIgaGVpZ2h0PSIxMDAlIiBvcGFjaXR5PSIwLjAyIiBmaWxsPSIjZGRkIiAvPjxyZWN0IHg9IjIwNSIgeT0iMCIgd2lkdGg9IjgiIGhlaWdodD0iMTAwJSIgb3BhY2l0eT0iMC4wNDYiIGZpbGw9IiMyMjIiIC8+PHJlY3QgeD0iMjI1IiB5PSIwIiB3aWR0aD0iNyIgaGVpZ2h0PSIxMDAlIiBvcGFjaXR5PSIwLjAzNzMzMzMzMzMzMzMzMyIgZmlsbD0iI2RkZCIgLz48cmVjdCB4PSIyNTAiIHk9IjAiIHdpZHRoPSI5IiBoZWlnaHQ9IjEwMCUiIG9wYWNpdHk9IjAuMDU0NjY2NjY2NjY2NjY3IiBmaWxsPSIjZGRkIiAvPjxyZWN0IHg9IjI2OSIgeT0iMCIgd2lkdGg9IjE5IiBoZWlnaHQ9IjEwMCUiIG9wYWNpdHk9IjAuMTQxMzMzMzMzMzMzMzMiIGZpbGw9IiNkZGQiIC8+PHJlY3QgeD0iMzA0IiB5PSIwIiB3aWR0aD0iNSIgaGVpZ2h0PSIxMDAlIiBvcGFjaXR5PSIwLjAyIiBmaWxsPSIjZGRkIiAvPjxyZWN0IHg9IjMxOSIgeT0iMCIgd2lkdGg9IjE1IiBoZWlnaHQ9IjEwMCUiIG9wYWNpdHk9IjAuMTA2NjY2NjY2NjY2NjciIGZpbGw9IiNkZGQiIC8+PHJlY3QgeD0iMzUwIiB5PSIwIiB3aWR0aD0iMTciIGhlaWdodD0iMTAwJSIgb3BhY2l0eT0iMC4xMjQiIGZpbGw9IiNkZGQiIC8+PHJlY3QgeD0iMzc0IiB5PSIwIiB3aWR0aD0iNSIgaGVpZ2h0PSIxMDAlIiBvcGFjaXR5PSIwLjAyIiBmaWxsPSIjZGRkIiAvPjxyZWN0IHg9IjM4NyIgeT0iMCIgd2lkdGg9IjYiIGhlaWdodD0iMTAwJSIgb3BhY2l0eT0iMC4wMjg2NjY2NjY2NjY2NjciIGZpbGw9IiMyMjIiIC8+PHJlY3QgeD0iNDA0IiB5PSIwIiB3aWR0aD0iOSIgaGVpZ2h0PSIxMDAlIiBvcGFjaXR5PSIwLjA1NDY2NjY2NjY2NjY2NyIgZmlsbD0iI2RkZCIgLz48L3N2Zz4=
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
114
admin/tool/componentlibrary/docspage.php
Normal file
114
admin/tool/componentlibrary/docspage.php
Normal file
|
@ -0,0 +1,114 @@
|
|||
<?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/>.
|
||||
|
||||
/**
|
||||
* Moodle Component Library
|
||||
*
|
||||
* Serves the Hugo docs html pages.
|
||||
*
|
||||
* @package tool_componentlibrary
|
||||
* @copyright 2021 Bas Brands <bas@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . '/../../../config.php');
|
||||
require_once($CFG->dirroot . '/lib/filelib.php');
|
||||
|
||||
require_login();
|
||||
require_capability('moodle/site:configview', context_system::instance());
|
||||
|
||||
if (empty($relativepath)) {
|
||||
$relativepath = get_file_argument();
|
||||
}
|
||||
|
||||
$args = explode('/', ltrim($relativepath, '/'));
|
||||
|
||||
$docs = clean_param($args[0], PARAM_TEXT);
|
||||
$folder = clean_param($args[1], PARAM_TEXT);
|
||||
$section = clean_param($args[2], PARAM_TEXT);
|
||||
|
||||
$docsdir = '/' . $CFG->admin . '/tool/componentlibrary/docs/';
|
||||
$cssfile = '/' . $CFG->admin . '/tool/componentlibrary/hugo/dist/css/docs.css';
|
||||
$docspage = '';
|
||||
|
||||
$validroots = [
|
||||
'bootstrap',
|
||||
'library',
|
||||
'moodle',
|
||||
];
|
||||
|
||||
if (in_array($docs, $validroots)) {
|
||||
$docspage = implode(
|
||||
'/',
|
||||
[
|
||||
$CFG->dirroot,
|
||||
$docsdir,
|
||||
$docs,
|
||||
$folder,
|
||||
$section,
|
||||
'index.html',
|
||||
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$thispageurl = new moodle_url('/admin/tool/componentlibrary/docspage.php');
|
||||
|
||||
$PAGE->set_pagelayout('base');
|
||||
$PAGE->set_url($thispageurl);
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$title = get_string('pluginname', 'tool_componentlibrary');
|
||||
$PAGE->set_heading($title);
|
||||
$PAGE->set_title($title);
|
||||
$PAGE->requires->css($cssfile);
|
||||
$jsonfile = new moodle_url('/admin/tool/componentlibrary/hugo/site/data/my-index.json');
|
||||
$PAGE->requires->js_call_amd('tool_componentlibrary/loader', 'init', ['jsonfile' => $jsonfile->out()]);
|
||||
|
||||
if (get_config('core', 'allowthemechangeonurl')) {
|
||||
$themes = core_component::get_plugin_list('theme');
|
||||
$themes = array_keys($themes);
|
||||
$menuthemes = [];
|
||||
foreach ($themes as $themename) {
|
||||
$actionurl = new moodle_url($thispageurl . $relativepath, ['theme' => $themename]);
|
||||
$menuthemes[] = new action_menu_link_secondary($actionurl, null, $themename);
|
||||
}
|
||||
$thememenu = new action_menu($menuthemes);
|
||||
$thememenu->set_menu_trigger($PAGE->theme->name, 'nav-link');
|
||||
$thememenu->set_owner_selector('change-moodle-theme');
|
||||
$thememenu->set_alignment(\action_menu::TL, \action_menu::BL);
|
||||
$PAGE->set_headingmenu($OUTPUT->render($thememenu));
|
||||
}
|
||||
|
||||
if (!file_exists($docspage)) {
|
||||
$firstpage = new moodle_url('/admin/tool/componentlibrary/docspage.php/library/getting-started/');
|
||||
redirect($firstpage);
|
||||
}
|
||||
|
||||
echo $OUTPUT->header();
|
||||
if (!file_exists($CFG->dirroot . $docsdir)) {
|
||||
echo $OUTPUT->render_from_template('tool_componentlibrary/rundocs', (object) []);
|
||||
exit(0);
|
||||
}
|
||||
// Load the content after the footer that contains the JS for this page.
|
||||
$page = file_get_contents($docspage);
|
||||
$page = str_replace('http://MOODLEROOT', $thispageurl, $page);
|
||||
$page = str_replace('MOODLEIMAGEDIR', new moodle_url('/admin/tool/componentlibrary/content/static'), $page);
|
||||
$filtered = str_replace('MOODLEROOT', $thispageurl, $page);
|
||||
$rooturl = new moodle_url('/');
|
||||
$filtered = str_replace('MOODLESITE', $rooturl->out(), $page);
|
||||
echo $filtered;
|
||||
|
||||
echo $OUTPUT->footer();
|
58
admin/tool/componentlibrary/formfields.php
Normal file
58
admin/tool/componentlibrary/formfields.php
Normal file
|
@ -0,0 +1,58 @@
|
|||
<?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/>.
|
||||
|
||||
/**
|
||||
* Moodle Component Library
|
||||
*
|
||||
* A sample form with most of the available form elements.
|
||||
*
|
||||
* @package tool_componentlibrary
|
||||
* @copyright 2021 Bas Brands <bas@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once('../../../config.php');
|
||||
require_once($CFG->dirroot.'/lib/formslib.php');
|
||||
|
||||
require_login();
|
||||
require_capability('moodle/site:configview', context_system::instance());
|
||||
|
||||
$repeatcount = optional_param('test_repeat', 1, PARAM_INT);
|
||||
|
||||
$PAGE->set_pagelayout('embedded');
|
||||
|
||||
$url = new moodle_url('/admin/tool/componentlibrary/formfields.php');
|
||||
|
||||
$toggles = (object)[];
|
||||
$toggles->defaulturl = $url;
|
||||
$toggles->helpurl = new moodle_url('/admin/tool/componentlibrary/formfields.php', ['help' => 1]);
|
||||
$toggles->requiredurl = new moodle_url('/admin/tool/componentlibrary/formfields.php', ['required' => 1]);
|
||||
$toggles->bothurl = new moodle_url('/admin/tool/componentlibrary/formfields.php', ['help' => 1, 'required' => 1]);
|
||||
$toggles->mixedurl = new moodle_url('/admin/tool/componentlibrary/formfields.php', ['help' => 1, 'required' => 1, 'mixed' => 1]);
|
||||
|
||||
$PAGE->set_url($url);
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
$PAGE->set_heading('Moodle form fields');
|
||||
$PAGE->set_title('Moodle form fields');
|
||||
|
||||
$form = new \tool_componentlibrary\exampleform($url, ['repeatcount' => $repeatcount]);
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
echo $OUTPUT->render_from_template('tool_componentlibrary/moodleformtoggles', $toggles);
|
||||
$form->display();
|
||||
echo $OUTPUT->footer();
|
1101
admin/tool/componentlibrary/hugo/dist/css/docs.css
vendored
Normal file
1101
admin/tool/componentlibrary/hugo/dist/css/docs.css
vendored
Normal file
File diff suppressed because it is too large
Load diff
110
admin/tool/componentlibrary/hugo/dist/css/docs.css.map
vendored
Normal file
110
admin/tool/componentlibrary/hugo/dist/css/docs.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
10
admin/tool/componentlibrary/hugo/scss/_anchor.scss
Normal file
10
admin/tool/componentlibrary/hugo/scss/_anchor.scss
Normal file
|
@ -0,0 +1,10 @@
|
|||
.anchorjs-link {
|
||||
font-weight: 400;
|
||||
color: rgba($link-color, .5);
|
||||
@include transition(color .15s ease-in-out);
|
||||
|
||||
&:hover {
|
||||
color: $link-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
49
admin/tool/componentlibrary/hugo/scss/_callouts.scss
Normal file
49
admin/tool/componentlibrary/hugo/scss/_callouts.scss
Normal file
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// Callouts
|
||||
//
|
||||
|
||||
.bd-callout {
|
||||
padding: 1.25rem;
|
||||
margin-top: 1.25rem;
|
||||
margin-bottom: 1.25rem;
|
||||
border: 1px solid $gray-200;
|
||||
border-left-width: .25rem;
|
||||
@include border-radius();
|
||||
|
||||
h4 {
|
||||
margin-bottom: .25rem;
|
||||
}
|
||||
|
||||
p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
code {
|
||||
@include border-radius();
|
||||
}
|
||||
|
||||
+ .bd-callout {
|
||||
margin-top: -.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
// Variations
|
||||
@mixin bs-callout-variant($color) {
|
||||
border-left-color: $color;
|
||||
|
||||
h4 {
|
||||
color: $color;
|
||||
}
|
||||
}
|
||||
|
||||
.bd-callout-info {
|
||||
@include bs-callout-variant($bd-info);
|
||||
}
|
||||
|
||||
.bd-callout-warning {
|
||||
@include bs-callout-variant($bd-warning);
|
||||
}
|
||||
|
||||
.bd-callout-danger {
|
||||
@include bs-callout-variant($bd-danger);
|
||||
}
|
36
admin/tool/componentlibrary/hugo/scss/_clipboard-js.scss
Normal file
36
admin/tool/componentlibrary/hugo/scss/_clipboard-js.scss
Normal file
|
@ -0,0 +1,36 @@
|
|||
// clipboard.js
|
||||
//
|
||||
// JS-based `Copy` buttons for code snippets.
|
||||
|
||||
.bd-clipboard {
|
||||
position: relative;
|
||||
display: none;
|
||||
float: right;
|
||||
|
||||
+ .highlight {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-clipboard {
|
||||
position: absolute;
|
||||
top: .5rem;
|
||||
right: .5rem;
|
||||
z-index: 10;
|
||||
display: block;
|
||||
padding: .25rem .5rem;
|
||||
@include font-size(.75em);
|
||||
color: $gray-800;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
@include border-radius();
|
||||
|
||||
&:hover {
|
||||
color: $white;
|
||||
background-color: $primary;
|
||||
}
|
||||
}
|
17
admin/tool/componentlibrary/hugo/scss/_colors.scss
Normal file
17
admin/tool/componentlibrary/hugo/scss/_colors.scss
Normal file
|
@ -0,0 +1,17 @@
|
|||
//
|
||||
// Docs color palette classes
|
||||
//
|
||||
|
||||
@each $color, $value in $colors {
|
||||
.swatch-#{$color} {
|
||||
color: color-yiq($value);
|
||||
background-color: #{$value};
|
||||
}
|
||||
}
|
||||
|
||||
@each $color, $value in $grays {
|
||||
.swatch-#{$color} {
|
||||
color: color-yiq($value);
|
||||
background-color: #{$value};
|
||||
}
|
||||
}
|
273
admin/tool/componentlibrary/hugo/scss/_component-examples.scss
Normal file
273
admin/tool/componentlibrary/hugo/scss/_component-examples.scss
Normal file
|
@ -0,0 +1,273 @@
|
|||
// stylelint-disable no-duplicate-selectors
|
||||
|
||||
//
|
||||
// Grid examples
|
||||
//
|
||||
|
||||
.bd-example-row {
|
||||
.row {
|
||||
|
||||
> .col,
|
||||
> [class^="col-"] {
|
||||
padding-top: .75rem;
|
||||
padding-bottom: .75rem;
|
||||
background-color: rgba(86, 61, 124, .15);
|
||||
border: 1px solid rgba(86, 61, 124, .2);
|
||||
}
|
||||
}
|
||||
|
||||
.row + .row {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.bd-example-row-flex-cols .row {
|
||||
min-height: 10rem;
|
||||
background-color: rgba(255, 0, 0, .1);
|
||||
}
|
||||
|
||||
.bd-highlight {
|
||||
background-color: rgba($bd-purple, .15);
|
||||
border: 1px solid rgba($bd-purple, .15);
|
||||
}
|
||||
|
||||
.bd-example-responsive-containers {
|
||||
[class^="container"] {
|
||||
padding-top: .75rem;
|
||||
padding-bottom: .75rem;
|
||||
background-color: rgba(86, 61, 124, .15);
|
||||
border: 1px solid rgba(86, 61, 124, .2);
|
||||
}
|
||||
}
|
||||
|
||||
// Grid mixins
|
||||
.example-container {
|
||||
width: 800px;
|
||||
@include make-container();
|
||||
}
|
||||
|
||||
.example-row {
|
||||
@include make-row();
|
||||
}
|
||||
|
||||
.example-content-main {
|
||||
@include make-col-ready();
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
@include make-col(6);
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
@include make-col(8);
|
||||
}
|
||||
}
|
||||
|
||||
.example-content-secondary {
|
||||
@include make-col-ready();
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
@include make-col(6);
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
@include make-col(4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Docs examples
|
||||
//
|
||||
|
||||
.bd-example {
|
||||
position: relative;
|
||||
padding: 1rem;
|
||||
margin: 1rem (-$grid-gutter-width / 2) 0;
|
||||
border: solid $gray-100;
|
||||
border-width: .2rem 0 0;
|
||||
@include clearfix();
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
padding: 1.5rem;
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
border-width: .2rem;
|
||||
}
|
||||
|
||||
+ .highlight,
|
||||
+ .clipboard + .highlight {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
+ p {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
> .form-control {
|
||||
+ .form-control {
|
||||
margin-top: .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
> .nav + .nav,
|
||||
> .alert + .alert,
|
||||
> .navbar + .navbar,
|
||||
> .progress + .progress {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
> .dropdown-menu {
|
||||
position: static;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
// Images
|
||||
.bd-example {
|
||||
|
||||
> svg + svg,
|
||||
> img + img {
|
||||
margin-left: .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
// Buttons
|
||||
.bd-example {
|
||||
|
||||
> .btn,
|
||||
> .btn-group {
|
||||
margin-top: .25rem;
|
||||
margin-bottom: .25rem;
|
||||
}
|
||||
|
||||
> .btn-toolbar + .btn-toolbar {
|
||||
margin-top: .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
// List groups
|
||||
.bd-example > .list-group {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.bd-example > [class*="list-group-horizontal"] {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
// Navbars
|
||||
.bd-example {
|
||||
|
||||
.fixed-top,
|
||||
.sticky-top {
|
||||
position: static;
|
||||
margin: -1rem -1rem 1rem;
|
||||
}
|
||||
|
||||
.fixed-bottom {
|
||||
position: static;
|
||||
margin: 1rem -1rem -1rem;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
|
||||
.fixed-top,
|
||||
.sticky-top {
|
||||
margin: -1.5rem -1.5rem 1rem;
|
||||
}
|
||||
|
||||
.fixed-bottom {
|
||||
margin: 1rem -1.5rem -1.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pagination
|
||||
.bd-example .pagination {
|
||||
margin-top: .5rem;
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
|
||||
.bd-example-modal {
|
||||
background-color: #fafafa;
|
||||
|
||||
.modal {
|
||||
position: static;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
// Tooltips
|
||||
.tooltip-demo a {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
// Scrollspy demo on fixed height div
|
||||
.scrollspy-example {
|
||||
position: relative;
|
||||
height: 200px;
|
||||
margin-top: .5rem;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.scrollspy-example-2 {
|
||||
position: relative;
|
||||
height: 350px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.bd-example-border-utils {
|
||||
[class^="border"] {
|
||||
display: inline-block;
|
||||
width: 5rem;
|
||||
height: 5rem;
|
||||
margin: .25rem;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
}
|
||||
|
||||
.bd-example-border-utils-0 {
|
||||
[class^="border"] {
|
||||
border: 1px solid $border-color;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Code snippets
|
||||
//
|
||||
|
||||
.highlight {
|
||||
padding: 1rem;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
background-color: $gray-100;
|
||||
-ms-overflow-style: -ms-autohiding-scrollbar;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.bd-content .highlight {
|
||||
margin-right: (-$grid-gutter-width / 2);
|
||||
margin-left: (-$grid-gutter-width / 2);
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.highlight {
|
||||
pre {
|
||||
padding: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
pre code {
|
||||
@include font-size(inherit);
|
||||
color: $gray-900; // Effectively the base text color
|
||||
}
|
||||
}
|
10
admin/tool/componentlibrary/hugo/scss/_componentlibrary.scss
Normal file
10
admin/tool/componentlibrary/hugo/scss/_componentlibrary.scss
Normal file
|
@ -0,0 +1,10 @@
|
|||
.path-admin-tool-componentlibrary {
|
||||
#page-header,
|
||||
#maincontent {
|
||||
display: none;
|
||||
}
|
||||
#region-main {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
}
|
94
admin/tool/componentlibrary/hugo/scss/_content.scss
Normal file
94
admin/tool/componentlibrary/hugo/scss/_content.scss
Normal file
|
@ -0,0 +1,94 @@
|
|||
// stylelint-disable
|
||||
//
|
||||
// Automatically style Markdown-based tables like a Bootstrap `.table`.
|
||||
//
|
||||
|
||||
.bd-content {
|
||||
|
||||
// Hack the sticky header
|
||||
>h2[id],
|
||||
>h3[id],
|
||||
>h4[id] {
|
||||
pointer-events: none;
|
||||
|
||||
&::before {
|
||||
display: block;
|
||||
height: 6rem;
|
||||
margin-top: -6rem;
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
|
||||
// Override Bootstrap defaults
|
||||
>.table {
|
||||
max-width: 100%;
|
||||
margin-bottom: 1.5rem;
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
|
||||
&.table-bordered {
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
&:first-child {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
padding-right: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent breaking of code (e.g., Grunt tasks list)
|
||||
td:first-child>code {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bd-content-title {
|
||||
display: block;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
//
|
||||
// Docs sections
|
||||
//
|
||||
|
||||
.bd-content {
|
||||
>h2:not(:first-child) {
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
>h3 {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
>ul li,
|
||||
>ol li {
|
||||
margin-bottom: .25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.bd-title {
|
||||
margin-bottom: .5rem;
|
||||
@include font-size(3rem);
|
||||
}
|
||||
|
||||
.bd-lead {
|
||||
@include font-size(1.5rem);
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.bd-text-purple {
|
||||
color: $bd-purple;
|
||||
}
|
||||
|
||||
.bd-text-purple-bright {
|
||||
color: $bd-purple-bright;
|
||||
}
|
35
admin/tool/componentlibrary/hugo/scss/_footer.scss
Normal file
35
admin/tool/componentlibrary/hugo/scss/_footer.scss
Normal file
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// Footer
|
||||
//
|
||||
|
||||
.bd-footer {
|
||||
@include font-size(.875rem);
|
||||
color: #63707c;
|
||||
|
||||
a {
|
||||
font-weight: 600;
|
||||
color: $gray-700;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: $link-color;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.bd-footer-links {
|
||||
padding-left: 0;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
|
||||
+ li {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
15
admin/tool/componentlibrary/hugo/scss/_placeholder-img.scss
Normal file
15
admin/tool/componentlibrary/hugo/scss/_placeholder-img.scss
Normal file
|
@ -0,0 +1,15 @@
|
|||
//
|
||||
// Placeholder svg used in the docs.
|
||||
//
|
||||
|
||||
// Remember to update `site/_layouts/examples.html` too if this changes!
|
||||
|
||||
.bd-placeholder-img {
|
||||
@include font-size(1.125rem);
|
||||
text-anchor: middle;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.bd-placeholder-img-lg {
|
||||
@include font-size(3.5rem);
|
||||
}
|
104
admin/tool/componentlibrary/hugo/scss/_sidebar.scss
Normal file
104
admin/tool/componentlibrary/hugo/scss/_sidebar.scss
Normal file
|
@ -0,0 +1,104 @@
|
|||
// stylelint-disable declaration-no-important
|
||||
$navbar-height: 50px;
|
||||
|
||||
.sidebar {
|
||||
line-height: 1.8;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
.sidebar {
|
||||
border-right: 1px solid $border-color;
|
||||
border-bottom: 1px solid $border-color;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar .dropdown-menu .dropdown-item {
|
||||
white-space: normal;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.docs-sidebar ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.docs-sidebar > ul {
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
.docs-sidebar a {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: $body-color;
|
||||
text-decoration: none;
|
||||
padding: .3rem 0.5rem;
|
||||
border-top: solid 1px $border-color;
|
||||
&.dropdown-toggle::after {
|
||||
margin-left: auto;
|
||||
font-size: 14px;
|
||||
color: $gray-400;
|
||||
}
|
||||
}
|
||||
|
||||
.docs-sidebar a:hover {
|
||||
background-color: $gray-200;
|
||||
}
|
||||
|
||||
.docs-sidebar > ul > li li a {
|
||||
padding-left: 1rem;
|
||||
border-top: solid 1px transparent;
|
||||
}
|
||||
|
||||
.docs-sidebar > ul ul > li li a {
|
||||
padding-left: 2rem;
|
||||
border-top: solid 1px transparent;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
.docs-sidebar > ul > li:last-child a {
|
||||
border-bottom: solid 1px $border-color;
|
||||
}
|
||||
}
|
||||
|
||||
.docs-sidebar .active > a {
|
||||
background: $border-color;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.docs-sidebar .slide-menu .has-sub-menu:not(.parent) ul {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.secondnav {
|
||||
z-index: 0;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: calc(100vh - #{$navbar-height});
|
||||
top: $navbar-height;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#TableOfContents > ul {
|
||||
font-size: 90%;
|
||||
padding-left: 0;
|
||||
padding-top: 1rem;
|
||||
border-left: 1px solid $border-color;
|
||||
ul {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
li {
|
||||
display: block;
|
||||
a {
|
||||
display: block;
|
||||
padding: .125rem 1.5rem;
|
||||
color: $body-color;
|
||||
&:hover {
|
||||
color: $primary;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
17
admin/tool/componentlibrary/hugo/scss/_skippy.scss
Normal file
17
admin/tool/componentlibrary/hugo/scss/_skippy.scss
Normal file
|
@ -0,0 +1,17 @@
|
|||
.skippy {
|
||||
display: block;
|
||||
padding: 1em;
|
||||
color: $white;
|
||||
text-align: center;
|
||||
background-color: $bd-purple;
|
||||
outline: 0;
|
||||
|
||||
&:hover {
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
|
||||
.skippy-text {
|
||||
padding: .5em;
|
||||
outline: 1px dotted;
|
||||
}
|
94
admin/tool/componentlibrary/hugo/scss/_syntax.scss
Normal file
94
admin/tool/componentlibrary/hugo/scss/_syntax.scss
Normal file
|
@ -0,0 +1,94 @@
|
|||
// stylelint-disable
|
||||
|
||||
/* NEW Background .chroma { background-color: #f0f0f0; } */
|
||||
/* NEW Error .chroma .err { } */
|
||||
/* NEW LineTableTD .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; } */
|
||||
/* NEW LineTable .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; width: auto; overflow: auto; display: block; } */
|
||||
/* NEW LineHighlight .chroma .hl { display: block; width: 100%; background-color: #ffffcc; } */
|
||||
/* NEW LineNumbersTable .chroma .lnt { margin-right: .4em; padding: 0 .4em; } */
|
||||
/* NEW LineNumbers .chroma .ln { margin-right: .4em; padding: 0 .4em; } */
|
||||
|
||||
/* LiteralStringDelimiter */ .chroma .dl { color: #4070a0; } /* NEW */
|
||||
/* Comment */ .chroma .c { color: #727272; }
|
||||
/* CommentMultiline */ .chroma .c1 { color: #727272; }
|
||||
/* CommentHashbang */ .chroma .ch { font-style: italic; color: #60a0b0; } /* NEW */
|
||||
/* CommentMultiline */ .chroma .cm { color: #727272; }
|
||||
/* CommentPreproc */ .chroma .cp { color: #008085; }
|
||||
/* CommentPreprocFile */ .chroma .cpf { color: #007020; } /* NEW */
|
||||
/* CommentSpecial */ .chroma .cs { color: #727272; }
|
||||
/* GenericDeleted */ .chroma .gd { background-color: #fcc; border: 1px solid #c00; }
|
||||
/* GenericEmph */ .chroma .ge { font-style: italic; }
|
||||
/* GenericHeading */ .chroma .gh { color: #030; }
|
||||
/* GenericInserted */ .chroma .gi { background-color: #cfc; border: 1px solid #0c0; }
|
||||
/* GenericUnderline */ .chroma .gl { text-decoration: underline; } /* NEW */
|
||||
/* GenericOutput */ .chroma .go { color: #aaa; }
|
||||
/* GenericPrompt */ .chroma .gp { color: #009; }
|
||||
/* GenericError */ .chroma .gr { color: #f00; }
|
||||
/* GenericStrong */ .chroma .gs { font-weight: 700; } /* NEW */
|
||||
/* GenericTraceback */ .chroma .gt { color: #9c6; }
|
||||
/* GenericSubheading */ .chroma .gu { color: #030; }
|
||||
/* LiteralNumberIntegerLong */ .chroma .il { color: #c24f19; }
|
||||
/* Keyword */ .chroma .k { color: #069; }
|
||||
/* KeywordConstant */ .chroma .kc { color: #069; }
|
||||
/* KeywordDeclaration */ .chroma .kd { color: #069; }
|
||||
/* KeywordNamespace */ .chroma .kn { color: #069; }
|
||||
/* KeywordPseudo */ .chroma .kp { color: #069; }
|
||||
/* KeywordReserved */ .chroma .kr { color: #069; }
|
||||
/* KeywordType */ .chroma .kt { color: #078; }
|
||||
/* LiteralNumber */ .chroma .m { color: #c24f19; }
|
||||
/* LiteralNumberFloat */ .chroma .mf { color: #c24f19; }
|
||||
/* LiteralNumberBin */ .chroma .mb { color: #40a070; } /* NEW */
|
||||
/* LiteralNumberHex */ .chroma .mh { color: #c24f19; }
|
||||
/* LiteralNumberInteger */ .chroma .mi { color: #c24f19; }
|
||||
/* LiteralNumberOct */ .chroma .mo { color: #c24f19; }
|
||||
/* NameAttribute */ .chroma .na { color: #006ee0; }
|
||||
/* NameBuiltin */ .chroma .nb { color: #366; }
|
||||
/* NameClass */ .chroma .nc { color: #168174; }
|
||||
/* NameDecorator */ .chroma .nd { color: #6b62de; }
|
||||
/* NameException */ .chroma .ne { color: #c00; }
|
||||
/* NameFunction */ .chroma .nf { color: #b715f4; }
|
||||
/* NameEntity */ .chroma .ni { color: #727272; }
|
||||
/* NameLabel */ .chroma .nl { color: #6b62de; }
|
||||
/* NameNamespace */ .chroma .nn { color: #007ca5; }
|
||||
/* NameConstant */ .chroma .no { color: #360; }
|
||||
/* NameTag */ .chroma .nt { color: #2f6f9f; }
|
||||
/* NameVariable */ .chroma .nv { color: #033; }
|
||||
/* Operator */ .chroma .o { color: #555; }
|
||||
/* OperatorWord */ .chroma .ow { color: #000; }
|
||||
/* LiteralString */ .chroma .s { color: #d73038; }
|
||||
/* LiteralStringSingle */ .chroma .s1 { color: #c30; }
|
||||
/* LiteralStringDouble */ .chroma .s2 { color: #c30; }
|
||||
/* LiteralStringAffix */ .chroma .sa { color: #4070a0; } /* NEW */
|
||||
/* LiteralStringBacktick */ .chroma .sb { color: #c30; }
|
||||
/* LiteralStringChar */ .chroma .sc { color: #c30; }
|
||||
/* LiteralStringDoc */ .chroma .sd { font-style: italic; color: #c30; }
|
||||
/* LiteralStringEscape */ .chroma .se { color: #c30; }
|
||||
/* LiteralStringHeredoc */ .chroma .sh { color: #c30; }
|
||||
/* LiteralStringInterpol */ .chroma .si { color: #a00; }
|
||||
/* LiteralStringRegex */ .chroma .sr { color: #337e7e; }
|
||||
/* LiteralStringSymbol */ .chroma .ss { color: #fc3; }
|
||||
/* LiteralStringOther */ .chroma .sx { color: #c30; }
|
||||
/* TextWhitespace */ .chroma .w { color: #bbb; }
|
||||
|
||||
.chroma {
|
||||
.language-bash,
|
||||
.language-sh {
|
||||
&::before {
|
||||
color: #009;
|
||||
content: "$ ";
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
// This is just to work around a Chroma bug;
|
||||
// should be removed when fixed upstream
|
||||
.m {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.language-powershell::before {
|
||||
color: #009;
|
||||
content: "PM> ";
|
||||
user-select: none;
|
||||
}
|
||||
}
|
25
admin/tool/componentlibrary/hugo/scss/_toc.scss
Normal file
25
admin/tool/componentlibrary/hugo/scss/_toc.scss
Normal file
|
@ -0,0 +1,25 @@
|
|||
// stylelint-disable selector-max-type, selector-max-combinators, selector-max-compound-selectors
|
||||
|
||||
.bd-toc nav {
|
||||
padding-top: .125em;
|
||||
padding-bottom: .125em;
|
||||
border-left: .25em solid $gray-200;
|
||||
|
||||
> ul {
|
||||
padding-left: .5rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
> ul > li {
|
||||
display: block;
|
||||
}
|
||||
|
||||
li ul li {
|
||||
margin-bottom: .25rem;
|
||||
list-style-type: disc;
|
||||
}
|
||||
|
||||
a code {
|
||||
font: inherit;
|
||||
}
|
||||
}
|
11
admin/tool/componentlibrary/hugo/scss/_variables.scss
Normal file
11
admin/tool/componentlibrary/hugo/scss/_variables.scss
Normal file
|
@ -0,0 +1,11 @@
|
|||
// stylelint-disable scss/dollar-variable-default
|
||||
|
||||
// Local docs variables
|
||||
$bd-purple: #563d7c;
|
||||
$bd-purple-bright: lighten(saturate($bd-purple, 5%), 15%);
|
||||
$bd-purple-light: lighten(saturate($bd-purple, 5%), 45%);
|
||||
$bd-dark: #2a2730;
|
||||
$bd-download: #ffe484;
|
||||
$bd-info: #5bc0de;
|
||||
$bd-warning: #f0ad4e;
|
||||
$bd-danger: #d9534f;
|
33
admin/tool/componentlibrary/hugo/scss/docs.scss
Normal file
33
admin/tool/componentlibrary/hugo/scss/docs.scss
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*!
|
||||
* Bootstrap Docs (https://getbootstrap.com/)
|
||||
* Copyright 2011-2020 The Bootstrap Authors
|
||||
* Copyright 2011-2020 Twitter, Inc.
|
||||
* Licensed under the Creative Commons Attribution 3.0 Unported License.
|
||||
* For details, see https://creativecommons.org/licenses/by/3.0/.
|
||||
*/
|
||||
|
||||
// Load Bootstrap variables and mixins
|
||||
|
||||
@import "theme/boost/scss/bootstrap/functions";
|
||||
@import "theme/boost/scss/bootstrap/variables";
|
||||
@import "theme/boost/scss/bootstrap/mixins";
|
||||
|
||||
// Load docs components
|
||||
@import "variables";
|
||||
@import "content";
|
||||
@import "skippy";
|
||||
@import "sidebar";
|
||||
@import "toc";
|
||||
@import "footer";
|
||||
@import "component-examples";
|
||||
@import "callouts";
|
||||
@import "colors";
|
||||
@import "clipboard-js";
|
||||
@import "placeholder-img";
|
||||
|
||||
// Load docs dependencies
|
||||
@import "syntax";
|
||||
@import "anchor";
|
||||
|
||||
// Accessibility
|
||||
@import "componentlibrary";
|
29
admin/tool/componentlibrary/hugo/site/data/breakpoints.yml
Normal file
29
admin/tool/componentlibrary/hugo/site/data/breakpoints.yml
Normal file
|
@ -0,0 +1,29 @@
|
|||
- breakpoint: xs
|
||||
abbr: ""
|
||||
name: Extra small
|
||||
min-width: 0px
|
||||
container: ""
|
||||
|
||||
- breakpoint: sm
|
||||
abbr: -sm
|
||||
name: Small
|
||||
min-width: 576px
|
||||
container: 540px
|
||||
|
||||
- breakpoint: md
|
||||
abbr: -md
|
||||
name: Medium
|
||||
min-width: 768px
|
||||
container: 720px
|
||||
|
||||
- breakpoint: lg
|
||||
abbr: -lg
|
||||
name: Large
|
||||
min-width: 992px
|
||||
container: 960px
|
||||
|
||||
- breakpoint: xl
|
||||
abbr: -xl
|
||||
name: Extra large
|
||||
min-width: 1200px
|
||||
container: 1140px
|
16
admin/tool/componentlibrary/hugo/site/data/colors.yml
Normal file
16
admin/tool/componentlibrary/hugo/site/data/colors.yml
Normal file
|
@ -0,0 +1,16 @@
|
|||
- name: primary
|
||||
hex: "#007bff"
|
||||
- name: secondary
|
||||
hex: "#868e96"
|
||||
- name: success
|
||||
hex: "#28a745"
|
||||
- name: danger
|
||||
hex: "#dc3545"
|
||||
- name: warning
|
||||
hex: "#ffc107"
|
||||
- name: info
|
||||
hex: "#17a2b8"
|
||||
- name: light
|
||||
hex: "#f8f9fa"
|
||||
- name: dark
|
||||
hex: "#343a40"
|
File diff suppressed because one or more lines are too long
18
admin/tool/componentlibrary/hugo/site/data/grays.yml
Normal file
18
admin/tool/componentlibrary/hugo/site/data/grays.yml
Normal file
|
@ -0,0 +1,18 @@
|
|||
- name: 100
|
||||
hex: "#f8f9fa"
|
||||
- name: 200
|
||||
hex: "#e9ecef"
|
||||
- name: 300
|
||||
hex: "#dee2e6"
|
||||
- name: 400
|
||||
hex: "#ced4da"
|
||||
- name: 500
|
||||
hex: "#adb5bd"
|
||||
- name: 600
|
||||
hex: "#868e96"
|
||||
- name: 700
|
||||
hex: "#495057"
|
||||
- name: 800
|
||||
hex: "#343a40"
|
||||
- name: 900
|
||||
hex: "#212529"
|
23
admin/tool/componentlibrary/hugo/site/data/icons.yml
Normal file
23
admin/tool/componentlibrary/hugo/site/data/icons.yml
Normal file
|
@ -0,0 +1,23 @@
|
|||
preferred:
|
||||
- name: Font Awesome
|
||||
website: https://fontawesome.com/
|
||||
- name: Feather
|
||||
website: https://feathericons.com/
|
||||
- name: Octicons
|
||||
website: https://octicons.github.com/
|
||||
|
||||
more:
|
||||
- name: Bytesize
|
||||
website: https://github.com/danklammer/bytesize-icons
|
||||
- name: Google Material icons
|
||||
website: https://material.io/resources/icons/
|
||||
- name: Ionicons
|
||||
website: https://ionicons.com/
|
||||
- name: Dripicons
|
||||
website: http://demo.amitjakhu.com/dripicons/
|
||||
- name: Ikons
|
||||
website: http://ikons.piotrkwiatkowski.co.uk/
|
||||
- name: Icons8
|
||||
website: https://icons8.com/
|
||||
- name: icofont
|
||||
website: https://icofont.com/
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue