Giter VIP home page Giter VIP logo

react-scorm-provider's Introduction

React SCORM Provider

Presented by

S4 NetQuest Logo

Overview

React-scorm-provider (RSP) is a set of React Components that simplify the inclusion of the SCORM API into your React projects. It utilizes the great SCORM API wrapper from pipwerks. Use RSP to easily add SCORM capabilities to your learning modules, resources, games, or any web content you are creating with React. RSP in its current form is meant for single SCO packages and relatively simple communications to the LMS, however it can easily be extended and modified to work for more complex projects.

Keep in mind that this project does not include any kind of packaging or bundling for SCORM. It simply enables SCORM API calls inside your React code. For SCORM packaging your React app build, check out simple-scorm-packager.

There are two major components of RSP, ScormProvider and withScorm.

View the live demo


ScormProvider Component

<ScormProvider></ScormProvider>

A wrapper component which should only be included ONCE in your React application component tree. It should be included as close to the root of your component tree as possible so that child components can take advantage of the withScorm Higher-Order Component. The ScormProvider component automatically establishes a connection to the SCORM API and retrieves some initial data from the LMS via the SCORM API. Once the ScormProvider Component is included, any other component that is a child of the ScormProvider can access the SCORM-related properties and functions via the withScorm Higher-Order Component described below.

Note that the ScormProvider component itself does not pass props to any of its children. In order to access properties and methods of the ScormProvider component and make calls to the SCORM API, you must use the provided withScorm Higher-Order Component.

Configuration

The ScormProvider Component accepts two optional configuration props:

  • version: (String) (Optional) Specify the SCORM API version, accepts "1.2" or "2004". This is completely optional and probably not needed, as the included pipwerks SCORM API wrapper will automatically attempt to connect to any SCORM API it can find. The version found will the be stored to the ScormProvider Component.
  • debug: (Boolean) (Optional) (Default: true) Specify if the SCORM API should be in debug mode and emit messages to the console.

Putting it together:

// adding a ScormProvider

import React from 'react';
import ScormProvider from 'react-scorm-provider';

const App = () => {
  return (
    <ScormProvider version="1.2" debug={process.env.NODE_ENV !== 'production'}>
      <h1>Hello SCORM world!</h1>
      <p>
        Although I can't yet access any props or methods from the ScormProvider (because I haven't yet included 'withScorm()'), a connection to the SCORM API will be made, initial values retrieved from the LMS via that API, and stored in the ScormProvider Component for use with 'withScorm()'.
      </p>
    </ScormProvider>
  );
};

export default App;

withScorm Higher-Order Component

const YourEnhancedComponent = withScorm()(YourComponent)

This Higher-Order Component provides access to a number of properties and functions of the ScormProvider. Use this to enhance your components with SCORM goodness! All exposed properties and functions are passed to your enhanced component via the 'sco' prop that is added to your component.

The 'sco' prop object contains the following properties:

// props.sco
{
  // status of the connection to the SCORM API
  apiConnected: Bool,

  // cmi.core.student_name (SCORM 1.2) || cmi.learner_name (SCORM 2004)
  learnerName: String,

  // indication of course status
  completionStatus: String,

  // cmi.suspend_data parsed as an object (all suspend_data must be a JSON.stringify'd object for the suspend_data to work properly with RSP)
  suspendData: Object,

  // SCORM API version that is connected ('1.2' or '2004')
  scormVersion: String,

  // calling this function will update props.sco.suspendData with the current suspend_data from the LMS
  getSuspendData: Function () returns a Promise,

  // this function takes the required key and value arguments and merges them into the suspendData Object, overwriting the value if the key already exists. It then stringifies the object and saves it to the LMS as suspend_data
  setSuspendData: Function (key, val) returns a Promise,

  // resets the suspend_data to an empty object, clearing any existing key:value pairs
  clearSuspendData: Function () returns a Promise,

  // sends an updated course status to the LMS, accepts one of: "passed", "completed", "failed", "incomplete", "browsed", "not attempted"
  setStatus: Function (string) returns a Promise,

  // sends a score to the LMS via an object argument -- { value: Number - score (required), min: Number - min score (optional), max: Number - max score (optional), status: String - same as setStatus method (optional) }
  setScore: Function ({ value, min, max, status }) returns a Promise,

  // sets a SCORM value, ex: props.sco.set('cmi.score.scaled', 100)
  set: Function (string, val) returns a Promise,

  // gets a SCORM value from the LMS, ex: props.sco.get('cmi.score.scaled')
  get: Function (string) returns the LMS value
}

