Giter Club home page Giter Club logo

adapt-authoring's Introduction

Adapt Authoring Tool

Snyk security Documentation build CI Join the chat at https://gitter.im/adaptlearning/adapt_authoring

⚠️ DISCLAIMER ⚠️

This is pre-release software and does not represent the final product. This software should not be installed and used in a production environment, and contains incomplete and buggy source code which is currently undergoing a thorough testing and improvement process.


Adapt is a free and easy to use framework and authoring tool that creates fully responsive, multi-device, HTML5 e-learning content.

What Does It Do?

The Adapt authoring tool is a web-based user interface for the Adapt Framework. Use it to create responsive, single-version HTML5 e-learning courses for delivery on a web server or SCORM-compliant learning management system.

Interested? See what Adapt can do.

Features

  • Web application for creating, editing and publishing Adapt content
  • Supports all core extensions and components
  • Allows uploading and linking of course assets
  • Built on Node.js, Express, MongoDB, and Backbone.js

Full Documentation

Visit the developer documentation for more information, including installation instructions, full API documentation, developer guides, and other information.

Communication

Contributing to Adapt

See Contributing to the Adapt authoring tool.

Troubleshooting, Bugs, and Feedback

License

adapt learning logo Adapt is licensed under the GNU General Public License, Version 3.

adapt-authoring's People

Contributors

dependabot[bot] avatar kristofferbroberg avatar taylortom avatar tomgreenfield avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

adapt-authoring's Issues

Is DataStoreQuery class necessary?

I'm starting to think this is an abstraction for abstraction's sake; not sure it's really useful in the long-run. Is it useful to have a query class that can be used for all 3? Queries to different datastores are probably going to vary enough to make render this a bit pointless. It's also probably a bit more dev-friendly + transparent to expose datastore-specific APIs.

Example DataStores

  • MongoDB
  • xAPI
  • Google Analytics

Make datastore module configurable

Would be nice to specify the config for a module in the config/package.json for the module, with a default option if not configured.

Example:

  • Main app config specifies mongodb as storage
  • Users module doesn't specify a storage type
  • An 'analytics' module specifies googleanalytics as its storage
  • Module#storage function gets the storage module according to the module's config:
    • mongodb for users
    • googleanalytics for analytics

How should we call 'internal' code across modules

Assuming two modules are on the same server, it's overkill to have to create http requests to use functionality across each module. What is the best way to bridge this gap?

Requirements:

  • Make sure we don't unnecessarily repeat any code (e.g. input validation).
  • May need to reassess how middleware's used (to make sure any middleware applies only to functionality related specifically to HTTP requests).

Possible solutions:

  • Expose relevant functions on AbtractModule export

Research localisation options

Requirements

  • Ability to set app-wide language
  • Ability for individual users to set front-end language (would override default setting)
  • Ability to add lang strings in any language in each module
  • Ability to override all strings from a single location (i.e. a single file), to open up the possibility of creating 'language pack' modules
  • API endpoint for front-end access

Tasks

  • Investigate localisation
  • Working localisation prototype for one module
  • Write any docs necessary to aid future implementation
  • Investigate how to document lang strings

Probably makes sense to base module around Polyglot.js again

Investigate using async await more

Very generic one, but I've not done a lot of async/await in the current prototype, so could do with identifying any areas that would be a good use of it.

Refactor dependencyloader error messages

Original problem here was that any errors occurring before logger has initialised use console log & were therefore ugly. I've refactored this so that the logging works as expected, but it needs another rewrite as feels a bit hacky.

What we need:

  • Utility-level errors need to use the logger (with a console fallback in the case that logger has failed)
  • Module-level errors should use logger, as the app should fail if any utilities haven't loaded correctly (check this happens)

Investigate courseasset alternatives

In the current incarnation, courseasset records are used to flag individual asset instances.

  • Course build: to determine which assets to include
  • Asset deletion: to determine if assets are used in any course

Possible solutions:

  • ???

Research unit tests

We need to think about how unit tests will be implemented and run.

  • Research running tests across the module set
  • Research integration with CI on GitHub
  • Write any docs necessary to aid future implementation

Prototype configuration module

Goal

Allow easy user configuration with as little input from the user as possible.

Requirements

  • Support multiple environments/sets of configurations
  • Remove (or greatly reduce) the need for defensive coding when accessing config values (e.g. if(!configValue) ...).
  • Allow devs to specify constraints for their config values (see Config schemas)
  • Singleton?
  • Should listen to module create event
  • Modules need to define a config file (or default to config.JSON?)
  • Should probably namespace config options (e.g. config.mongodb.server_port)
    • How will this work with CMD args?

