{"id":22446989,"url":"https://github.com/learnosity/custom-questions-skeleton","last_synced_at":"2025-04-13T21:07:05.709Z","repository":{"id":39761343,"uuid":"416989763","full_name":"Learnosity/custom-questions-skeleton","owner":"Learnosity","description":"Build custom questions/features with Learnosity APIs","archived":false,"fork":false,"pushed_at":"2025-03-10T02:32:30.000Z","size":1810,"stargazers_count":1,"open_issues_count":34,"forks_count":9,"subscribers_count":19,"default_branch":"master","last_synced_at":"2025-04-13T21:06:56.845Z","etag":null,"topics":["customise","learnosity"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Learnosity.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-14T04:37:16.000Z","updated_at":"2025-03-10T02:32:28.000Z","dependencies_parsed_at":"2025-03-10T00:32:24.176Z","dependency_job_id":null,"html_url":"https://github.com/Learnosity/custom-questions-skeleton","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Learnosity%2Fcustom-questions-skeleton","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Learnosity%2Fcustom-questions-skeleton/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Learnosity%2Fcustom-questions-skeleton/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Learnosity%2Fcustom-questions-skeleton/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Learnosity","download_url":"https://codeload.github.com/Learnosity/custom-questions-skeleton/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248782269,"owners_count":21160717,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["customise","learnosity"],"created_at":"2024-12-06T04:13:35.386Z","updated_at":"2025-04-13T21:07:05.685Z","avatar_url":"https://github.com/Learnosity.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003cimg width=\"50%\" height=\"50%\" src=\"images/image-logo-graphic.png\"\u003e\u003c/p\u003e\n\u003ch1 align=\"center\"\u003eGuidelines for Learnosity Custom Questions and Features\u003c/h1\u003e\n\u003cp align=\"center\"\u003eThe guideline you need to start building your custom question/feature with Learnosity APIs using your preferred toolkit and languages.\u003cbr\u003e \n\u003c/p\u003e\n\u003cp align=\"center\"\u003eMore Custom Questions documentation is available at the \u003ca href=\"https://help.learnosity.com/hc/en-us/sections/4412969135761-Creating-Custom-Questions-and-Features\"\u003eLearnosity Help Site\u003c/a\u003e\u003cbr\u003e\n  An official Learnosity open-source project.\u003c/p\u003e\n  \n---\n\n## Table of Contents\n\n* [Overview: what's in the guideline?](#overview-what-does-it-contain)\n* [Available Demo Scripts](#available-demo-scripts)\n* [Test your Custom Question](#test-your-custom-question)\n* [Publish your custom question](#publish-your-custom-question)\n* [Development Recommendations](#development-recommendations)\n* [Next steps: additional documentation](#next-steps-additional-documentation)\n* [Contributing to this project](#contributing-to-this-project)\n* [License](#license)\n\n## Overview: what's in the guideline?\nThe Learnosity Custom Question/Feature Guideline provides the complete demos of some custom questions/features\nbuilt by Learnosity engineers which you can use as a base of your custom question/feature project.\n\nThe following demos have been included in this repository:\n* Box and whisker\n* Custom question skeleton\n\nEach demo has the following structure:\n* `package.json`: contains the information about your custom question/feature project.\n  This file also contains some handy `scripts` that you can execute to quickly develop your custom question/feature.\n* `webpack.config.js`: is used to transpile and bundle your custom question/feature code.\n* `assessment.php`: a local Assessment demo page to help you to develop your custom question/feature quickly.\n* `authoring.php`: a local Assessment demo page to help you to develop the Schemas and Authoring layout for your custom question/feature.\n* `authoring_custom_layout.html`: the Authoring HTML layout of your custom question/feature. \n* `debugServerScorer.js`: a local Assessment server side demo page to help you to test the behavior of your custom question's scorer in the server side locally.\n* `src`: the source code folder\n  * `src/question.js`: the frontend entry point of your custom question/feature.\n    This file is responsible to generate the UI in the browser of you custom question/feature. \n  * `src/scorer.js`: the server side entry point of your custom question/feature.\n    This file is responsible to score the stored response of your custom question/feature and should not contain any UI related or any DOM manipulation libraries.\n* `scss`: the SASS source code folder\n\n*Note*: Note: for any files hosted outside Learnosity, you may need to set CORS privileges for such files. See more information in this article: \u003ca href=\"https://help.learnosity.com/hc/en-us/articles/360000757877\" target=\"_new\"\u003eWorking with Firewalls \u0026 Domain Whitelisting\u003c/a\u003e.\n\n## Available Demo Scripts\n**1. Box and Whisker Question Demo**\n* Project Location: `demos/box-and-whisker`\n\n**2. Custom Question Skeleton Demo**\n* A clean custom question skeleton you can leverage to start working on your custom question \n* Project Location: `demos/custom-question-skeleton`\n\n**3. Custom Feature Skeleton Demo**\n* A clean custom feature skeleton you can leverage to start working on your custom feature \n* Project Location: `demos/custom-feature-skeleton`\n\n**4. Simple Text Input Question Demo**\n* Project Location: `demos/simple-input-react`\n\n**5. Piano Question Demo**\n* Project Location: `demos/piano`\n\n**6. Clock Question Demo**\n* Project Location: `demos/clock`\n\n**Scripts**\n```\n# Start the localhost server to start developing your custom question\nyarn dev\n\n# Build the production ready code of your custom question\nyarn prod\n\n# Test your scorer's behavior in the server side. Update question/response in debugeServerScorer.js to test\nyarn debug-server-scorer\n\n# Run Jest unit-tests\nyarn unit-tests\n\n# Run Jest unit-tests in watch mode\nyarn unit-tests-watch\n```\n\n## Test your custom question\nAssessment demo using Questions API: \nhttp://localhost:12345/assessment.php\n\nAuthoring demo using Author API: \nhttp://localhost:12345/authoring.php\n\n## Publish your custom question\n* Once your custom question is ready, run `yarn prod` to generate the production ready build then\ncopy the content of the `dist` folder and your `authoring_custom_layout.html` to your server and\nmake sure those files are accessible on the web.\n* To test your production build, in your `assessment.php` file, point the `js` and `css` files to the location of your files\n```\n\"js\": {\n  \"question\": \"YOUR-SERVER-URL/question.js\",\n  \"scorer\": \"YOUR-SERVER-URL/scorer.js\"\n},\n\"css\": \"YOUR-SERVER-URL/question.css\"\n```\n\n## Development Recommendations\n**1. Leverage predefined Learnosity components**\n\nAvoid building the following default components to keep the consistent look-and-feel with Learnosity UI \n* **Check Answer button**\n  * Syntax: `lrnUtils.renderComponent('CheckAnswerButton', wrapperElement)`\n  * ```\n    // Example:\n    export default class MyCustomQuestion {\n        constructor(init, lrnUtils) {\n          const checkAnswerWrapperElement = document.createElement('DIV');\n    \n          init.el.appendChild(checkAnswerWrapperElement);\n    \n          this.checkAnswerButton = lrnUtils.renderComponent('CheckAnswerButton', checkAnswerWrapperElement);\n          ...\n        }\n    ```\n  * Public methods:\n    * `remove()`: Remove the component\n      * ```\n        this.checkAnswerButton = lrnUtils.renderComponent('CheckAnswerButton', checkAnswerWrapperElement);\n        this.checkAnswerButton.remove();\n        ```\n\n* **Suggested Answers list**\n* Syntax: `lrnUtils.renderComponent('SuggestedAnswersList', wrapperElement)`\n  * ```\n    // Example:\n    export default class MyCustomQuestion {\n        constructor(init, lrnUtils) {\n          const checkAnswerWrapperElement = document.createElement('DIV');\n    \n          init.el.appendChild(suggestedListWrapperElement);\n    \n          this.suggestedAnswersList = lrnUtils.renderComponent('SuggestedAnswersList', suggestedListWrapperElement);\n          ...\n        }\n    ```\n  * Public methods:\n    * `remove()`: Remove the component\n      * ```\n        this.suggestedAnswersList = lrnUtils.renderComponent('SuggestedAnswersList', suggestedListWrapperElement);\n        this.checkAnswerButton.remove();\n        ```\n    * `reset()`: Reset the components to its default state. All rendered answers will be removed.\n      * ```\n        this.suggestedAnswersList = lrnUtils.renderComponent('SuggestedAnswersList', suggestedListWrapperElement);\n        this.checkAnswerButton.reset();\n        ```\n    * `setAnswers(Array\u003c{ index: number, label: string }\u003e)`: Render the answers based on provided array\n      * ```\n        this.suggestedAnswersList = lrnUtils.renderComponent('SuggestedAnswersList', suggestedListWrapperElement);\n        this.suggestedAnswersList.setAnswers([\n            { index: 0, label: 'A'},\n            { index: 1, label: 'B'},\n            { index: 2, label: 'C'}\n        ]);\n        ```\n\n**2. Leverage predefined Learnosity style**\n\nYou can leverage the predefined validation UI style of Learnosity API by wrapping your custom question/feature content\nunder the DOM structure below\n```\n\u003cdiv class=\"lrn-bnw lrn-response-validation-wrapper\"\u003e\n    \u003cdiv class=\"lrn_response_input\"\u003e\n        RENDER YOUR CUSTOM QUESTION/FEATURE ELEMENT IN HERE\n    \u003c/div\u003e            \n\u003c/div\u003e\n```\n\nAdding `lrn_correct` (when all correct answers are provided) or `lrn_incorrect` (when the provided answer is not correct)\nto `lrn_response_input` will render the proper validation UI state to your custom question/feature.\n\n**3. Best practices: using a prefix for CSS class names**\n\nWhen creating a Learnosity Custom Question, it’s important to prefix the CSS class names being used inside your custom Question UI. You should avoid using a generic class name like `.btn`. Instead, you should add a prefix to it like `.company-name-my-custom-question-btn` to avoid CSS conflict with the host page and the CSS used by the Learnosity API.\n\n## Next steps: additional documentation\nYou can find more detailed documentation in the [Learnosity Help site](https://help.learnosity.com/hc/en-us/sections/4412969135761-Creating-Custom-Questions-and-Features).\nIf you are new to Learnosity Custom Questions we highly recommend starting [here](https://help.learnosity.com/hc/en-us/articles/4414363148561-Getting-Started-with-Custom-Questions-and-Features).\n\n## Contributing to this project\n\n### Adding new features or fixing bugs\nContribution in the form of [PRs] are welcome.\n\n[(Back to top)](#table-of-contents)\n\n## License\nThis project is licensed under MIT License. [Read more](LICENSE.md).\n\n[(Back to top)](#table-of-contents)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flearnosity%2Fcustom-questions-skeleton","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flearnosity%2Fcustom-questions-skeleton","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flearnosity%2Fcustom-questions-skeleton/lists"}