diff --git a/packages/user-activity-broadcaster/CHANGELOG.md b/packages/user-activity-broadcaster/CHANGELOG.md new file mode 100644 index 00000000..4a053c75 --- /dev/null +++ b/packages/user-activity-broadcaster/CHANGELOG.md @@ -0,0 +1,23 @@ +# Changelog + +This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). + +# 0.1.0-alpha.0 (2024-10-22) + + +### Features + +* **user-activity-broadcaster:** adding changelog file EB-719 ([1607004](https://github.com/Availity/sdk-js/commit/16070049522d8db8401d71f7d5d074dc0bc213c4)) +* **user-activity-broadcaster:** adding ignore because we're not using typescript EB-719 ([b66e9b8](https://github.com/Availity/sdk-js/commit/b66e9b87c2dcd305cd1ccbba5980e7550cc1bd70)) +* **user-activity-broadcaster:** adding package EB-719 ([1213b58](https://github.com/Availity/sdk-js/commit/1213b58c37fcec8f5f6298e6e66103150a9db61e)) + + + +# 0.1.0-alpha.0 (2024-10-22) + + +### Features + +* **user-activity-broadcaster:** adding changelog file EB-719 ([1607004](https://github.com/Availity/sdk-js/commit/16070049522d8db8401d71f7d5d074dc0bc213c4)) +* **user-activity-broadcaster:** adding ignore because we're not using typescript EB-719 ([b66e9b8](https://github.com/Availity/sdk-js/commit/b66e9b87c2dcd305cd1ccbba5980e7550cc1bd70)) +* **user-activity-broadcaster:** adding package EB-719 ([1213b58](https://github.com/Availity/sdk-js/commit/1213b58c37fcec8f5f6298e6e66103150a9db61e)) diff --git a/packages/user-activity-broadcaster/README.md b/packages/user-activity-broadcaster/README.md new file mode 100644 index 00000000..9fbb65c7 --- /dev/null +++ b/packages/user-activity-broadcaster/README.md @@ -0,0 +1,25 @@ +# @availity/user-activity-broadcaster + +> This package broadcasts user activity to the navigation. + +[![Version](https://img.shields.io/npm/v/@availity/user-activity-broadcaster.svg?style=for-the-badge)](https://www.npmjs.com/package/@availity/user-activity-broadcaster) +[![NPM Downloads](https://img.shields.io/npm/dt/@availity/user-activity-broadcaster.svg?style=for-the-badge)](https://www.npmjs.com/package/@availity/user-activity-broadcaster) +[![Dependecy Status](https://img.shields.io/librariesio/release/npm/@availity/user-activity-broadcaster?style=for-the-badge)](https://github.com/Availity/sdk-js/blob/master/packages/user-activity-broadcaster/package.json) + +## Installation + +### NPM + +```bash +npm install @availity/user-activity-broadcaster +``` + +### Yarn + +```bash +yarn add @availity/user-activity-broadcaster +``` + +## Usage + +> All you have to do is include this as a dependency and import it into the root of your web application. diff --git a/packages/user-activity-broadcaster/jest.config.js b/packages/user-activity-broadcaster/jest.config.js new file mode 100644 index 00000000..98dbc596 --- /dev/null +++ b/packages/user-activity-broadcaster/jest.config.js @@ -0,0 +1,7 @@ +const global = require('../../jest.config'); + +module.exports = { + ...global, + displayName: 'user-activity-broadcaster', + coverageDirectory: '../../coverage/user-activity-broadcaster', +}; diff --git a/packages/user-activity-broadcaster/package.json b/packages/user-activity-broadcaster/package.json new file mode 100644 index 00000000..08d12b94 --- /dev/null +++ b/packages/user-activity-broadcaster/package.json @@ -0,0 +1,26 @@ +{ + "name": "@availity/user-activity-broadcaster", + "version": "0.1.0-alpha.0", + "description": "This package broacasts user activity to the navigation.", + "main": "src/user-activity-broadcaster.js", + "keywords": [], + "author": "Joe Spanbauer ", + "engines": { + "node": "^18.0.0 || ^20.0.0" + }, + "scripts": { + "build": "tsup src/index.js --format esm,cjs --dts", + "dev": "tsup src/index.js --format esm,cjs --watch --dts", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "clean": "rm -rf node_modules && rm -rf dist", + "publish": "yarn npm publish --tolerate-republish --access public" + }, + "license": "MIT", + "devDependencies": { + "tsup": "^7.2.0" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/user-activity-broadcaster/project.json b/packages/user-activity-broadcaster/project.json new file mode 100644 index 00000000..1d616949 --- /dev/null +++ b/packages/user-activity-broadcaster/project.json @@ -0,0 +1,39 @@ +{ + "name": "@availity/user-activity-broadcaster", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/resolve-url"], + "options": { + "jestConfig": "packages/user-activity-broadcaster/jest.config.js" + } + }, + "version": { + "executor": "@jscutlery/semver:version", + "options": { + "preset": "angular", + "commitMessageFormat": "chore(user-activity-broadcaster): release version ${version} [skip ci]", + "tagPrefix": "{projectName}@", + "baseBranch": "master", + "trackDeps": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "eslintConfig": ".eslintrc.yaml", + "silent": false, + "fix": false, + "cache": true, + "cacheLocation": "./node_modules/.cache/user-activity-broadcaster/.eslintcache", + "maxWarnings": -1, + "quiet": false, + "noEslintrc": false, + "hasTypeAwareRules": true, + "cacheStrategy": "metadata" + } + } + } +} diff --git a/packages/user-activity-broadcaster/src/index.d.ts b/packages/user-activity-broadcaster/src/index.d.ts new file mode 100644 index 00000000..4f36ee13 --- /dev/null +++ b/packages/user-activity-broadcaster/src/index.d.ts @@ -0,0 +1 @@ +/* eslint-disable unicorn/no-empty-file */ diff --git a/packages/user-activity-broadcaster/src/index.js b/packages/user-activity-broadcaster/src/index.js new file mode 100644 index 00000000..5d16eb3d --- /dev/null +++ b/packages/user-activity-broadcaster/src/index.js @@ -0,0 +1,51 @@ +const MINUTE = 60 * 1000 +const interval = MINUTE * 5 +export const eventName = 'user_activity' + +// Must be a dynamic object to test this +export const lastActivity = {} + +export const getTargetOrigin = (origin = window.location.origin) => { + // Setup targetOrigin to alternate origin (because the same origin already works) + if (origin) { + if (origin.includes('apps')) { + return origin.replace('apps', 'essentials') + } + + if (origin.includes('essentials')) { + return origin.replace('essentials', 'apps') + } + } + + return undefined +} + +const targetOrigin = getTargetOrigin() + +// PostMessage Logic +export const handleActivityUpdate = () => { + window.top.postMessage({ + event: eventName, + time: lastActivity.time + }, targetOrigin) +} + +// Debounce Logic +let activityIntervalId = setInterval(handleActivityUpdate, interval) +// Re-assignable for testing +export const updateInterval = (newInterval) => { + clearInterval(activityIntervalId) + activityIntervalId = setInterval(handleActivityUpdate, newInterval) +} + +// Event Handlers +export const handleActivity = () => { + lastActivity.time = Date.now().toString() +} + +// Add ability to test handleActivity and events +export const addEventListeners = () => { + document.addEventListener('mousedown', handleActivity) + document.addEventListener('keydown', handleActivity) +} +addEventListeners() diff --git a/packages/user-activity-broadcaster/src/tests/index.test.js b/packages/user-activity-broadcaster/src/tests/index.test.js new file mode 100644 index 00000000..8ea3d15e --- /dev/null +++ b/packages/user-activity-broadcaster/src/tests/index.test.js @@ -0,0 +1,76 @@ +const userActivityBroadcaster = require('../index') + +const { + getTargetOrigin, + handleActivity, + updateInterval, + addEventListeners, + lastActivity +} = userActivityBroadcaster + +describe('user-activity-broadcaster', () => { + describe('targetOrigin', () => { + test('essentials.availity.com origin should have targetOrigion of apps', () => { + const testOrigin = 'essentials.availity.com' + const expected = 'apps.availity.com' + + const targetOrigin = getTargetOrigin(testOrigin) + + expect(targetOrigin).toBe(expected) + }) + + test('apps.availity.com origin should have targetOrigion of essentials', () => { + const testOrigin = 'apps.availity.com' + const expected = 'essentials.availity.com' + + const targetOrigin = getTargetOrigin(testOrigin) + + expect(targetOrigin).toBe(expected) + }) + }) + + test('should call handleActivityUpdate every interval', async () => { + const testInterval = 1000 + const waitTime = 2999 + const expectedCallCount = 2 + + window.top.postMessage = () => {} + + const spy = jest.spyOn(userActivityBroadcaster, 'handleActivityUpdate') + + updateInterval(testInterval) + + await new Promise((resolve) => { + setTimeout(() => { + resolve() + }, waitTime) + }) + + expect(spy).toHaveBeenCalledTimes(expectedCallCount) + }) + + test('keydown events call handleActivity', async () => { + const spy = jest.spyOn(userActivityBroadcaster, 'handleActivity') + + addEventListeners() + + document.dispatchEvent(new MouseEvent('keydown')) + + expect(spy).toHaveBeenCalled() + }) + + test('mousedown events call handleActivity', async () => { + const spy = jest.spyOn(userActivityBroadcaster, 'handleActivity') + + addEventListeners() + + document.dispatchEvent(new MouseEvent('mousedown')) + + expect(spy).toHaveBeenCalled() + }) + + test('handleActivity should update handleActivity', () => { + handleActivity() + expect(lastActivity.time).toBeDefined() + }) +}) diff --git a/packages/user-activity-broadcaster/tsconfig.json b/packages/user-activity-broadcaster/tsconfig.json new file mode 100644 index 00000000..b70853b0 --- /dev/null +++ b/packages/user-activity-broadcaster/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../../tsconfig.json", + "include": ["."], + "exclude": ["dist", "build", "node_modules"] +} diff --git a/packages/user-activity-broadcaster/tsconfig.spec.json b/packages/user-activity-broadcaster/tsconfig.spec.json new file mode 100644 index 00000000..a85a3f59 --- /dev/null +++ b/packages/user-activity-broadcaster/tsconfig.spec.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "allowJs": true + }, + "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] +} diff --git a/yarn.lock b/yarn.lock index 0223710e..8f291e03 100644 --- a/yarn.lock +++ b/yarn.lock @@ -446,6 +446,14 @@ __metadata: languageName: unknown linkType: soft +"@availity/user-activity-broadcaster@workspace:packages/user-activity-broadcaster": + version: 0.0.0-use.local + resolution: "@availity/user-activity-broadcaster@workspace:packages/user-activity-broadcaster" + dependencies: + tsup: ^7.2.0 + languageName: unknown + linkType: soft + "@availity/yup@workspace:packages/yup": version: 0.0.0-use.local resolution: "@availity/yup@workspace:packages/yup"