Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breaking: ES6 Upgrade (fixes: issue/13) #32

Open
wants to merge 78 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 76 commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
c4d0eaa
Update abstractStatementModel.js
joe-replin Feb 28, 2024
12734a2
Create accessedStatementModel.js
joe-replin Feb 28, 2024
505d525
Update assessmentStatementModel.js
joe-replin Feb 28, 2024
2e47fff
Adding new statement models
joe-replin Feb 28, 2024
1f57dfb
Changing current statement files
joe-replin Feb 28, 2024
6e9d5b3
Delete js/statements/unfavouriteStatementModel.js
joe-replin Feb 28, 2024
104ba1d
Delete js/statements/favouriteStatementModel.js
joe-replin Feb 28, 2024
eb4b5ac
Delete js/statements/resourceItemStatementModel.js
joe-replin Feb 28, 2024
d2e5ae2
Update bower.json
joe-replin Feb 28, 2024
5d02b08
Update package.json
joe-replin Feb 28, 2024
2f632c3
Update package-lock.json
joe-replin Feb 28, 2024
3093602
Update sliderStatementModel.js
joe-replin Feb 28, 2024
86cffe8
Update terminatedStatementModel.js
joe-replin Feb 28, 2024
d63578c
Rename adapt-xapi.js to adapt-kineo-xapi.js
joe-replin Feb 28, 2024
53b63cc
Update questionStatementModel.js
joe-replin Feb 28, 2024
9ec8681
Uploaded files
joe-replin Sep 26, 2024
eda69ea
Reverting launch.html
joe-replin Sep 26, 2024
0b6c1f1
Merge branch 'master' into issue/13
joe-replin Sep 26, 2024
7e6876c
Update adapt-kineo-xapi.js
joe-replin Sep 26, 2024
efa0e08
Update example.json
joe-replin Sep 26, 2024
73ca7a6
Update properties.schema
joe-replin Sep 26, 2024
feb6647
Update config.schema.json
joe-replin Sep 26, 2024
738f277
Update README.md
joe-replin Sep 26, 2024
6c620d8
Update abstractStatementModel.js
joe-replin Sep 26, 2024
c9bd79d
Update abstractStatementModel.js
joe-replin Sep 26, 2024
abdba24
Remove Polyfill libraries
joe-replin Oct 2, 2024
474f6cc
Remove Polyfill Libraries
joe-replin Oct 2, 2024
28f98c5
Revert "Update abstractStatementModel.js"
joe-replin Oct 2, 2024
907c7c7
Revert "Update abstractStatementModel.js"
joe-replin Oct 2, 2024
edb66a5
Revert "Merge branch 'master' into issue/13"
joe-replin Oct 2, 2024
827c676
Recommitting abstractStatementModel
joe-replin Oct 2, 2024
0cfcd28
Revert "Recommitting abstractStatementModel"
joe-replin Oct 2, 2024
6d03f72
Update abstractStatementModel.js
joe-replin Oct 2, 2024
5176e8c
Update abstractStatementModel.js
joe-replin Oct 2, 2024
87edb79
Removing proposed new features
joe-replin Oct 2, 2024
dc07aaf
ES6 super
joe-replin Oct 15, 2024
1670dc1
Convert lodash to ES6 standards
joe-replin Oct 15, 2024
a2d5304
File Structure Adjustments
joe-replin Oct 15, 2024
f132b99
ES6 Changes
joe-replin Oct 15, 2024
8ac29a6
ES6 Improvements
joe-replin Oct 15, 2024
60ecb96
Statement file clean-up
joe-replin Oct 15, 2024
3c5e168
Rename errorNotificationModel.js to ErrorNotificationModel.js
joe-replin Oct 16, 2024
24a7d18
Rename launchModel.js to LaunchModel.js
joe-replin Oct 16, 2024
7539ad7
Rename stateModel.js to StateModel.js
joe-replin Oct 16, 2024
eb0ea3b
Rename statementModel.js to StatementModel.js
joe-replin Oct 16, 2024
801e29e
Rename utils.js to Utils.js
joe-replin Oct 16, 2024
06873c6
Rename abstractStatementModel.js to AbstractStatementModel.js
joe-replin Oct 16, 2024
2310ecc
Rename assessmentStatementModel.js to AssessmentStatementModel.js
joe-replin Oct 16, 2024
7436ef3
Rename completedStatementModel.js to CompletedStatementModel.js
joe-replin Oct 16, 2024
b4fcc8e
Rename confidenceSliderStatementModel.js to ConfidenceSliderStatement…
joe-replin Oct 16, 2024
91d69a2
Rename experiencedStatementModel.js to ExperiencedStatementModel.js
joe-replin Oct 16, 2024
ab60fb2
Rename initializedStatementModel.js to InitializedStatementModel.js
joe-replin Oct 16, 2024
8bf0dcc
Rename languageStatementModel.js to LanguageStatementModel.js
joe-replin Oct 16, 2024
8ac502c
Rename matchingStatementModel.js to MatchingStatementModel.js
joe-replin Oct 16, 2024
74ff9b2
Rename mcqStatementModel.js to McqStatementModel.js
joe-replin Oct 16, 2024
d604430
Rename preferredStatementModel.js to PreferredStatementModel.js
joe-replin Oct 16, 2024
1477035
Rename questionStatementModel.js to QuestionStatementModel.js
joe-replin Oct 16, 2024
7cee46a
Rename sliderStatementModel.js to SliderStatementModel.js
joe-replin Oct 16, 2024
6d5d01b
Rename terminatedStatementModel.js to TerminatedStatementModel.js
joe-replin Oct 16, 2024
1c8d317
Rename textInputStatementModel.js to TextInputStatementModel.js
joe-replin Oct 16, 2024
40fff86
Adding back offlineStorage import
joe-replin Oct 17, 2024
a2768e9
No need to bind
joe-replin Oct 17, 2024
beb94be
Fixing bugs
joe-replin Oct 17, 2024
b292ed3
Package name
joe-replin Oct 17, 2024
805a2b5
Merge branch 'issue/13' of https://github.com/cgkineo/adapt-xAPI into…
joe-replin Oct 17, 2024
074e0da
Update README.md
joe-replin Oct 17, 2024
05a19bc
optional chaining
joe-replin Oct 17, 2024
f429fe0
Reverting launch.html
joe-replin Oct 17, 2024
f108cf2
Adjusted for latest language change logic
joe-replin Oct 17, 2024
6519719
Merge branch 'issue/13' of https://github.com/cgkineo/adapt-xAPI into…
joe-replin Oct 17, 2024
d15865d
Using logging API
joe-replin Oct 22, 2024
ecfdae8
onADLaunchAttempt de-nest
joe-replin Oct 31, 2024
a44ad26
Remove extra default
joe-replin Oct 31, 2024
ca2a437
Update ErrorNotificationModel.js
joe-replin Nov 6, 2024
58d982c
Update AbstractStatementModel.js
joe-replin Jan 20, 2025
2dd19eb
Update AbstractStatementModel.js
joe-replin Jan 20, 2025
4985d13
Merge branch 'master' into issue/13
joe-replin Jan 20, 2025
9b994a3
Update AbstractStatementModel.js
joe-replin Jan 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Please refer to [example.json](example.json) for the JSON snippet which should b

