Skip to content

Commit

Permalink
RMET-3477 :: OutSystems Wrapper :: Add OneSignal Plugin Manager (#35)
Browse files Browse the repository at this point in the history
- adds code specific to outsystems lifecycle aka one signal plugin manager
- adds the code that will be in outsystems wrapper's javascript nodes
- add sonar cloud integration for typescript files

https://outsystemsrd.atlassian.net/browse/RMET-3477
  • Loading branch information
OS-martacarlos authored Jun 21, 2024
1 parent e01bcc2 commit 83b97a3
Show file tree
Hide file tree
Showing 23 changed files with 647 additions and 1 deletion.
32 changes: 32 additions & 0 deletions .github/workflows/run_unit_tests_workflow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Run Unit Tests

on:
workflow_dispatch:
push:
branches: [ main, development ]
pull_request:
branches: [ main, development ]

jobs:
test:
name: Unit-Tests
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 18

- name: Install dependencies
run: npm install

- name: Run tests (with coverage)
run: npm test -- --coverage --ci

- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
env:
SONAR_TOKEN: ${{ secrets. SONAR_TOKEN }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
node_modules
package-lock.json
coverage
14 changes: 14 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// jest.config.js

module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
moduleFileExtensions: ['ts', 'js'],
testMatch: ['**/*.spec.ts'],
transform: {
'^.+\\.tsx?$':['ts-jest', {
tsconfig: 'tsconfig.json',
}]
},
};

10 changes: 10 additions & 0 deletions outsystems/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Changelog
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


### 2024-06-19

- Re-write `OneSignal_Manager` as an UMD module, [RMET-3477](https://outsystemsrd.atlassian.net/browse/RMET-3477)
19 changes: 19 additions & 0 deletions outsystems/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# OutSystems Wrapper


Welcome! Here lies the code related to the OutSystems Wrapper *aka* the JavaScript code that is present on the OutSystems Plugin, downloadable from Forge.

## Structure

In an OutSystems Plugin, there's two ways to host JavaScript code: JavaScript Nodes and script files.

* `nodes` holds the JavaScript code inside a OutSystems Javascript node, with the same name
* `scripts` JavaScript files that the plugin imports

And lastly, but not least, the wrapper differs depending on the platform (ODC vs O11) and, as such, so does this folder.

## How is it used

This repository holds the code related to the OneSignal Plugin's module, `OneSignal_Manager`. Up until 2024, this manager was counting on the existence of RequireJS in an OutSystems' App Runtime to create this module. Since RequireJS will no longer be part of OutSystems' Runtime, `OneSignal_Manager` needed to be updated. The approach was to create an UMD module, available to any plugin/app that imports `OneSignal_Manager`.

Additionally, this module assumes the Common Plugin's `PluginManager` is imported in the app.
18 changes: 18 additions & 0 deletions outsystems/nodes/O11/initOneSignal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require(["OneSignalPluginManager"], function(oneSignalMgr){
var builder = window.plugins.OneSignal.startInit($parameters.ApiKey);
builder.handleNotificationReceived(oneSignalMgr.notificationReceivedDelegate);
builder.handleNotificationOpened(oneSignalMgr.notificationOpenedDelegate);
builder.inFocusDisplaying($parameters.InFocusDisplayOption);

// Set your iOS Settings
var iosSettings = {};
iosSettings["kOSSettingsKeyAutoPrompt"] = true;
iosSettings["kOSSettingsKeyInAppLaunchURL"] = false;

builder.iOSSettings(iosSettings);

builder.endInit();

$resolve();

});
37 changes: 37 additions & 0 deletions outsystems/nodes/O11/registerDispatcher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
require(["PluginManager","OneSignalPluginManager"], function(module, oneSignalMgr){

var onReady = function(scope) {
console.log("onReady scope");
scope.handleNotificationOpened = scope.newCallback(function(jsonData) {
try{
console.log("handleNotificationOpened");
window.oneSignalEvents.triggerOnDispatchNotificationOpened(jsonData);
} catch(err) {
console.error(err);
}
});

scope.handleNotificationReceived = scope.newCallback(function(jsonData) {
try{
console.log("handleNotificationReceived");
window.oneSignalEvents.triggerOnDispatchNotificationReceived(jsonData);
} catch(err) {
console.error(err);
}
});

oneSignalMgr.setNotificationReceivedCallback(scope.handleNotificationReceived);
oneSignalMgr.setNotificationOpenedCallback(scope.handleNotificationOpened);

}

var onDestroy = function(scope) {
console.log("onDestroy scope");
oneSignalMgr.unregisterReceivedCallback(scope.handleNotificationReceived);
oneSignalMgr.unregisterOpenedCallback(scope.handleNotificationOpened);
}

module.createScope(`OneSignalPlugin_${$parameters.Token}`, onReady, onDestroy);

$resolve();
});
4 changes: 4 additions & 0 deletions outsystems/nodes/O11/unregisterPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require(["PluginManager"], function(module){
module.destroyScope(`OneSignalPlugin_${$parameters.Token}`);
$resolve();
});
13 changes: 13 additions & 0 deletions outsystems/nodes/ODC/initOneSignal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var builder = window.plugins.OneSignal.startInit($parameters.ApiKey);
builder.handleNotificationReceived(OSOneSignal.notificationReceivedDelegate);
builder.handleNotificationOpened(OSOneSignal.notificationOpenedDelegate);
builder.inFocusDisplaying($parameters.InFocusDisplayOption);

// Set your iOS Settings
var iosSettings = {};
iosSettings["kOSSettingsKeyAutoPrompt"] = true;
iosSettings["kOSSettingsKeyInAppLaunchURL"] = false;

builder.iOSSettings(iosSettings);

builder.endInit();
32 changes: 32 additions & 0 deletions outsystems/nodes/ODC/registerDispatcher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
var onReady = function(scope) {
console.log("onReady scope");
scope.handleNotificationOpened = scope.newCallback(function(jsonData) {
try{
console.log("handleNotificationOpened");
window.oneSignalEvents.triggerOnDispatchNotificationOpened(jsonData);
} catch(err) {
console.error(err);
}
});

scope.handleNotificationReceived = scope.newCallback(function(jsonData) {
try{
console.log("handleNotificationReceived");
window.oneSignalEvents.triggerOnDispatchNotificationReceived(jsonData);
} catch(err) {
console.error(err);
}
});

OSOneSignal.setNotificationReceivedCallback(scope.handleNotificationReceived);
OSOneSignal.setNotificationOpenedCallback(scope.handleNotificationOpened);

}

var onDestroy = function(scope) {
console.log("onDestroy scope");
OSOneSignal.unregisterReceivedCallback(scope.handleNotificationReceived);
OSOneSignal.unregisterOpenedCallback(scope.handleNotificationOpened);
}

OSCommonPlugin.PluginManager.createScope(`OneSignalPlugin_${$parameters.Token}`, onReady, onDestroy);
1 change: 1 addition & 0 deletions outsystems/nodes/ODC/unregisterPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
OSCommonPlugin.PluginManager.destroyScope(`OneSignalPlugin_${$parameters.Token}`);
68 changes: 68 additions & 0 deletions outsystems/scripts/O11/manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
define("OneSignalPluginManager", ["exports"], function(exports) {

var notificationReceivedCallback = [];
var notificationOpenedCallback = [];

/**
* Public delegate for OneSignal's handleNotificationReceived
*/
function notificationReceivedDelegate(jsonData) {
notificationReceivedCallback.forEach(function(callback){
callback.call(undefined, jsonData);
});
}

/**
* Public delegate for OneSignal's handleNotificationOpened
*/
function notificationOpenedDelegate(jsonData) {
notificationOpenedCallback.forEach(function(callback){
callback.call(undefined, jsonData);
});
}

/**
* Sets the current callback for OneSignal's Notification Received events.
*/
function setNotificationReceivedCallback(callback) {
notificationReceivedCallback.push(callback);
}

/**
* Sets the current callback for OneSignal's Notification Opened events.
*/
function setNotificationOpenedCallback(callback) {
notificationOpenedCallback.push(callback);
}

/**
* Unregister the old callback of OneSignal's Notification Received
*/
function unregisterReceivedCallback(callback) {
var cbIndex = notificationReceivedCallback.indexOf(callback);
if(cbIndex >= 0) {
notificationReceivedCallback[cbIndex] = undefined;
delete notificationReceivedCallback[cbIndex];
}
}

/**
* Unregister the old callback of OneSignal's Notification Opened
*/
function unregisterOpenedCallback(callback) {
var cbIndex = notificationOpenedCallback.indexOf(callback);
if(cbIndex >= 0) {
notificationOpenedCallback[cbIndex] = undefined;
delete notificationOpenedCallback[cbIndex];
}
}

exports.notificationReceivedDelegate = notificationReceivedDelegate;
exports.notificationOpenedDelegate = notificationOpenedDelegate;

exports.setNotificationReceivedCallback = setNotificationReceivedCallback;
exports.setNotificationOpenedCallback = setNotificationOpenedCallback;

exports.unregisterReceivedCallback = unregisterReceivedCallback;
exports.unregisterOpenedCallback = unregisterOpenedCallback;
});
1 change: 1 addition & 0 deletions outsystems/scripts/ODC/definitions.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type OneSignalCallback = (...args: any[]) => void;
26 changes: 26 additions & 0 deletions outsystems/scripts/ODC/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { OneSignalCallback } from './definitions';

/**
* Public delegate for OneSignal's handleNotificationReceived
*/
export declare function notificationReceivedDelegate(jsonData: any): void;
/**
* Public delegate for OneSignal's handleNotificationOpened
*/
export declare function notificationOpenedDelegate(jsonData: any): void;
/**
* Sets the current callback for OneSignal's Notification Received events.
*/
export declare function setNotificationReceivedCallback(callback: OneSignalCallback): void;
/**
* Sets the current callback for OneSignal's Notification Opened events.
*/
export declare function setNotificationOpenedCallback(callback: OneSignalCallback): void;
/**
* Unregister the old callback of OneSignal's Notification Received
*/
export declare function unregisterReceivedCallback(callback: OneSignalCallback): void;
/**
* Unregister the old callback of OneSignal's Notification Opened
*/
export declare function unregisterOpenedCallback(callback: OneSignalCallback): void;
42 changes: 42 additions & 0 deletions outsystems/scripts/ODC/manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
(function(global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.OSOneSignal = {}));
})(this, function(exports2) {
"use strict";
let notificationReceivedCallback = [];
let notificationOpenedCallback = [];
function notificationReceivedDelegate(jsonData) {
notificationReceivedCallback.forEach(function(callback) {
callback(jsonData);
});
}
function notificationOpenedDelegate(jsonData) {
notificationOpenedCallback.forEach(function(callback) {
callback(jsonData);
});
}
function setNotificationReceivedCallback(callback) {
notificationReceivedCallback.push(callback);
}
function setNotificationOpenedCallback(callback) {
notificationOpenedCallback.push(callback);
}
function unregisterReceivedCallback(callback) {
let cbIndex = notificationReceivedCallback.indexOf(callback);
if (cbIndex >= 0) {
notificationReceivedCallback.splice(cbIndex, 1);
}
}
function unregisterOpenedCallback(callback) {
let cbIndex = notificationOpenedCallback.indexOf(callback);
if (cbIndex >= 0) {
notificationOpenedCallback.splice(cbIndex, 1);
}
}
exports2.notificationOpenedDelegate = notificationOpenedDelegate;
exports2.notificationReceivedDelegate = notificationReceivedDelegate;
exports2.setNotificationOpenedCallback = setNotificationOpenedCallback;
exports2.setNotificationReceivedCallback = setNotificationReceivedCallback;
exports2.unregisterOpenedCallback = unregisterOpenedCallback;
exports2.unregisterReceivedCallback = unregisterReceivedCallback;
Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
});
47 changes: 47 additions & 0 deletions outsystems/scripts/OneSignal_Events.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Due to the nature of OutSystems Screens' & Blocks' Lifecyle
* We keep track of the active callbacks (valid client actions) via this window object
*/
(function() {

var callbacks = {
onDispatchNotificationOpened: null,
onDispatchNotificationReceived: null
}

var token;

var OneSignalEventsSync = {
registerCallbacks: function (onDispatchNotificationReceived, onDispatchNotificationOpened){
token = (new Date()).getTime().toString();

callbacks.onDispatchNotificationReceived = onDispatchNotificationReceived;
callbacks.onDispatchNotificationOpened = onDispatchNotificationOpened;

return token
},

unregisterCallbacks: function (previousToken){
if(token === previousToken) {
callbacks = null;
}
},

triggerOnDispatchNotificationReceived: function (json){
if(callbacks && callbacks.onDispatchNotificationReceived) {
callbacks.onDispatchNotificationReceived(JSON.stringify(json));
}
},

triggerOnDispatchNotificationOpened: function (json){
if(callbacks && callbacks.onDispatchNotificationOpened) {
callbacks.onDispatchNotificationOpened(JSON.stringify(json));
}
}

}

if (!window.oneSignalEvents) {
window.oneSignalEvents = OneSignalEventsSync;
}
})();
Loading

0 comments on commit 83b97a3

Please sign in to comment.