All you have to do to provide the sco prop object to a component is wrap the component with withScorm. In order for withScorm to work, the component it is enhancing must be a child of ScormProvider.

Example:

// enhancing a component and adding the sco object to its props

import React from 'react';
import { withScorm } from 'react-scorm-provider';

const StandardFunctionalComponent = (props) => {
  return (
    <div>
      <p>Welcome, {props.sco.learnerName}!</p>
      <p>Your course status is currently: {props.sco.completionStatus}</p>
      <p>Click the button below to complete the course!</p>
      <button onClick={() => props.sco.setStatus('completed')}>Mark me complete!</button>
    </div>
  );
};

const EnhancedComponent = withScorm()(StandardFunctionalComponent);

export default EnhancedComponent;

Full Example

import React from 'react';
import ScormProvider, { withScorm } from 'react-scorm-provider';

const Learner = (props) => {
  return (
    <div>
      <p>Welcome, {props.sco.learnerName}!</p>
      <p>Your course status is currently: {props.sco.completionStatus}</p>
      <p>Click the button below to complete the course!</p>
      <button onClick={() => props.sco.setStatus('completed')}>Mark me complete!</button>
    </div>
  )
}

const ScoLearner = withScorm()(Learner);


const App = () => {
  return (
    <ScormProvider>
      <h1>We've got a connection just by including ScormProvider!</h1>
      <p>I'm a child with no access to the ScormProvider's props. But the ScoLearner component is enhanced with withScorm()!</p>
      <ScoLearner />
    </ScormProvider>
  );
};

export default App;

react-scorm-provider's People

Contributors

jayv30 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

react-scorm-provider's Issues

Access scorm in componentDidMount method.

Hi, want to know if it is possible to access scorm inside if componentDidMount lifecycle method. Basically I am trying to retrieve the suspend data from the LMS and then call my action from componentDidMount so that I can filter the api data with the suspend data but it seems I can't access it from there as the connection becomes active only after it moves onto the render methods. Is there amy way to access scorm from the actions or componentDidMount? Thanks

TypeScript typings

Since I had to write these anyway, I'm sharing TypeScript typings for this package in case somebody needs them. It would be also a neat base for potential TypeScript migration in the future.

declare module 'react-scorm-provider' {
  type ScormVersion = '1.2' | '2004';

  type SuspendData = Record<string, unknown>;

  type Status =
    | 'passed'
    | 'completed'
    | 'failed'
    | 'incomplete'
    | 'browsed'
    | 'not attempted'
    | 'unknown';

  type ScoreObj = {
    value: number;
    min: number;
    max: number;
    status: string;
  };

  export type ScoProp = {
    apiConnected: boolean;
    clearSuspendData: () => SuspendData;
    completionStatus: Status;
    get: (param: string) => unknown;
    getSuspendData: () => SuspendData;
    learnerName: string;
    scormVersion: ScormVersion;
    set: (param: string, val: any, deferSaveCall?: boolean) => void;
    setScore: (scoreObj: ScoreObj) => any[];
    setStatus: (status: Status, deferSaveCall?: boolean) => void;
    setSuspendData: (key: string | number, val: any) => SuspendData;
    suspendData: SuspendData;
  };

  const ScormProvider: React.ComponentType<{
    children?: React.ReactNode;
    version?: ScormVersion;
    debug?: boolean;
  }>;

  export const withScorm: () => <P extends object>(
    Component: React.ComponentType<P>,
  ) => React.ComponentType<Omit<P, 'sco'>>;

  export default ScormProvider;
}

[Documentation improvements] I don't know how to start with this.

