Developers' Forum

UI blockly plugin

UI blockly plugin

by Ruben Cancho -
Number of replies: 16

Hi Richard,

I'm developing a new UI plugin that integrates Blockly Google library. I read the forum thread where Sergi Garcia exposed the idea and it made me click, as I'm a ICT teacher in secondary education where we use block programming with our students (for example, Scratch and App Inventor).

I followed the guidelines you gave him, implementing the UI plugin API and integrating blockly as a AMD module. Here is the fork with the basic implementation and a screenshot:


My idea is to test it with my students the next course. Internally I save in the textArea the blockly state and the code generated in Python. I'm still figuring out some features, like localization and configuring the available toolbox blocks and categories by question. 

For localization I'm using a templateParams option, but I'd like to be able to configure it only in the prototype, not in each question. Is this possible?

I would like to know if you would be interested to have it integrated in upstream or as a subplugin, and if so what should be improved. Anyway, thank you for developing such a great plugin!

Regards,

Ruben.

In reply to Ruben Cancho

Re: UI blockly plugin

by Richard Lobb -

Hi Ruben

Wow, that's impressive. Congratulations. Unfortunately, though, it doesn't seem to run on my machine as it stands. I cloned your github repo onto my machine and simply replaced my version of coderunner with yours. Was that what you were expecting me to do? When I clear the cache, I get the following JavaScript errors:

Uncaught ReferenceError: goog is not defined
    at /moodle/lib/requirejs.php/1595836404/core/first.js:192
/moodle/lib/requirejs.php/1595836404/media_videojs/loader.js:192 Uncaught ReferenceError: goog is not defined
    at /moodle/lib/requirejs.php/1595836404/media_videojs/loader.js:192
require.min.js:5 Uncaught Error: No define call for media_videojs/loader
http://requirejs.org/docs/errors.html#nodefine
    at makeError (require.min.js:5)
    at Object.completeLoad (require.min.js:5)
    at HTMLScriptElement.onScriptLoad (require.min.js:5)
/moodle/lib/requirejs.php/1595836404/message_popup/notification_popover_controller.js:192 Uncaught ReferenceError: goog is not defined
    at /moodle/lib/requirejs.php/1595836404/message_popup/notification_popover_controller.js:192
require.min.js:5 Uncaught Error: No define call for message_popup/notification_popover_controller
http://requirejs.org/docs/errors.html#nodefine
    at makeError (require.min.js:5)
    at Object.completeLoad (require.min.js:5)
    at HTMLScriptElement.onScriptLoad (require.min.js:5)
/moodle/lib/requirejs.php/1595836404/theme_boost/drawer.js:192 Uncaught ReferenceError: goog is not defined
    at /moodle/lib/requirejs.php/1595836404/theme_boost/drawer.js:192
require.min.js:5 Uncaught Error: No define call for theme_boost/drawer
http://requirejs.org/docs/errors.html#nodefine
    at makeError (require.min.js:5)
    at Object.completeLoad (require.min.js:5)
    at HTMLScriptElement.onScriptLoad (require.min.js:5)
/moodle/lib/requirejs.php/1595836404/theme_boost/loader.js:192 Uncaught ReferenceError: goog is not defined
    at /moodle/lib/requirejs.php/1595836404/theme_boost/loader.js:192
require.min.js:5 Uncaught Error: No define call for theme_boost/loader
http://requirejs.org/docs/errors.html#nodefine
    at makeError (require.min.js:5)
    at Object.completeLoad (require.min.js:5)Finally congratulations on what is certainly a very interesting development effort.
    at HTMLScriptElement.onScriptLoad (require.min.js:5)

and a similar list on every page I load.

Copying your question prototype from the samples folder and trying to create a question of that type also doesn't go well. 

It seems that Google's closure library is required, but I've never used that and I'm not sure how it's meant to be loaded or built. Can you advise what I should do next, please?

To answer your other questions ...

Yes, you should be able to put template parameters into the prototype. The complete set of template parameters for a question is obtained by merging the specific question's parameters with those of the prototype.

I am certainly interested in knowing more about your extension, and playing with it a bit myself. I'm a bit nervous about integrating it into the base CodeRunner plugin, however, as it's yet another thing to be documented, maintained, tested on each new Moodle release, etc. I'm a bit reluctant to get into that, since I'm almost certainly not going to be using blockly myself. However, I have a colleague in our department who's very involved in school computer education, so I'd want to get his opinions on it.

My preference would be to have a separate sub-plugin, distributed via github and maintained independently by you. I'm not sure how to make that work, however. Bits of your subplugin need to go in various different places within coderunner (amd/src, amd/build, samples and language/*). To make that work there needs to be proper sub-plugin API, including an install capability. Again, things might start to get complicated.