| Property | Type | Default | Description |
|--|--|--|--|
| \_isEnabled | Boolean | `false` | Set to `true` to enable the extension.
| \_isEnabled | Boolean | `true` | Set to `true` to enable the extension.
| \_activityId | String | `""` | Used to populate the Activity id included in _tincan.xml_ and for use in the Statement and State API. The value will be overriden if changed on the hosting environment.
| \_revision | String | `""` | This helps identify users running particular versions of the content, should functionality have been changed or issues found which require updates/voided statements for users running a specific revision. Where data has changed significantly, a new Activity id is recommended.
| \_tracking | Object | `{ _storeQuestionResponses: true, _questionInteractions: true, _assessmentsCompletion: false, _assessmentCompletion: true }` | <ul><li>\_storeQuestionResponses: Restore question responses across browser sessions.</li><li>\_questionInteractions: Record statements for questions.</li><li>\_assessmentsCompletion: Record a completed statement on completion of individual assessments.</li><li>\_assessmentCompletion: Record a completed statement on completion of all assessments combined.</li></ul>
Expand Down
8 changes: 4 additions & 4 deletions bower.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"name": "adapt-xAPI",
"version": "2.1.4",
"framework": ">=3.0.0",
"framework": ">=5.19.1",
"homepage": "https://github.com/cgkineo/adapt-xAPI",
"issues": "https://github.com/cgkineo/adapt-xAPI/issues",
"displayName": "xAPI",
"bugs": "https://github.com/cgkineo/adapt-xAPI/issues",
"extension": "xapi",
"targetAttribute": "_xapi",
"displayName": "xAPI",
"description": "An extension which allows the Experience API (xAPI) to collect data on human performance, stored within a suitable Learning Record Store (LRS).",
"main": "/js/adapt-xapi.js",
"keywords": [
Expand All @@ -17,7 +18,6 @@
"experience api",
"tracking"
],
"targetAttribute": "_xapi",
"license": "GPL-3.0",
"private": true,
"devDependencies": {
Expand Down
6 changes: 3 additions & 3 deletions example.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"_xapi": {
"_isEnabled": true,
"_comment": "included in tincan.xml. _activityId will be overriden if changed on the hosting environment.",
"_activityId": "https://example.com/unique_identifier",
"_revision": "",
"_activityId": "https://example.com/unique_identifier",
"_revision": "",
"_tracking": {
"_storeQuestionResponses": true,
"_questionInteractions": true,
Expand Down Expand Up @@ -32,4 +32,4 @@
}
}
}
}
}
117 changes: 117 additions & 0 deletions js/ErrorNotificationModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import Adapt from "core/js/adapt";
import notify from 'core/js/notify';
import wait from "core/js/wait";
import logging from "core/js/logging";