Notes

  • Major performance hit when accessing process.env, so make sure this is read once and cached

Config schemas

For consistency, these should mirror the format we use for other schemas throughout the app.

Allow devs to include schemas with any modules which allow them to specify what config options are needed, and what values are acceptable:

  • Whether the option is required
  • Default value (if not required)
  • Type of value
  • Constraints/validation to further restrict what is provided here (this could be replace type, or compliment it)
  • Whether the option is hidden from the front-end app
  • Description of the value

These schemas could then be processed during the app boot process to:

  • Check all required config options have been set by the user (and warn of any missing config options, possibly stop loading process of module or entire app)
  • Provide default values for any non-required options not present in the app config file

Schemas would also be useful for various automated processes:

  • Current config/config.json route requires a hard-coded list of whitelisted attributes, schemas could expose a value which would set this (e.g. hidden)
  • Install process could use schemas to greatly reduce the code in a specific install script.
    This would make it easy to automate the install process & config/config.json API route.

Discuss 'essential' APIs

Some questions:

  • How (and where) do we define the 'interfaces' (i.e. which functions should be available etc.)
  • How much should the code work without them an 'essential' API (probably not at all)
  • Some functions are a bit verbose (e.g. this.app.lang.t, this.app.logger.log) -- would nice to add dev-friendly shortcuts to these functions (e.g. this.t, this.log), but how does this fit into the above?

This is likely to be a particular problem with the unit tests. The most common example being the lang module (and translating error strings etc.) - should the app continue to function if this isn't present (we can obviously mock the translation module to get around this in tests).

Write abstract API module/class

Considering that writing APIs will be the main task when extending the authoring tool, we could do with writing some reusable bits to make API creation less code-heavy (and remove duplication).

Things you want to define when creating an API:

  • Main mount-point
  • Sub-routes
  • Route handlers
  • Middleware
  • DB models/schemas

Other points:

  • Skeleton Module class which can be extended (inits the API, controller, data models etc.)
  • API/route template with the standard methods: POST, GET, UPDATE, DELETE
    • Should also be able to restrict to a subset of the above
  • Generic controller to handle DB storage
  • Generic middleware (e.g. to check POST requests have a body)
  • Possibly set default paths for the required files (controller.js, api.js etc.), so you can omit boilerplate loading code if using these standard paths
  • Consistent querying
  • Consistent data responses (e.g. pagination)
  • Consistent error handling
  • Ways to easily customise/override all of the above
    • Router/per-route middleware
    • Disable specific HTTP methods
    • Override individual handlers (i.e. not all or none)
  • Should it be possible to define a new API without any code?? (i.e. just using package.json...and probably schema)

Prototype authentication

This issue covers the basic implementation of authentication.

  • User passwords should be encrypted
  • New auth module should setup passport with local strategy
  • Use token based authentication
  • The auth module should have a way to run necessary auth code on server boot
  • The user delete route should require authentication
  • Merge changes into main repo(s)

Installer module

Think it'd be good to encapsulate the install/upgrade process in a separate module to allow for easy modification/replacement later. This would also allow for easier testing + interaction between the installer and other parts of the application.

If the installer is an Adapt Module, it'd also be easy to replicate the version check + log output that we have currently.

Create interfaces for core app modules to allow loose-ish coupling

Main requirement with this is to be able to allow modules to interact with key parts of the application without needing to know about the implementation.

Main areas I'm thinking of with this:

  • Logger
  • Config
  • Lang

Requirements:

  • Provide a class/interface to inherit from/implement
  • Will probably need to ensure at least one module has been registered for each interface
  • Allow modules to register themselves

Revisit need for sanitiseInput middleware

For reference: Middleware#sanitiseInput

The middleware nullifies body/params/query on the request if they're empty objects. The original intention was to make presence checking a bit cleaner by using truthy values (e.g. if(req.body) {} rather than checking keys etc. each time).

HOWEVER, this now leads to extra defensive code if you need to use properties of the above (e.g. if(req.params && req.params._id) {} which is annoying...).

Possible solutions:

  • Revert back to original functionality, which may reintroduce the need to have existence checks
  • Amend middleware to leave original body/params/query objects be, and maybe store a separate boolean value on the request (e.g. req.hasBody, req.hasParams etc.)

Document API/module map

List of modules that are needed for the restructure. These will be a mixture of the existing /lib and /plugins files, as well as some necessary extras now we're using a modular architecture.