I'm also a bit nervous about the implications of having another large JavaScript library running within the Moodle infrastructure. 

But let me mull over the issues later. I'd first like to get it working so I have a better feel for what it can do and how useful and maintainable it would be.

Thank you for such an interesting development.

Richard

In reply to Richard Lobb

Re: UI blockly plugin

by Ruben Cancho -

Hi Richard,

Unfortunately I should have checked more the code before posting here. I've made more changes recently to fix some issues, so maybe if you do a 'git pull' now those errors will hopefully get fixed (crossing fingers here).

Yes, I created a blockly prototype that I import in the CR_PROTOTYPE category and then I create questions selecting the blockly type question type. I'm also using Moodle 3.9 and latest Google Chrome if that helps.

About the params parameter in the loadUi API I read from your documentation:

"The params parameter is a record that allows additional parameters to be passed in, such as those from the question's templateParams field and, in the case of the Ace UI, the 'lang' (language) that the editor is editing."

I checked a little the code and I can see that "params" passed to UI constructor is filled with data-params textArea attribute, but I don't follow where the merge with the prototype is done. Maybe templateParams only inherit from prototype value in the question code?

I understand your nervousness and I'm ok with the subplugin road, no worries. I want to test it more during this course and get it battle tested before any step further. I will also try not to get you more nervous with silly javascript errors ;)

thank you for your interest and support!

Ruben

In reply to Ruben Cancho

Re: UI blockly plugin

by Richard Lobb -

Hi Ruben

Sorry, but I still seem to have the same problems with lots of JavaScript errors like the list I gave earlier on every page. The errors occur as soon as I purge all caches after switching to your version of the code.

I thought I might try to regenerate the build contents from src but when I run grunt, the approved Moodle checker and minimiser, I get an impressive 11,000 odd errors - clearly blockly isn't written to grunt specs! But what I did notice is that there's a build/blockly_coderunner.min.js and a build/block_coderunner.min.js.map but no corresponding blockly_coderunner.js file in the src directory. However, I can't see how that could cause the problems I'm having.

It could be that the problem occurs due to some setting in my development system, but that seems a bit unlikely. Have you tried installing your version of CodeRunner in a clean new install of Moodle?

On other matters ...

Many thanks for drawing my attention to the Moodle subplugin capability - I had never heard of it before! 

Merging of template parameters is done in the PHP code, server side, since it involves both the current question and the prototype, and also requires Twig processing for randomisation. That means that when you add or edit template parameters within the author editing form you have to save the question (.e.g "Save and continue editing") to see the effects. I agree this is a bit clumsy, but it's difficult to avoid.

Richard



In reply to Richard Lobb

Re: UI blockly plugin

by Ruben Cancho -

Hi Richard,

I don't really know what could be happening... I'm sending to your email at UC some teacher credentials to a Moodle site where I installed the fork yesterday. I didn't have any problems installing it from git, and changing the coderunner folder with the new one. My coderunner version was older and forced an upgrade, I also have Javascript cache disabled as a got some problems upgrading from 3.8 to 3.9.

About the blockly_coderunner file is an old file I didn't remember to delete in build, now is done. You are right that blockly isn't grunt friendly, I must do a "grunt --force" to get the files build and I close my eyes to not see those red alerts flashing :)

Ruben

In reply to Ruben Cancho

Re: UI blockly plugin

by Richard Lobb -

Yay! I have it working on my machine :-) 

Turning off Javascript caching was the main thing. But I also had to change the url computation around line 34 in ui_blockly.js to be compatible with my development machine, where URLs begin http://localhost/moodle/...

In order to get a clean grunt run, I also copied toolbox.xml into the blockly folder in build and changed ui_blockly.js to load it from there. I then removed the blockly folder from src.

I don't know much about blockly so I wasn't able to do much. But clearly the basic functionality works and it looks like great fun, Ruben. 

I think the subplugin idea is the way to go, but I haven't had time to look into whether that can be made to work with question types and what I have to do to support it. Let us know about any further developments. I suggest you email me directly with minor tweaks, bug fixes etc but post back here if you have actual developments suitable for others to use.

Thanks again for an interesting and fun development.

In reply to Richard Lobb

Re: UI blockly plugin

by Richard Lobb -
A brief update: I tried breaking the user interfaces out into a set of subplugins but it didn't work. The documentation here, which says they're supported only for activity modules, html editors, local plugins and admin tools, is in fact correct. Code lines 60/61 in component.php provide the proof:

    /** @var array list plugin types that support subplugins, do not add more here unless absolutely necessary */
    protected static $supportsubplugins = array('mod', 'editor', 'tool', 'local');

So, sadly, if looks like subplugins are not the way to go here, at least not for now.

In reply to Richard Lobb

Re: UI blockly plugin

by Mark Brand -
Hi Richard