const LAUNCH_ERROR_ID = 'launch-error';
const ACTIVITYID_ERROR_ID = 'activityId-error';
const LRS_ERROR_ID = 'lrs-error';

class ErrorNotificationModel extends Backbone.Model {

defaults() {
return {
_isReady: false,
_isNotifyOpen: false,
_isDeferredLoadingError: false,
_currentNotifyId: null
};
}

initialize() {
this.listenToOnce(Adapt, {
'app:dataLoaded': this.onDataLoaded
});

this.listenTo(Adapt, {
'xapi:launchError': this.onShowLaunchError,
'xapi:activityIdError': this.onShowActivityIdError,
'xapi:lrsError': this.onShowLRSError,
'notify:closed': this.onNotifyClosed
});
}

_showNotification(config, id) {
if (this._isReady) {
if (!this._isNotifyOpen) {
logging.error(config?.title);

const notifyConfig = this._getNotifyConfig(config, id);

notify.popup(notifyConfig);

this._isNotifyOpen = true;
this._currentNotifyId = id;
} else if (this._currentNotifyId !== id) {
this.listenToOnce(Adapt, 'notify:closed', this._showNotification.bind(this, config, id));
}
} else {
this._isDeferredLoadingError = true;

this.listenToOnce(Adapt, 'app:dataLoaded', this._showNotification.bind(this, config, id));
}
}

_getNotifyConfig(config, id) {
const notifyConfig = {
title: config?.title,
body: config?.body,
_classes: `xAPIError ${id} ${config._classes}`,
_isxAPIError: true
};

let isCancellable = true;

if (config.hasOwnProperty('_isCancellable')) {
isCancellable = config._isCancellable;
notifyConfig._isCancellable = isCancellable;
notifyConfig._closeOnShadowClick = !isCancellable;
}

return notifyConfig;
}

/**
* Can't show notify until data has loaded due to `import_globals` in template
*/
onDataLoaded() {
this._isReady = true;

if (this._isDeferredLoadingError) {
wait.begin();

$('.loading').hide();
}
}

onShowLaunchError() {
this._showNotification(this.get('_launch'), LAUNCH_ERROR_ID);
}

onShowActivityIdError() {
this._showNotification(this.get('_activityId'), ACTIVITYID_ERROR_ID);
}

onShowLRSError() {
this._showNotification(this.get('_lrs'), LRS_ERROR_ID);
}

onNotifyClosed(notify) {
if (!notify.model.get('_isxAPIError')) return;

if (this._isDeferredLoadingError) {
wait.end();

this._isDeferredLoadingError = false;

// cancel other errors if launch failed and user dismissed, as it won't track regardless
this.stopListening();
}

this._isNotifyOpen = false;
this._currentNotifyId = null;
}

}

export default ErrorNotificationModel;
132 changes: 132 additions & 0 deletions js/LaunchModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import Adapt from "core/js/adapt";