Hey everyone,

I am a frontend developer for a LMS platform and I need to give the users the possibility to take courses provided from our stakeholders through our application. The problem is that this is completely new to me so I did some research and then I found this package which seems useful for me at the moment.

The problem is that I don't know how to start with it. I ran the example available in READ.me and I'm getting this error:

`SCORM.API.find: Error finding API. 
Find attempts: 0. 
Find attempt limit: 500
index.js:835 API.get failed: Can't find the API!
index.js:835 SCORM.connection.initialize failed: API is null.
ScormProvider.js:256 ScormProvider init error: could not create the SCORM API connection`

As I understand, maybe I'm wrong but I need to insert the API from where the Scorm Provider will get the courses. But the question is where and how?

I can use some help right now and I think a better documentation and some examples would solve this problem in the future.

Cheers,
Vlad

How to wait for the API to be connected

Hi there,

First of all, really great wrapper that simplifies a lot of things so thank you for that.

My only issue is that I'm trying to wait for the SCORM API to be ready so I can fetch the data previously set in suspend data, any idea how to achieve this?

Thanks,
Arno

How work with this?

Hello!

I have SCORM Package in scorm_project/index_scorm.html

I do next:

const Learner = (props) => {
  console.log(props.sco);

  return (
    <div>
      <p>Welcome, {props.sco.learnerName}!</p>
      <p>Welcome, {props.sco.scormVersion}!</p>
      <p>Your course status is currently: {props.sco.completionStatus}</p>
      <p>Click the button below to complete the course!</p>
      <button onClick={() => props.sco.setStatus('completed')}>Mark me complete!</button>

      <button onClick={() => {
        window.open("scorm_project/index_scorm.html", "", "&w=400&h=400");
      }}>
        Click
      </button>
    </div>
  )
}

const ScoLearner = withScorm()(Learner);


const App = () => {
  return (
    <>
    <ScormProvider version="2004" debug={process.env.NODE_ENV !== 'production'}>
      <h1>We've got a connection just by including ScormProvider!</h1>
      <p>I'm a child with no access to the ScormProvider's props. But the ScoLearner component is enhanced with withScorm()!</p>
      <ScoLearner />
    </ScormProvider>
    </>
  );
};

I get

SCORM.API.find: SCORM version 2004 was specified by user, but API_1484_11 cannot be found.
index.js:883 SCORM.API.find: Error finding API. 
Find attempts: 0. 
Find attempt limit: 500

When i click on button i get error from my package Unable to acquire LMS API.

What i need do to working with this?

Thanks.

Could not resolve dependency: npm ERR! peer react@"^16.4.2" from [email protected]

Hi,
while I am installing this library, I faced this error from npm:

npm install react-scorm-provider           
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR! 
npm ERR! While resolving: [email protected]
npm ERR! Found: [email protected]
npm ERR! node_modules/react
npm ERR!   react@"^18.2.0" from the root project
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^16.4.2" from [email protected]
npm ERR! node_modules/react-scorm-provider
npm ERR!   react-scorm-provider@"*" from the root project
npm ERR! 
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.

Can you upgrade the library to React 18 please?

Do you want this fork as PR ?

Hi,

I recently forked this repo to include Typescript typings and a fallback to localStorage if the module is not used in a LMS.
Are these features in the scope of this library and if so, do you want me to open a PR ?

'SCORM.data.save failed: API connection is inactive' on link click

I'm having a problem with navigating a multiple page SCO using React Scorm Provider.

Everything works fine on one page and I can set suspend data and status using React components there, all great.

I have several other pages defined in my manifests generated by Simple Scorm Packager and the links in the initial page and manifest match up.

However on clicking any links I get the SCORM.data.save failed: API connection is inactive even seconds after doing an API interaction in my components, and am redirected back to SCORM Cloud's dashboard.

I've dug into the issue and the error message seems to come from the packaged SCORM API wrapper based on the state of scorm.connection.isActive, logically enough.

I feel like I may be making some basic error in my understanding of how SCORM works or this is a bug of some kind?

Any insights into this would be greatly appreciated!

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.