TODO

  • Identify modules which will need to access other modules & solutions

'Module' column refers to whether the module is an Adapt authoring module (rather than just a standard Node module).

Name Module Description GitHub
adapt-authoring-adaptoutput true Handles the transformation of DB data + local files into an Adapt course. :octocat:
adapt-authoring-assets true Asset handling. :octocat:
adapt-authoring-authentication-local true May be combined with authorisation. :octocat:
adapt-authoring-authorisation-??? true May be combined with authentication. :octocat:
adapt-authoring-clipboard true Server-side copy/pasting. :octocat:
adapt-authoring-content false :octocat:
adapt-authoring-content-article (adapt-authoring-content) true :octocat:
adapt-authoring-content-block (adapt-authoring-content) true :octocat:
adapt-authoring-content-component (adapt-authoring-content) true :octocat:
adapt-authoring-content-contentobject (adapt-authoring-content) true :octocat:
adapt-authoring-core false :octocat:
adapt-authoring-docs false :octocat:
adapt-authoring-logger false :octocat:
adapt-authoring-middleware true :octocat:
adapt-authoring-missingroute true :octocat:
adapt-authoring-mongodb true :octocat:
adapt-authoring-plugin false :octocat:
adapt-authoring-plugin-component (adapt-authoring-plugin) true :octocat:
adapt-authoring-plugin-extension (adapt-authoring-plugin) true :octocat:
adapt-authoring-plugin-menu (adapt-authoring-plugin) true :octocat:
adapt-authoring-plugin-theme (adapt-authoring-plugin) true :octocat:
adapt-authoring-roles true :octocat:
adapt-authoring-server true :octocat:
adapt-authoring-tags true :octocat:
adapt-authoring-ui true :octocat:
adapt-authoring-users true :octocat:

Research authorisation options

See this Google Doc for more notes.

Below list is subject to change once discussed.

  • Investigate scope based roles
  • Investigate how to define roles
  • Investigate how auth should be applied (i.e. should it be possible to enable/disable at an individual API/API route level, or as an entire application)
  • Suggest best way to document using ESDocs
  • Think about how to cater for individual resources (see notes)

Questions

Does it matter where the auth comes in the stack (i.e. should other middleware be able to run before auth middleware)
Probably not, but for performance reasons it would be good to be able to stop any unnecessary middleware running if user doesn't have access to the system.

Abstract file storage API

We need a module to allow storage to both local and remote sources (by default, we only need to support local file storage).

Would be nice to allow the following:

  • temp files (e.g. build files, can be deleted)
  • app files (created during installation etc., app breaks if these are missing)
  • assets both local and remote

Possible API example:

await filestore.writeFile('http://drive.google.com/myFile.txt', 'googledrive');
const file = await filestore.readFile('http://drive.google.com/myFile.txt', 'googledrive');
// no param defaults to config 'defaultStore' option or similar
const file = await filestore.readFile('/path/to/myFile.txt');

Prototype content functionality

  • Breakdown of 'content' into separate modules + inheritance
    • Support framework schemas
  • Investigate splitting schemas:
    • Framework/content schemas
    • Editor schemas (extra editor settings not needed in content) example attributes: course hero image, course tags, course is shared, block layout options, component color label
  • Investigate building a course without the need for temp files (e.g. streaming?)
  • Investigate 'quick' build methods (e.g. precompiling of core/plugin code)

REST APIs must be documented

There's currently no mechanism to document the external API endpoints.

  • OpenAPI-based? (Swagger, ReDoc)
  • Integrate with ESDoc?

Error factory?

Might be nice to be able to 'register' errors to the app, to allow easy error type reuse across all modules in the app.

Note: not saying the below is the best way to implement, but gets my point across

e.g. Say a HelloWorld module defines a HelloWorldError:

class HelloWorld {
  constructor() {
    this.app.registerError(HelloWorldError);
  }
}

Some OtherModule can then use this error like so:

class OtherModule {
  someFunc() {
    throw this.app.ErrorFactory('HellowWorldError', { option: 1, option: 'two' });
  }
}

If the specific error hasn't been defined, a standard Error can be returned.

Documentation

  • Write up local module npm install stuff
  • Investigate levelling up the search function to include the manual pages
  • Look into switching to an ESDoc fork, as original isn't actively maintained
  • Document APIs exposed by AAT modules:
    • Probably OpenAPI-based? Swagger, ReDoc
    • Integrate with ESDoc?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.