class LaunchModel extends Backbone.Model {

defaults() {
return {
_xAPIWrapper: null,
_retryCount: 0,
_retryLimit: 1,
registration: null,
actor: null,
contextActivities: {
grouping: []
}
};
}

initialize() {
this.initializeLaunch();
}

initializeLaunch() {
const { lrs } = ADL.XAPIWrapper;

/**
* can auth be sent through in a different process, e.g. OAuth?
* lrs.endpoint && lrs.auth have defaults in the ADL xAPIWrapper, so can't assume their existence means they are the correct credentials - errors will be handled when communicating with the LRS
*/
if (lrs.endpoint && lrs.auth && lrs.actor) {
this._xAPIWrapper = ADL.XAPIWrapper;

// add trailing slash if missing in endpoint
lrs.endpoint = lrs.endpoint.replace(/\/?$/, '/');

// @todo: capture grouping URL params - unsure what data this actually contains based on specs - unlike contextActivities for ADL Launch
const launchData = {
registration: lrs.registration || null,
actor: JSON.parse(lrs.actor)
};

this.set(launchData);

this.triggerLaunchInitialized();
} else {
ADL.launch(this.onADLLaunchAttempt.bind(this), false);
}
}

getWrapper() {
return this._xAPIWrapper;
}

showErrorNotification() {
Adapt.trigger('xapi:launchError');
}

triggerLaunchInitialized() {
setTimeout(function() {
Adapt.trigger('xapi:launchInitialized');
}, 0);
}

onADLLaunchAttempt(err, launchdata, wrapper) {
/*
200 = OK
400 = launch already initialized
404 = launch removed
*/
if (err) {
if (performance.navigation.type === 1) {
this.onReload();
return;
}

if (this._retryCount < this._retryLimit) {
this._retryCount++;
this.initializeLaunch();
return;
}

this.onLaunchFail();
return;
}

this._xAPIWrapper = wrapper;

// can ADL launch include registration?
const launchData = {
registration: launchdata.registration || null,
actor: launchdata.actor
};

const contextActivities = launchdata.contextActivities;
if (contextActivities && Object.keys(contextActivities).length > 0) {
launchData.contextActivities = contextActivities;
}

this.set(launchData);

// store launch server details should browser be reloaded and launch server session still initialized
sessionStorage.setItem('lrs', JSON.stringify(wrapper.lrs));
sessionStorage.setItem('launchData', JSON.stringify(launchData));

this.triggerLaunchInitialized();
}

// if launch session expired, will the next request to the launch server produce an error notification for the user?
onReload() {
const lrs = JSON.parse(sessionStorage.getItem('lrs'));
const launchData = JSON.parse(sessionStorage.getItem('launchData'));

if (!lrs || !launchData) {
this.onLaunchFail();
return;
}

this._xAPIWrapper = ADL.XAPIWrapper;
this._xAPIWrapper.changeConfig(lrs);

this.set(launchData);

this.triggerLaunchInitialized();
}

onLaunchFail() {
Adapt.trigger('xapi:launchFailed');

this.showErrorNotification();
}
}

export default LaunchModel;
48 changes: 48 additions & 0 deletions js/OfflineStorageHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const OfflineStorageHandler = {

// will be set to StateModel once ready - store values until then
model: new Backbone.Model(),

get(name) {
switch (name.toLowerCase()) {
case 'student':// for backwards-compatibility. learnerInfo is preferred and will give more information
return this.model.get('actor').name;
case 'learnerinfo':
return this._getActorData();
default:
return this.model.get(name);
}
},

set(name, value) {
this.model.set(name, value);
},

_getActorData: function() {
const actor = this.model.get('actor');
const id = this._getIdFromActor(actor);

/*
* don't think we should make any judgement on name format for firstname or lastname, as there is no standard for this in xAPI
* if actor.name not provided, use id IFI
*/
return {
id,
name: actor.name || id
};
},

_getIdFromActor(actor) {
const { openid, mbox, mbox_sha1sum, account } = actor;
if (openid) return openid;
if (mbox) return mbox;
if (mbox_sha1sum) return mbox_sha1sum;
if (account?.homePage && account?.name) {
return `${account.homePage}:${account.name}`;
}
return null;
}

}

export default OfflineStorageHandler;
Loading