diff --git a/example.json b/example.json
index e09aecf..dbc2d95 100644
--- a/example.json
+++ b/example.json
@@ -4,6 +4,20 @@
"_debugFile": ""
}
+// course.json - _globals._extensions
+"_devtools": {
+ "_navButton": {
+ "ariaLabel": "Developer tools",
+ "_navOrder": 9000,
+ "_showLabel": true,
+ "navLabel": "Dev Tools"
+ },
+ "_navTooltip": {
+ "_isEnabled": true,
+ "text": "Developer tools"
+ }
+}
+
/*
_debugFile example (e.g. dev.json)
diff --git a/js/adapt-devtools.js b/js/adapt-devtools.js
index 85e52d8..7b3599e 100644
--- a/js/adapt-devtools.js
+++ b/js/adapt-devtools.js
@@ -5,6 +5,10 @@ import wait from 'core/js/wait';
import logging from 'core/js/logging';
import location from 'core/js/location';
import AdaptModel from 'core/js/models/adaptModel';
+import NavigationButtonModel from 'core/js/models/NavigationButtonModel';
+import NavigationButtonView from 'core/js/views/NavigationButtonView';
+import navigation from 'core/js/navigation';
+import tooltips from 'core/js/tooltips';
import DevtoolsModel from './devtools-model';
import PassHalfFail from './pass-half-fail';
import ToggleBanking from './toggle-banking';
@@ -377,44 +381,37 @@ class DevtoolsView extends Backbone.View {
}
}
-class DevtoolsNavigationView extends Backbone.View {
+class DevtoolsNavigationButtonView extends NavigationButtonView {
- initialize () {
- this.render = this.render.bind(this);
- const template = Handlebars.templates.devtoolsNavigation;
- this.$el = $(template());
- $('html').addClass('devtools-enabled').toggleClass('devtools-extended', Adapt.devtools.get('_extended'));
- if (this.$el.is('a') || this.$el.is('button')) this.$el.on('click', this.onDevtoolsClicked.bind(this));
- else this.$el.find('a, button').on('click', this.onDevtoolsClicked.bind(this));
- this.listenTo(Adapt, 'pageView:postRender menuView:postRender', this.onContentRendered);
- // ensure render occurs at least once (_isReady will not change to true on menus that exclude content objects)
- this.listenToOnce(Adapt, 'pageView:postRender menuView:postRender', this.render);
- }
-
- render () {
- $('.nav__inner').append(this.$el);
- return this;
+ events () {
+ return {
+ click: 'onDevtoolsClicked'
+ };
}
- remove () {
- this.$el.remove();
- this.stopListening();
- return this;
+ static get template() {
+ return 'devtoolsNavigationButton.jsx';
}
- deferredRender () {
- _.defer(this.render);
+ attributes () {
+ return {
+ ...super.attributes(),
+ 'data-tooltip-id': this.model.get('_id'),
+ 'aria-haspopup': 'dialog'
+ };
}
- onContentRendered (view) {
- if (view.model.get('_id') === location._currentId) {
- this.stopListening(view.model, 'change:_isReady', this.deferredRender);
- this.listenToOnce(view.model, 'change:_isReady', this.deferredRender);
- }
+ initialize (options) {
+ super.initialize(options);
+ this.listenTo(Adapt, { remove: this.remove });
+ tooltips.register({
+ _id: this.model.get('_id'),
+ ...this.model.get('_navTooltip') || {}
+ });
}
onDevtoolsClicked (event) {
- if (event && event.preventDefault) event.preventDefault();
+ event.preventDefault();
drawer.openCustomView(new DevtoolsView().$el, false);
}
@@ -426,13 +423,37 @@ Adapt.once('courseModel:dataLoaded', () => {
function initNavigationView() {
if (!Adapt.devtools.get('_isEnabled')) return;
- if (navigationView) navigationView.remove();
- navigationView = new DevtoolsNavigationView();
+ if (navigationView) navigation.removeButton(navigationView);
+ $('html').addClass('devtools-enabled').toggleClass('devtools-extended', Adapt.devtools.get('_extended'));
+ const devtoolsGlobals = Adapt.course.get('_globals')?._extensions?._devtools ?? {};
+ const {
+ ariaLabel = 'Developer tools',
+ _navOrder = 9000,
+ _showLabel = true,
+ navLabel = 'Dev Tools'
+ } = devtoolsGlobals._navButton ?? {};
+ const { _navTooltip = {} } = devtoolsGlobals;
+ const model = new NavigationButtonModel({
+ _id: 'devtools',
+ _order: _navOrder,
+ _showLabel,
+ _classes: 'nav__devtools-btn devtools__nav-btn',
+ _iconClasses: 'icon-cog',
+ _role: 'button',
+ ariaLabel: ariaLabel || navLabel,
+ text: navLabel,
+ _navTooltip
+ });
+ navigationView = new DevtoolsNavigationButtonView({ model });
+ navigation.addButton(navigationView);
}
Adapt.once('adapt:initialize devtools:enable', () => {
+ Adapt.on({
+ 'router:contentObject': initNavigationView,
+ 'app:languageChanged': initNavigationView
+ });
initNavigationView();
- Adapt.on('app:languageChanged', initNavigationView);
});
data.on('loaded', async () => {
diff --git a/less/devtools.less b/less/devtools.less
index 5a5cdc4..c826f58 100644
--- a/less/devtools.less
+++ b/less/devtools.less
@@ -1,10 +1,4 @@
.devtools {
- // Nav icons
- // --------------------------------------------------
- &__nav-btn .icon {
- .icon-cog;
- }
-
// Items
// --------------------------------------------------
&__item {
diff --git a/properties.schema b/properties.schema
index cc30ca6..6aa1046 100644
--- a/properties.schema
+++ b/properties.schema
@@ -1,26 +1,26 @@
{
- "type":"object",
+ "type": "object",
"$schema": "http://json-schema.org/draft-04/schema",
"id": "http://jsonschema.net",
- "required":false,
- "properties":{
+ "required": false,
+ "properties": {
"pluginLocations": {
- "type":"object",
- "required":true,
- "properties":{
+ "type": "object",
+ "required": true,
+ "properties": {
"config": {
- "type":"object",
+ "type": "object",
"properties": {
"_devtools": {
- "type":"object",
- "required":false,
+ "type": "object",
+ "required": false,
"legend": "Dev tools",
- "properties":{
+ "properties": {
"_isEnabled": {
- "type":"boolean",
- "required":false,
+ "type": "boolean",
+ "required": false,
"title": "Show dev tools in nav bar",
- "inputType": { "type": "Boolean", "options": [false, true]},
+ "inputType": { "type": "Boolean", "options": [false, true] },
"validators": [],
"help": "Set to true to show 'dev tools' in the navigation bar. Remember to disable/uninstall before going live!"
}
@@ -29,19 +29,19 @@
}
},
"course": {
- "type":"object"
+ "type": "object"
},
"contentobject": {
- "type":"object"
+ "type": "object"
},
"article": {
- "type":"object"
+ "type": "object"
},
"block": {
- "type":"object"
+ "type": "object"
},
"component": {
- "type":"object"
+ "type": "object"
}
}
}
diff --git a/schema/course.schema.json b/schema/course.schema.json
new file mode 100644
index 0000000..844e3f1
--- /dev/null
+++ b/schema/course.schema.json
@@ -0,0 +1,87 @@
+{
+ "$anchor": "devtools-course",
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "type": "object",
+ "$patch": {
+ "source": {
+ "$ref": "course"
+ },
+ "with": {
+ "properties": {
+ "_globals": {
+ "type": "object",
+ "default": {},
+ "properties": {
+ "_extensions": {
+ "type": "object",
+ "default": {},
+ "properties": {
+ "_devtools": {
+ "type": "object",
+ "title": "Dev Tools",
+ "default": {},
+ "properties": {
+ "_navButton": {
+ "type": "object",
+ "title": "Navigation button",
+ "default": {},
+ "properties": {
+ "ariaLabel": {
+ "type": "string",
+ "title": "Navigation button aria label",
+ "default": "Developer tools",
+ "_adapt": {
+ "translatable": true
+ }
+ },
+ "_navOrder": {
+ "type": "number",
+ "title": "Navigation bar order",
+ "description": "Determines the order in which the button is displayed in the navigation bar. Negative numbers (e.g. -100) are left-aligned. Positive numbers (e.g. 100) are right-aligned.",
+ "default": 9000
+ },
+ "_showLabel": {
+ "type": "boolean",
+ "title": "Enable navigation bar button label",
+ "default": true
+ },
+ "navLabel": {
+ "type": "string",
+ "title": "Navigation bar button label",
+ "default": "Dev Tools",
+ "_adapt": {
+ "translatable": true
+ }
+ }
+ }
+ },
+ "_navTooltip": {
+ "type": "object",
+ "title": "Navigation tooltip",
+ "default": {},
+ "properties": {
+ "_isEnabled": {
+ "type": "boolean",
+ "title": "Enable tooltip for navigation button",
+ "default": true
+ },
+ "text": {
+ "type": "string",
+ "title": "Tooltip text",
+ "default": "Developer tools",
+ "_adapt": {
+ "translatable": true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/templates/devtoolsNavigation.hbs b/templates/devtoolsNavigation.hbs
deleted file mode 100644
index b8532eb..0000000
--- a/templates/devtoolsNavigation.hbs
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/templates/devtoolsNavigationButton.jsx b/templates/devtoolsNavigationButton.jsx
new file mode 100644
index 0000000..5a3be6a
--- /dev/null
+++ b/templates/devtoolsNavigationButton.jsx
@@ -0,0 +1,26 @@
+import React from 'react';
+import { classes, compile } from 'core/js/reactHelpers';
+
+export default function DevtoolsNavigationButton(props) {
+ const {
+ text,
+ _iconClasses
+ } = props;
+
+ return (
+ <>
+
+
+ >
+ );
+}