From 535014944ef03c6bc948ff8b7b8f29a60ee31527 Mon Sep 17 00:00:00 2001 From: boyan-tonchev <108174872+boyan-tonchev@users.noreply.github.com> Date: Wed, 3 Jul 2024 14:32:03 +0300 Subject: [PATCH] GDB-10382: Default message info not displayed when the reinitialized function is called (#1455) * GDB-10382: Default message info not displayed when the reinitialized function is called What - The YASR results and YASQE buttons are not cleared when the repository is changed from the repository view; - The Infer and sameAs buttons are disabled when the default user settings are false, and the chosen repositories is ontop. Why - The YASGUI is a third-party library and does not know about repository changes. Managing repository changes is a function of the GraphDB Workbench; - A check for the repository type was missed when YASGUI was created. How - Added functionality to persist the repository used by the YASGUI instance. When the YASGUI is initialized, a clearState flag is passed to the configuration. The value of the flag is based on whether the current repository is different from the last one used by YASGUI. If the repositories differ, the flag is set to true, which triggers the clearing of the YASR results and the YASQE buttons; - Added check if repository is ontope when configure the YASGUI. A check has been added to verify if the repository is ontop when configuring the YASGUI. # Additional work The repositoryChangedHandler is called twice when the SPARQL view controller is created, causing the YASGUI component to initialize twice. The first one call is without repository. A check has been added to skip the initialization of YASGUI if the repository is not set. --------- Co-authored-by: desislava.borisova --- package-lock.json | 14 +-- package.json | 2 +- .../ontotext-yasgui/ontotext-yasgui-config.js | 7 ++ src/js/angular/sparql-editor/controllers.js | 97 ++++++++++++------- src/js/angular/utils/local-storage-adapter.js | 3 +- .../expand-results-over-sameas.spec.js | 2 +- 6 files changed, 79 insertions(+), 46 deletions(-) diff --git a/package-lock.json b/package-lock.json index e22c869e5..157f3be5d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,7 +35,7 @@ "ng-file-upload": "^12.2.13", "ng-tags-input": "^3.2.0", "oclazyload": "^1.1.0", - "ontotext-yasgui-web-component": "1.3.14", + "ontotext-yasgui-web-component": "1.3.15", "shepherd.js": "^11.2.0" }, "devDependencies": { @@ -9137,9 +9137,9 @@ } }, "node_modules/ontotext-yasgui-web-component": { - "version": "1.3.14", - "resolved": "https://registry.npmjs.org/ontotext-yasgui-web-component/-/ontotext-yasgui-web-component-1.3.14.tgz", - "integrity": "sha512-FTuIoKypwi1w2ogFobuQyU3F6kzaflM5HGZqJ2uNs6u26FKWIH0CdDDGlOGoro7/b4l6nrEBKH6FWcFte/lq5Q==", + "version": "1.3.15", + "resolved": "https://registry.npmjs.org/ontotext-yasgui-web-component/-/ontotext-yasgui-web-component-1.3.15.tgz", + "integrity": "sha512-8PKne4gJSKbZuewPq8WVKZTcjvPoVIhyNdGrNYGlfIpvnt/wUuuNgVJkFXsVRMJ6+fucAA+WSr5D/m5PdTUeVg==", "dependencies": { "@stencil/core": "^2.21.0", "tippy.js": "^6.3.7" @@ -22530,9 +22530,9 @@ } }, "ontotext-yasgui-web-component": { - "version": "1.3.14", - "resolved": "https://registry.npmjs.org/ontotext-yasgui-web-component/-/ontotext-yasgui-web-component-1.3.14.tgz", - "integrity": "sha512-FTuIoKypwi1w2ogFobuQyU3F6kzaflM5HGZqJ2uNs6u26FKWIH0CdDDGlOGoro7/b4l6nrEBKH6FWcFte/lq5Q==", + "version": "1.3.15", + "resolved": "https://registry.npmjs.org/ontotext-yasgui-web-component/-/ontotext-yasgui-web-component-1.3.15.tgz", + "integrity": "sha512-8PKne4gJSKbZuewPq8WVKZTcjvPoVIhyNdGrNYGlfIpvnt/wUuuNgVJkFXsVRMJ6+fucAA+WSr5D/m5PdTUeVg==", "requires": { "@stencil/core": "^2.21.0", "tippy.js": "^6.3.7" diff --git a/package.json b/package.json index 81e7b8c9f..cc467453d 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "ng-file-upload": "^12.2.13", "ng-tags-input": "^3.2.0", "oclazyload": "^1.1.0", - "ontotext-yasgui-web-component": "1.3.14", + "ontotext-yasgui-web-component": "1.3.15", "shepherd.js": "^11.2.0" }, "resolutions": { diff --git a/src/js/angular/models/ontotext-yasgui/ontotext-yasgui-config.js b/src/js/angular/models/ontotext-yasgui/ontotext-yasgui-config.js index fdc20ae4f..a70e0abae 100644 --- a/src/js/angular/models/ontotext-yasgui/ontotext-yasgui-config.js +++ b/src/js/angular/models/ontotext-yasgui/ontotext-yasgui-config.js @@ -153,6 +153,13 @@ export class OntotextYasguiConfig { */ this.immutableSameAs = undefined; + /** + * If the Yasgui state should be cleared to the initial state. Default value is false. + * + * @type {boolean} + */ + this.clearState = false; + /** * If the configured endpoint should be preconfigured to any new opened editor tab. * diff --git a/src/js/angular/sparql-editor/controllers.js b/src/js/angular/sparql-editor/controllers.js index 2dfe06395..5dc4bac51 100644 --- a/src/js/angular/sparql-editor/controllers.js +++ b/src/js/angular/sparql-editor/controllers.js @@ -15,13 +15,13 @@ import {VIEW_SPARQL_EDITOR} from "../models/sparql/constants"; import {CancelAbortingQuery} from "../models/sparql/cancel-aborting-query"; import {QueryMode} from "../models/ontotext-yasgui/query-mode"; import 'angular/core/services/event-emitter-service'; -import {YasguiResetFlags} from "../models/ontotext-yasgui/yasgui-reset-flags"; const modules = [ 'ui.bootstrap', 'graphdb.framework.rest.connectors.service', 'graphdb.framework.externalsync.controllers', - 'graphdb.framework.utils.event-emitter-service' + 'graphdb.framework.utils.event-emitter-service', + 'graphdb.framework.utils.localstorageadapter' ]; angular @@ -44,7 +44,9 @@ SparqlEditorCtrl.$inject = [ 'GuidesService', 'ModalService', 'MonitoringRestService', - 'EventEmitterService']; + 'EventEmitterService', + 'LocalStorageAdapter', + 'LSKeys']; function SparqlEditorCtrl($rootScope, $scope, @@ -61,13 +63,14 @@ function SparqlEditorCtrl($rootScope, GuidesService, ModalService, MonitoringRestService, - EventEmitterService) { + EventEmitterService, + LocalStorageAdapter, + LSKeys) { this.repository = ''; const QUERY_EDITOR_ID = '#query-editor'; - // When the view is loaded the repository change watcher will be triggered. We need to have this flag to prevent - // resetting the yasgui on the first load. This flag will be set to false after the first repository change. - let initialRepoInitialization = true; + let activeRepository = $repositories.getActiveRepository(); + let isOntopRepo = $repositories.isActiveRepoOntopType(); /** * @type {OntotextYasguiConfig} @@ -84,24 +87,29 @@ function SparqlEditorCtrl($rootScope, // ========================= // Public functions // ========================= - $scope.updateConfig = () => { + /** + * Updates the Yasgui configuration + * @param {boolean} clearYasguiState if set to true, the Yasgui will reinitialize and clear all tab results. Queries will remain. + */ + $scope.updateConfig = (clearYasguiState) => { $scope.yasguiConfig = { endpoint: getEndpoint, componentId: VIEW_SPARQL_EDITOR, prefixes: $scope.prefixes, - infer: $scope.inferUserSetting, - sameAs: $scope.sameAsUserSetting, + infer: isOntopRepo || $scope.inferUserSetting, + sameAs: isOntopRepo || $scope.sameAsUserSetting, yasrToolbarPlugins: [exploreVisualGraphYasrToolbarElementBuilder], beforeUpdateQuery: getBeforeUpdateQueryHandler(), outputHandlers: new Map([ [EventDataType.QUERY_EXECUTED, queryExecutedHandler], [EventDataType.REQUEST_ABORTED, requestAbortedHandler] - ]) + ]), + clearState: clearYasguiState !== undefined ? clearYasguiState : false }; }; $scope.getActiveRepositoryNoError = () => { - return $repositories.getActiveRepository(); + return activeRepository; }; // ========================= @@ -124,8 +132,13 @@ function SparqlEditorCtrl($rootScope, return $repositories.resolveSparqlEndpoint(yasqe.getQueryMode()); }; - const initViewFromUrlParams = () => { - $scope.updateConfig(); + /** + * Initializes the editor from the URL parameters. + * @param {boolean} clearYasguiState if set to true, the Yasgui will reinitialize and clear all tab results. Queries will remain. + * The default is false. + */ + const initViewFromUrlParams = (clearYasguiState = false) => { + $scope.updateConfig(clearYasguiState); const queryParams = $location.search(); if (queryParams.hasOwnProperty(RouteConstants.savedQueryName)) { // init new tab from shared saved query link @@ -409,7 +422,7 @@ function SparqlEditorCtrl($rootScope, }; // Initialization and bootstrap - const init = () => { + const init = (clearYasguiState) => { // This script check is required, because of the following scenario: // I am in the SPARQL view; // Then I go to a different view and change the language; @@ -430,12 +443,12 @@ function SparqlEditorCtrl($rootScope, return; } } - Promise.all([$jwtAuth.getPrincipal(), $repositories.getPrefixes($repositories.getActiveRepository())]) + Promise.all([$jwtAuth.getPrincipal(), $repositories.getPrefixes(activeRepository)]) .then(([principal, usedPrefixes]) => { $scope.prefixes = usedPrefixes; setInferAndSameAs(principal); // check is there is a saved query or query url parameter and init the editor - initViewFromUrlParams(); + initViewFromUrlParams(clearYasguiState); }); // TODO: we should also watch for changes in namespaces // scope.$watch('namespaces', function () {}); @@ -446,24 +459,17 @@ function SparqlEditorCtrl($rootScope, // ========================= const subscriptions = []; - const reInitYasgui = (flags) => { - YasguiComponentDirectiveUtil.getOntotextYasguiElementAsync(QUERY_EDITOR_ID) - .then((yasguiComponent) => { - return yasguiComponent.reInitYasgui(flags); - }) - .catch(() => { - console.error('Failed to reset yasr results'); - }); - }; - - const repositoryChangedHandler = (activeRepo) => { - if (activeRepo) { - if (!initialRepoInitialization) { - const flags = new YasguiResetFlags(true, true, true, true); - reInitYasgui(flags); - } - init(); - initialRepoInitialization = false; + const repositoryChangedHandler = (object) => { + if (!object) { + return; + } + activeRepository= $repositories.getActiveRepository(); + isOntopRepo = $repositories.isActiveRepoOntopType(object); + if (LocalStorageAdapter.get(LSKeys.SPARQL_LAST_REPO) !== activeRepository) { + init(true); + persistLasstUsedRepository(); + } else { + init(false); } }; @@ -538,6 +544,25 @@ function SparqlEditorCtrl($rootScope, window.removeEventListener('beforeunload', beforeunloadHandler); }; + const finalizeAndDestroy = () => { + persistLasstUsedRepository(); + removeAllListeners(); + }; + + const persistLasstUsedRepository = () => { + // The active repository is set when the controller is initialized and when the repository is changed. + // It holds the actual repository when the YASGUI is initialized. DON'T use runtime fetching of the actual repository here, because there is a scenario: + // 1. Open a tab with the SPARQL view open; + // 2. Open the SPARQL view in another tab and execute a query; + // 3. Switch to the repositories view and change the repository; + // 4. Switch back to the SPARQL view, and the YASR is not cleared. + // The problem occurs because of the second tab. When the repository is changed, its ID is persisted to local storage, which triggers the "storage" event to be fired. + // In the main controller, a listener has been registered to listen to that event and refresh the page outside of the Angular scope. + // Reloading the page triggers the destruction of the component and persistence of the active repository. The reloading of the page is out of the Angular scope, so the "activeRepository" + // holds the real repository when the YASGUI is created. If we use $$repositories.getActiveRepository(), the new value will be fetched, which in this case will be incorrect. + LocalStorageAdapter.set(LSKeys.SPARQL_LAST_REPO, activeRepository); + } + subscriptions.push( $scope.$on('language-changed', function () { location.reload(); @@ -561,7 +586,7 @@ function SparqlEditorCtrl($rootScope, )); // Deregister the watcher when the scope/directive is destroyed - $scope.$on('$destroy', removeAllListeners); + subscriptions.push($scope.$on('$destroy', finalizeAndDestroy)); // Wait until the active repository object is set, otherwise "canWriteActiveRepo()" may return a wrong result and the "ontotext-yasgui" // readOnly configuration may be incorrect. diff --git a/src/js/angular/utils/local-storage-adapter.js b/src/js/angular/utils/local-storage-adapter.js index 9865aa0a5..67d1167b0 100644 --- a/src/js/angular/utils/local-storage-adapter.js +++ b/src/js/angular/utils/local-storage-adapter.js @@ -27,7 +27,8 @@ angular 'REPOSITORY_ID': 'repository-id', 'REPOSITORY_LOCATION': 'repository-location', 'JSONLD_EXPORT_SETTINGS': 'jsonld-export-settings', - 'IMPORT_VIEW': 'import-view' + 'IMPORT_VIEW': 'import-view', + 'SPARQL_LAST_REPO': 'sparql-last-repo' }); LocalStorageAdapter.$inject = ['localStorageService', 'LSKeys']; diff --git a/test-cypress/integration/sparql-editor/actions/expand-results-over-sameas.spec.js b/test-cypress/integration/sparql-editor/actions/expand-results-over-sameas.spec.js index 1b4ea17de..e53cb649d 100644 --- a/test-cypress/integration/sparql-editor/actions/expand-results-over-sameas.spec.js +++ b/test-cypress/integration/sparql-editor/actions/expand-results-over-sameas.spec.js @@ -71,7 +71,7 @@ describe('Expand results over owl:sameAs', () => { YasqeSteps.getActionButtonTooltip(4).should('have.attr', 'data-tooltip', 'Expand results over owl:sameAs: ON'); }); - it('should not be enabled when infer is true and sameAs is false in user settings', () => { + it('should not be enabled when infer is true and sameAs is false in user settings', {retries: {runMode: 2}},() => { QueryStubs.stubInferAndSameAsDefaults(true, false); // When I visit a page with "ontotext-yasgui-web-component" in it.