Please excuse me reviving an old thread, but I thought it might make some sort of sense to keep this together with your earlier exchanges with Ruben. Feel free to rebuke me if I should have started a new thread.

I'm running Moodle 3.3.4+ (sorry, I'm not in a position to upgrade), with cachejs enabled (I believe that's no longer a problem?), and CodeRunner is running perfectly. I've replaced the coderunner question type folder with Ruben's (from the repository linked above), which triggered an upgrade (everything else still works). The blockly prototype question has been installed, as it should. Upon trying to create a new blockly question, the console gives me the error: "No define call for qtype_coderunner/blockly/browser", and the blockly interface is never shown. No other ui_ (graph, ace, html) seems to work after that either. Upon creating another new question, though, the other ui's work again. The problem only occurs when I select blockly as a question type. And the same error is shown when the question is previewed, of course.

I realise that you've probably spent little or no time with this ui since your experimentation over a year ago, but I'm hoping you might be able to share some insight that might get me moving in the right direction. I can see that the "define" being complained about is properly there in ui_blockly.js, but I can't establish why it's not being seen. Any and all advice is appreciated.

Mark
In reply to Mark Brand

Re: UI blockly plugin

by Ruben Cancho -
Hi Mark,

sorry for not maintaining my fork! Being 290 commits behind of master may be the source of your problems...

I'll try to sync in a few weeks and remember how Coderunner worked ;)

Ruben.
In reply to Ruben Cancho

Re: UI blockly plugin

by Mark Brand -
Hi Ruben

Thank you ever so much for your response. Your suggestion sent me to the diff tool. As mentioned, I'm running Moodle 3.3.4+. Therefore my CodeRunner was 3.7.9+ prior to dropping your repository in its place. That did trigger a small upgrade, but I kept a copy of the original coderunner folder, and diff shows me that the changes made (aside from the addition of ui_blockly.js and the blockly folder) were not many. I've been working through each of those in search of something that might account for why my blockly questions don't see a define call for qtype_coderunner/blockly/browser.

Are you able to confirm that your repository was built on Richard's 3.7.9+? A comparison with the next version (4.0.0) shows far more differences, leading me to believe that my assumption is correct. I honestly feel as if it's something small I'm missing here.

Mark
In reply to Mark Brand

Re: UI blockly plugin

by Mark Brand -
Hi Ruben

Upon mustering every inch of debug-fu at my disposal (which is not that much), I've been able to confirm that coderunner makes it at least to the require statement at userinterfacewrapper.js:269, but doesn't seem to make it into the constructor at ui_blockly.js:12. As the error message has been telling me all along, it doesn't seem to be able to resolve 'qtype_coderunner/blockly/browser'. I've been tinkering with require.config's path directive, but to no avail thus far. I haven't yet figured out how to determine whether the module definition at blockly/browser.js:4 is being missed between all of the other conditionals. That seems to me to be the most promising line of enquiry at the moment. If my blundering causes you to have any insights... please do share.

Mark
In reply to Mark Brand

Re: UI blockly plugin

by Richard Lobb -
I'm going to have to leave you in Ruben's hands, Mark, as it's his fork of CodeRunner and my latest version has diverged significantly from his. Also, it's the first week of a new semester here and I have a class of 1000 students, of which around 12% are having to self-isolate due to having COVID or being close contacts. This is keeping me busy.

The only comment I have is that I think Moodle has changed how it is handling AMD module JavaScript caching. I haven't looked into the changes but it seems I now have to run grunt for my JavaScript source changes to have any effect. Have you run grunt, so that the build directory is up to date? Also, you'll probably need to add the 'force' flag to the grunt run, since it's now much fussier than it used to be.

Good luck guys!
In reply to Richard Lobb

Re: UI blockly plugin

by Mark Brand -
Thank you Richard. Your comments are appreciated, all the more under the circumstances. The below is not intended to take up any more of your time, but rather just to respond to the questions you raise, and hopefully head off any effort expended on red-herrings.

I was running your CodeRunner 3.7.9+, since it's a Moodle 3.3.4+. A diff showed that Ruben's master branch varies from your clean CR 3.7.9+ in very clear, and dare I say, understandable ways. And I'm working on the assumption that this did work at some point for somebody. I strongly suspect that I'm fighting some sort of quirk on my system, but it would have to be a quirk that hasn't manifested anywhere else. This despite running CR for months, and being quite progressive in testing its capabilities. My biggest obstacle, as always, is my own ignorance (I've just learned about UMD... boy, do I feel silly about my earlier comment). I have succeeded in adding AMD modules to other Moodle question types, and these are all still working. CR's ui_graph is working perfectly, which I suspect is the closest comparison? And ace is doing fine too.

