Difference between revisions of "Widget:CodeExplorer"

From Coder Merlin
(7 intermediate revisions by one other user not shown)
Line 1: Line 1:
<noinclude>
<noinclude>
Parameters:
Parameters:
;userName: The current user's username
;userName: string: The current user's username
;uniqueID: integer: id for editor, must be unique per page
;sessionID: string: The ID of the current user's session
;experienceID: string: The experienceID of the page from which the widget is invoked
;codeExplorerGroupID: string: The code explorer group.  If empty, the submit button will be disabled.
;exerciseID: integer: exercise id for editor, must be unique per page
;width: integer|string: percentage (as string, e.g. "100%" or integer size in pixels), null for no change (full width)
;width: integer|string: percentage (as string, e.g. "100%" or integer size in pixels), null for no change (full width)
;height: integer|string: percentage (as string, e.g. "100%" or integer size in pixels), null for no change (~10 lines)
;height: integer|string: percentage (as string, e.g. "100%" or integer size in pixels), null for no change (~10 lines)
Line 15: Line 18:
{{#widget:CodeExplorer
{{#widget:CodeExplorer
|userName=john-williams
|userName=john-williams
|uniqueID=10
|sessionID=qh0ubrrme911kcg7db0i0ec6lct94h7f
|experienceID=W1020.23
|codeExplorerGroupID=WTRS-8527
|exerciseID=10
|width=null
|width=null
|height=null
|height=null
Line 29: Line 35:
</noinclude>
</noinclude>


<includeonly><form action="" id="codeEditorForm<!--{$uniqueID|validate:int}-->">
<includeonly>
<form action="" id="codeEditorForm<!--{$exerciseID|validate:int}-->">
     <div class="merlin-code-explorer-container">
     <div class="merlin-code-explorer-container">
     <div class="merlin-code-explorer-banner">
     <div class="merlin-code-explorer-banner">
         <img class="merlin-code-explorer-banner-merlin-icon" src="/wiki/resources/assets/MerlinRoundIcon.png" />
         <img class="merlin-code-explorer-banner-merlin-icon" src="/wiki/resources/assets/MerlinRoundIcon.png" />
         <span class="merlin-code-explorer-banner-text">CoderMerlin™ Code Explorer</span>
         <span class="merlin-code-explorer-banner-text">CoderMerlin™ Code Explorer: <!--{$experienceID}--> (<!--{$exerciseID}-->)</span>
         <img class="merlin-code-explorer-banner-language-icon" src="/wiki/images/thumb/3/3b/Swift-og.png/600px-Swift-og.png" />
         <img class="merlin-code-explorer-banner-language-icon" src="/wiki/images/thumb/3/3b/Swift-og.png/600px-Swift-og.png" />
     </div>
     </div>
     <div class="merlin-code-explorer-code-panel">
     <div class="merlin-code-explorer-code-panel">
         <textarea id="codeEditorTextArea<!--{$uniqueID|validate:int}-->"><!--{$initialCode}--></textarea>
         <textarea id="codeEditorTextArea<!--{$exerciseID|validate:int}-->"><!--{$initialCode}--></textarea>
         <script>
         <script>
             var codeEditor<!--{$uniqueID|validate:int}-->;
             var codeEditor<!--{$exerciseID|validate:int}-->;
             window.addEventListener('load', (event) => {
             window.addEventListener('load', (event) => {
                 codeEditor<!--{$uniqueID|validate:int}--> = CodeMirror.fromTextArea(document.getElementById('codeEditorTextArea<!--{$uniqueID|validate:int}-->'),
                 codeEditor<!--{$exerciseID|validate:int}--> = CodeMirror.fromTextArea(document.getElementById('codeEditorTextArea<!--{$exerciseID|validate:int}-->'),
                     {
                     {
                         keyMap: "emacs",
                         keyMap: "emacs",
Line 50: Line 57:
                     }
                     }
                 );
                 );
                 codeEditor<!--{$uniqueID|validate:int}-->.setSize("<!--{$width}-->", "<!--{$height}-->");
                // Set size
                 codeEditor<!--{$exerciseID|validate:int}-->.setSize("<!--{$width}-->", "<!--{$height}-->");


                // Determine if submit button is enabled, if not, disable
                var isSubmitEnabled = '<!--{$codeExplorerGroupID|strip}-->'.length > 0;
                if (isSubmitEnabled) {
                    var submitButton = $("#codeEditorSubmitButton<!--{$exerciseID|validate:int}-->");
                    submitButton.prop("value", "Submit to <!--{$codeExplorerGroupID|strip}-->");               
                } else {
                    var submitButton = $("#codeEditorSubmitButton<!--{$exerciseID|validate:int}-->");
                    submitButton.attr("disabled", true);
                    submitButton.css("background-color", "gray");
                }
                 // Attach handler to form                                                                                                                                                                                                                                                                   
                 // Attach handler to form                                                                                                                                                                                                                                                                   
                 $("#codeEditorForm<!--{$uniqueID|validate:int}-->").submit(function(event) {
                 $("#codeEditorForm<!--{$exerciseID|validate:int}-->").submit(function(event) {


                     // Suppress standard submission                                                                                                                                                                                                                                                         
                     // Suppress standard submission                                                                                                                                                                                                                                                         
                     event.preventDefault();
                     event.preventDefault();


                     // Disable submit button
                     // Disable buttons
                     var submitButton = $("#codeEditorSubmitButton<!--{$uniqueID|validate:int}-->");
                    var executeButton = $("#codeEditorExecuteButton<!--{$exerciseID|validate:int}-->");
                     var submitButton = $("#codeEditorSubmitButton<!--{$exerciseID|validate:int}-->");
                    var executeButtonBackgroundColor = executeButton.css("background-color");
                     var submitButtonBackgroundColor = submitButton.css("background-color");
                     var submitButtonBackgroundColor = submitButton.css("background-color");
                    executeButton.attr("disabled", true);
                    executeButton.css("background-color", "gray");
                     submitButton.attr("disabled", true);
                     submitButton.attr("disabled", true);
                     submitButton.css("background-color", "gray");
                     submitButton.css("background-color", "gray");


                     // Clear output
                     // Clear output
                     $("#codeEditorCombinedOutput<!--{$uniqueID|validate:int}-->").empty();
                     $("#codeEditorCombinedOutput<!--{$exerciseID|validate:int}-->").empty();


                     // Submit form via POST   
                     // Submit form via POST   
                    var username = "<!--{$userName}-->".toLowerCase();
                    var sessionID =  "<!--{$sessionID}-->"
                     var url = (subdomain() == "stg") ?  
                     var url = (subdomain() == "stg") ?  
                         "https://language-server-stg.codermerlin.com/execute" :
                         "https://language-server-stg.codermerlin.com/" :
                         "https://language-server.codermerlin.com/execute";                     
                         "https://language-server.codermerlin.com/";  
 
                     switch (event.target.submitter) {
                    var response = $.post(url, {
                        case "execute":
                         "username": "<!--{$userName}-->",
                            url += "experiences/" + "<!--{$experienceID}-->/" + "exercises/" + "<!--{$exerciseID}-->" + "/executions";
                         "experienceID": "W1001",
                            break;
                        "exerciseID": 10,
                         case "submit":
                         "sourceCodeLanguage": "swift",
                            url += "codeExplorerGroups/" + "<!--{$codeExplorerGroupID}-->/" + "experiences/" + "<!--{$experienceID}-->/" + "exercises/" + "<!--{$exerciseID}-->";
                        "sourceCode": codeEditor<!--{$uniqueID|validate:int}-->.getValue()
                            break;
                    }
                    console.log(url);
                    var response = $.ajax({
                         type: "POST",
                        url,
                        headers: {
                            "username": username,
                            "sessionID": sessionID
                        },
                         data: {
                            "sourceCodeLanguage": "swift",
                            "sourceCode": codeEditor<!--{$exerciseID|validate:int}-->.getValue()
                        },
                        timeout: 6000,
                        error: function(jqXHR, textStatus, errorThrown) {
                            // Display error
                            $("#codeEditorCombinedOutput<!--{$exerciseID|validate:int}-->").append("<span class='merlin-code-explorer-combined-output-error'>" +
                                "Failed to complete operation." +
                                "</span><br/>");
                            console.log(textStatus + " " + errorThrown);
                            // Re-enable buttons
                            executeButton.attr("disabled", false);
                            executeButton.css("background-color", executeButtonBackgroundColor);
                            if (isSubmitEnabled) {
                                submitButton.attr("disabled", false);
                                submitButton.css("background-color", submitButtonBackgroundColor);
                            }   
                        }
                     });
                     });


                     // Collect response data                                                                                                                                                                                                                                                               
                     // Collect response data                                                                                                                                                                                                                                                               
                     response.done(function(data) {
                     response.done(function(data) {
                         var executionCodeResponse = $(data)[0];
                         var executionCodeResponse = JSON.parse(data);
                         var standardError = consoleToHTML(executionCodeResponse.standardError);
                         var standardError = consoleToHTML(executionCodeResponse.standardError);
                         var standardOutput = consoleToHTML(executionCodeResponse.standardOutput);
                         var standardOutput = consoleToHTML(executionCodeResponse.standardOutput);
Line 101: Line 155:
                                 errorClass = "merlin-code-explorer-combined-output-error";
                                 errorClass = "merlin-code-explorer-combined-output-error";
                             };
                             };
                             $("#codeEditorCombinedOutput<!--{$uniqueID|validate:int}-->").append("<span class='" + errorClass + "'>" + errorLine + "</span><br/>");
                             $("#codeEditorCombinedOutput<!--{$exerciseID|validate:int}-->").append("<span class='" + errorClass + "'>" + errorLine + "</span><br/>");
                         };
                         };
                         $("#codeEditorCombinedOutput<!--{$uniqueID|validate:int}-->").append(standardOutput);
                         $("#codeEditorCombinedOutput<!--{$exerciseID|validate:int}-->").append(standardOutput);


                         // Re-enable submit button
                         // Re-enable buttons
                         submitButton.attr("disabled", false);
                         executeButton.attr("disabled", false);
                        submitButton.css("background-color", submitButtonBackgroundColor);
                        executeButton.css("background-color", executeButtonBackgroundColor);
                        if (isSubmitEnabled) {
                            submitButton.attr("disabled", false);
                            submitButton.css("background-color", submitButtonBackgroundColor);
                        }
                       });
                       });
                 });
                 });
Line 114: Line 172:
     </div>
     </div>
     <div class="merlin-code-explorer-control-panel">
     <div class="merlin-code-explorer-control-panel">
         <input id="codeEditorSubmitButton<!--{$uniqueID|validate:int}-->" class="merlin-code-explorer-run-button" type="submit" value="Run" />
        <input id="codeEditorExecuteButton<!--{$exerciseID|validate:int}-->" class="merlin-code-explorer-execute-button" onclick="this.form.submitter = 'execute';" type="submit" value="Run" />
         <input id="codeEditorSubmitButton<!--{$exerciseID|validate:int}-->" class="merlin-code-explorer-submit-button" onclick="this.form.submitter = 'submit';" type="submit" value="Submit"/>
     </div>
     </div>
     <div id="codeEditorCombinedOutput<!--{$uniqueID|validate:int}-->" class="merlin-code-explorer-combined-output"></div>
     <div id="codeEditorCombinedOutput<!--{$exerciseID|validate:int}-->" class="merlin-code-explorer-combined-output"></div>
     </div>
     </div>
</form>
</form>
</includeonly>
</includeonly>

Revision as of 20:18, 5 October 2021

Parameters:

userName
string: The current user's username
sessionID
string: The ID of the current user's session
experienceID
string: The experienceID of the page from which the widget is invoked
codeExplorerGroupID
string: The code explorer group. If empty, the submit button will be disabled.
exerciseID
integer: exercise id for editor, must be unique per page
width
integer|string: percentage (as string, e.g. "100%" or integer size in pixels), null for no change (full width)
height
integer|string: percentage (as string, e.g. "100%" or integer size in pixels), null for no change (~10 lines)
lineNumbers
boolean: true to display line numbers
theme
string: name of theme (which must be loaded via css)
readOnly
boolean: true if editing should be disabled
mode
string: language for highlighting (which must be loaded via js)
initialCode
string: initial code to place in editor

Example:

{{#widget:CodeExplorer
|userName=john-williams
|sessionID=qh0ubrrme911kcg7db0i0ec6lct94h7f
|experienceID=W1020.23
|codeExplorerGroupID=WTRS-8527
|exerciseID=10
|width=null
|height=null
|lineNumbers=true
|theme=vibrant-ink
|readOnly=false
|mode=swift
|initialCode=func sayHello() {
    print("Hello, World!")
}
}}