diff --git a/src/app.js b/src/app.js
index 75586bbd3..c37837590 100644
--- a/src/app.js
+++ b/src/app.js
@@ -41,6 +41,7 @@ const modules = [
'graphdb.framework.core.directives.uppercased',
'graphdb.framework.core.directives.prop-indeterminate',
'graphdb.framework.guides.services',
+ 'graphdb.framework.core.services.licenseService',
'graphdb.framework.core.directives.operationsstatusesmonitor',
'graphdb.framework.core.directives.autocomplete',
'ngCustomElement'
@@ -193,8 +194,8 @@ const moduleDefinition = function (productInfo, translations) {
workbench.constant('productInfo', productInfo);
// we need to inject $jwtAuth here in order to init the service before everything else
- workbench.run(['$rootScope', '$route', 'toastr', '$sce', '$translate', 'ThemeService', 'WorkbenchSettingsStorageService', 'LSKeys', 'GuidesService',
- function ($rootScope, $route, toastr, $sce, $translate, ThemeService, WorkbenchSettingsStorageService, LSKeys, GuidesService) {
+ workbench.run(['$rootScope', '$route', 'toastr', '$sce', '$translate', 'ThemeService', 'WorkbenchSettingsStorageService', 'LSKeys', 'GuidesService', '$licenseService',
+ function ($rootScope, $route, toastr, $sce, $translate, ThemeService, WorkbenchSettingsStorageService, LSKeys, GuidesService, $licenseService) {
$rootScope.$on('$routeChangeSuccess', function () {
updateTitleAndHelpInfo();
@@ -222,6 +223,9 @@ const moduleDefinition = function (productInfo, translations) {
ThemeService.applyDarkThemeMode();
GuidesService.init();
+
+ // Checks license status and adds tracking code when free/evaluation license
+ $licenseService.checkLicenseStatus();
}]);
workbench.filter('titlecase', function () {
diff --git a/src/js/angular/controllers.js b/src/js/angular/controllers.js
index bc2dc6f39..73cfffa44 100644
--- a/src/js/angular/controllers.js
+++ b/src/js/angular/controllers.js
@@ -92,7 +92,7 @@ function homeCtrl($scope, $rootScope, $http, $repositories, $jwtAuth, $licenseSe
}
}
- $scope.$on('autocompleteStatus', function() {
+ $scope.$on('autocompleteStatus', function () {
checkAutocompleteStatus();
});
@@ -202,7 +202,7 @@ function mainCtrl($scope, $menuItems, $jwtAuth, $http, toastr, $location, $repos
$scope.initTutorial();
});
- $scope.checkMenu = debounce(function() {
+ $scope.checkMenu = debounce(function () {
return $('.main-menu').hasClass('collapsed');
}, 250, {trailing: false});
@@ -324,7 +324,7 @@ function mainCtrl($scope, $menuItems, $jwtAuth, $http, toastr, $location, $repos
$scope.isFreeAccessEnabled = function () {
return $jwtAuth.isFreeAccessEnabled();
};
- $scope.hasExternalAuthUser = function() {
+ $scope.hasExternalAuthUser = function () {
return $jwtAuth.hasExternalAuthUser();
};
$scope.isDefaultAuthEnabled = function () {
@@ -401,7 +401,7 @@ function mainCtrl($scope, $menuItems, $jwtAuth, $http, toastr, $location, $repos
return $repositories.isActiveRepoFedXType();
};
- $scope.isLicenseValid = function() {
+ $scope.isLicenseValid = function () {
return $licenseService.isLicenseValid();
};
@@ -409,7 +409,7 @@ function mainCtrl($scope, $menuItems, $jwtAuth, $http, toastr, $location, $repos
* Sets attrs property in the directive
* @param attrs
*/
- $scope.setAttrs = function(attrs) {
+ $scope.setAttrs = function (attrs) {
$scope.attrs = attrs;
};
@@ -424,7 +424,7 @@ function mainCtrl($scope, $menuItems, $jwtAuth, $http, toastr, $location, $repos
if ($scope.attrs) {
$scope.isRestricted =
$scope.attrs.hasOwnProperty('license') && !$licenseService.isLicenseValid() ||
- $scope.attrs.hasOwnProperty('write') && $scope.isSecurityEnabled() && !$scope.canWriteActiveRepo()||
+ $scope.attrs.hasOwnProperty('write') && $scope.isSecurityEnabled() && !$scope.canWriteActiveRepo() ||
$scope.attrs.hasOwnProperty('ontop') && $scope.isActiveRepoOntopType() ||
$scope.attrs.hasOwnProperty('fedx') && $scope.isActiveRepoFedXType();
}
@@ -611,7 +611,7 @@ function mainCtrl($scope, $menuItems, $jwtAuth, $http, toastr, $location, $repos
},
{
"title": $translate.instant('main.info.title.create.repo.page'),
- "info": decodeHTML($translate.instant('main.info.create.repo.page', {link:""}))
+ "info": decodeHTML($translate.instant('main.info.create.repo.page', {link: ""}))
},
{
"title": $translate.instant('main.info.title.load.sample.dataset'),
@@ -637,7 +637,7 @@ function mainCtrl($scope, $menuItems, $jwtAuth, $http, toastr, $location, $repos
}, 50);
};
- $scope.getTutorialPageHtml = function(page) {
+ $scope.getTutorialPageHtml = function (page) {
return $sce.trustAsHtml(page.info);
};
@@ -811,6 +811,9 @@ function mainCtrl($scope, $menuItems, $jwtAuth, $http, toastr, $location, $repos
}
});
+ $scope.getProductType = function () {
+ return $licenseService.productType();
+ };
$scope.isEnterprise = function () {
return $scope.getProductType() === "enterprise";
@@ -827,24 +830,21 @@ function mainCtrl($scope, $menuItems, $jwtAuth, $http, toastr, $location, $repos
return _.indexOf(editions, $scope.getProductType()) >= 0;
};
- $scope.showLicense = function() {
- return $licenseService.showLicense;
+ $scope.showLicense = function () {
+ return $licenseService.showLicense();
};
- $scope.getLicense = function() {
- return $licenseService.license;
+ $scope.getLicense = function () {
+ return $licenseService.license();
};
- $scope.isLicenseHardcoded = function() {
- return $licenseService.isLicenseHardcoded;
+ $scope.isLicenseHardcoded = function () {
+ return $licenseService.isLicenseHardcoded();
};
- $scope.getProductType = function() {
- return $licenseService.productType;
- };
- $scope.getProductTypeHuman = function() {
- return $licenseService.productTypeHuman;
+ $scope.getProductTypeHuman = function () {
+ return $licenseService.productTypeHuman();
};
@@ -977,17 +977,17 @@ function uxTestCtrl($scope, $repositories, toastr, ModalService) {
});
};
- $scope.demoToast = function(alertType, secondArg=true) {
+ $scope.demoToast = function (alertType, secondArg = true) {
toastr[alertType]('Consectetur adipiscing elit. Sic transit gloria mundi.',
secondArg ? 'Lorem ipsum dolor sit amet' : undefined,
{timeOut: 300000, extendedTimeOut: 300000});
};
- $scope.clearToasts = function() {
+ $scope.clearToasts = function () {
toastr.clear();
};
- $scope.clearRepo = function() {
+ $scope.clearRepo = function () {
$repositories.setRepository('');
};
}
diff --git a/src/js/angular/core/services/license.service.js b/src/js/angular/core/services/license.service.js
index a03a28351..259c7d05f 100644
--- a/src/js/angular/core/services/license.service.js
+++ b/src/js/angular/core/services/license.service.js
@@ -1,47 +1,202 @@
+const EVALUATION_TYPE_1 = "this is an evaluation license";
+const EVALUATION_TYPE_2 = "evaluation";
+
angular.module('graphdb.framework.core.services.licenseService', [])
- .service('$licenseService', ['$rootScope', 'LicenseRestService', '$translate', licenseService]);
-
-function licenseService($rootScope, LicenseRestService, $translate) {
-
- const that = this;
-
- this.checkLicenseStatus = function () {
- that.loadingLicense = true;
- LicenseRestService.getHardcodedLicense().success(function (res) {
- that.isLicenseHardcoded = (res === 'true');
- }).error(function () {
- that.isLicenseHardcoded = true;
- }).then(function () {
- LicenseRestService.getLicenseInfo().then(function (res) {
- that.license = res.data;
- that.showLicense = true;
- that.loadingLicense = false;
- updateProductType(that.license);
- }, function () {
- that.license = {message: $translate.instant('no.license.set.msg'), valid: false};
- that.showLicense = true;
- that.loadingLicense = false;
- updateProductType(that.license);
+ .service('$licenseService', ['$window', '$document', 'LicenseRestService', '$translate', licenseService]);
+
+/**
+ * Service to manage and check license status, types, and tracking permissions.
+ * @param {object} $window - Angular service to interact with the window object.
+ * @param {object} $document - Angular service to interact with the document object.
+ * @param {object} LicenseRestService - Service for fetching license information from the backend.
+ * @param {object} $translate - Angular translate service for internationalization.
+ * @return {object} An object exposing methods for checking and managing license information:
+ * - `checkLicenseStatus`: Fetches license status and updates local variables.
+ * - `isLicenseValid`: Checks if the current license is valid.
+ * - `license`: Returns the current license object.
+ * - `loadingLicense`: Returns whether the license is being loaded.
+ * - `isLicenseHardcoded`: Checks if the license is hardcoded.
+ * - `showLicense`: Determines if the license should be shown in the UI.
+ * - `productType`: Returns the current product type associated with the license.
+ * - `productTypeHuman`: Returns a human-readable version of the product type.
+ */
+
+function licenseService($window, $document, LicenseRestService, $translate) {
+ let _license = undefined;
+ let _loadingLicense = false;
+ let _isLicenseHardcoded = false;
+ let _showLicense = false;
+ let _productType = undefined;
+ let _productTypeHuman = undefined;
+
+ /**
+ * Fetches license status and updates local variables related to license and product type.
+ * @return {Promise} A promise that resolves once the license status is fetched and processed.
+ */
+ const checkLicenseStatus = () => {
+ _loadingLicense = true;
+ return LicenseRestService.getHardcodedLicense()
+ .then((res) => {
+ _isLicenseHardcoded = (res === 'true');
+ return LicenseRestService.getLicenseInfo();
+ })
+ .then((res) => {
+ _license = res.data;
+ })
+ .catch(() => {
+ _isLicenseHardcoded = true;
+ _license = {
+ message: $translate.instant('no.license.set.msg'),
+ valid: false
+ };
+ })
+ .finally(() => {
+ updateProductType(_license);
+ updateTracking(_license);
+ _showLicense = true;
+ _loadingLicense = false;
});
- });
- };
-
- const updateProductType = function (license) {
- that.productType = license.productType;
- if (that.productType === "standard") {
- that.productTypeHuman = "Standard";
- } else if (that.productType === "enterprise") {
- that.productTypeHuman = "Enterprise";
- } else if (that.productType === "free") {
- that.productTypeHuman = "Free";
- } else if (that.productType === "graphdb") {
- that.productTypeHuman = "GraphDB";
+ };
+
+ const updateProductType = (license) => {
+ _productType = license.productType;
+ if (_productType === "standard") {
+ _productTypeHuman = "Standard";
+ } else if (_productType === "enterprise") {
+ _productTypeHuman = "Enterprise";
+ } else if (_productType === "free") {
+ _productTypeHuman = "Free";
+ } else if (_productType === "graphdb") {
+ _productTypeHuman = "GraphDB";
}
};
- this.checkLicenseStatus();
+ /**
+ * Updates the tracking behavior based on the user's tracking consent or permission.
+ * @private
+ */
+ const updateTracking = () => {
+ if (isTrackingAllowed()) {
+ addGoogleTagManagerScript();
+ } else {
+ removeGoogleTagManagerScripts();
+ }
+ };
+
+ /**
+ * Determines if tracking is allowed based on license status and product type.
+ * @return {boolean} A promise that resolves to a boolean indicating if tracking is allowed.
+ */
+ const isTrackingAllowed = () => {
+ const licenseTypeOfUse = _license && _license.typeOfUse.toLowerCase();
+ return _productType === "free" ||
+ licenseTypeOfUse === EVALUATION_TYPE_1 ||
+ licenseTypeOfUse === EVALUATION_TYPE_2;
+ };
+
+ /**
+ * Adds the Google Tag Manager (GTM) script to the document's head if it is not already present.
+ * This function creates a new script element for GTM and appends it to the document's head.
+ * @private
+ */
+ const addGoogleTagManagerScript = () => {
+ if (!gtmScriptExists()) {
+ const dataLayerScript = $document[0].createElement('script');
+ dataLayerScript.text = "(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'}); var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:''; j.async=true; j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl; f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-WBP6C6Z4');";
+ $document[0].getElementsByTagName('head')[0].appendChild(dataLayerScript);
+ }
+ };
+
+ /**
+ * Checks if a Google Tag Manager (GTM) script is already present in the document.
+ *
+ * When the GTM script is injected, it dynamically adds additional scripts depending on how many tags
+ * are configured within your GTM container. These scripts are usually inserted into the `` section,
+ * but it’s better to search through the entire document to ensure all related GTM scripts are found.
+ *
+ * This function searches through all `