My immediate challenge is to get Moodle to see the define in blockly/browser.js. I am not running in developer mode. After every change, I manually run grunt in the amd folder (with no flags), which writes 15 files without error. I then flush both Moodle and browser caches and test. At one point, I started making changes to minified code directly (in build), essentially to verify that my cache cleansing was effective. I've fiddled with pure Blockly AMD examples (independent of Moodle and CR), to satisfy myself that I understand what is required.

I've been ruminating on whether I need to grunt the blockly subfolder as well. Ruben supplies a minified version in his build/blockly folder, but I see that's not being touched by my grunt in the amd folder. Not that I'm needing to change anything in the blockly folder, but I did wonder about this. I'm also considering relocating all of the blockly files to either directly in src and build, or in the root of coderunner (as for ace). At this stage, I'm grabbing at straws. But it's not something I haven't experienced many, many times before.

Thank you both for sharing your insights, and moreover for your respective contributions to keeping every day exciting! I really am looking forward to seeing this all come together.
In reply to Mark Brand

Re: UI blockly plugin

by Richard Lobb -
OK, so it's the weekend and I do some recreational programming in weekends (though I'll probably regret this) ...

Here's what I did:
  1. I copied the Ruben's blockly plugin code (ui_blockly.js plus the blockly folder) into the AMD src folder of my development system (CodeRunner version 4.2.3),
  2. Turned off JS caching.
  3. Did a grunt --force. On the first run this took ages to process blockly (10 - 20 mins??) but it did eventually result in a blockly folder in the build folder containing all the minimised blockly code. [Note: on subsequent runs, when all I had done was edit ui_blockly.js, I killed grunt as soon as it had processed the changed file.]
  4. Tried creating a Python question but customised to use blockly UI (not knowing what was meant to happen - just exploring).
 I got an error message that loadBlockly was undefined. It turned out that the function definition was mis-positioned in the code and was being called before it was defined. I repositioned it. Then got a mostly useless blockly window with no toolbox. Discovered from reading the code that the toolbox is meant to be supplied as a template parameter. But template parameters are no longer provided to UI plugins (as of CodeRunner 4.0 I think): they need to instead use UI-params. For this you should define ui_blockly.json but I was fast losing enthusiasm. So instead I found an example of a toolbox definition in javascript on the web and just crudely pasted it into ui_blockly.js. That then let me create the following (which doesn't run, you'll note).
BLockly snapshot

I'm not sure what this proves, however, as I'm using CodeRunner 4.2.3 and you're on 3.7.9. But apart from the issue of template params having turned into UI params, it does suggest that your problems probably aren't the result of changes to either Moodle or CodeRunner. The minimised blockly code in build may actually be required?

I attached my hacked-at ui_blockly.js file.

You do have a toolbox template parameter defined, I assume?

Sorry but that's all I have to offer. My impression is that quite a lot of work is needed to knock this into shape and I recommend you wait till Ruben has pushed a more recent working version.
In reply to Richard Lobb

Re: UI blockly plugin

by Mark Brand -
Richard

Thank you, sincerely and deeply, for the trouble you've taken to nudge me along. You made me laugh out loud when you mentioned "recreational programming". Your effort is appreciated, honestly. I'll soldier on. Wishing you a properly recreational weekend.

Mark
In reply to Mark Brand

Re: UI blockly plugin

by Mark Brand -
Hello Richard and Ruben

I am ecstatic to report that I've managed to get it working. Yes, there will probably be some speedbumps, but I'm thrilled at the prospect of being able to introduce this into my teaching. In case you're curious, Richard: it'll serve to support my teaching of an entirely paper-based first course in programming principles. Really basic stuff, and I think this is the way to make it come alive, whilst simultaneously leveraging all the Moodle benefits. Thank you Ruben for connecting the dots, and for the all the work that must have gone into prototyping this. And my appreciation for CodeRunner just blooms day-by-day, Richard. Thank you both.

So, the key insight turned out to be this: https://tracker.moodle.org/browse/MDL-66192. In my version, at least, Moodle refused to deal with a subfolder beneath src. I had to dump the blockly code directly into coderunner's src, and rebase the references in ui_blockly.js. Also in ui_blockly.js, I found that loadBlockly_() was being invoked before it had been defined. That just needed switching around. That was the gist of it, aside from an obsession with flushing Moodle cache and browser cache after every grunt (which ran without errors, by the way). The result is not pretty, I agree, but it works. It seems that a neater solution is possible once I'm allowed to upgrade the Moodle server.

Now to see how to whittle down the toolbox, and to start writing lots and lots of questions! Once again, my deepest thanks to you both.
In reply to Mark Brand

Re: UI blockly plugin

by Richard Lobb -
Well done Mark! Good to hear. It's nice to have another happy camper and to hear your passion for teaching shining through. Enjoy!