Skip to content

Commit

Permalink
GDB-8810 introduces iri autocomplete select and integrates it in the …
Browse files Browse the repository at this point in the history
…acl view (#1055)

* GDB-8810 introduce iri autocomplete select and integrate in acl view

## What
IRI autocomplete component is implemented and integrated it in the ACL management view.

## Why
This improves the user experience allowing easier completion of triples when editing acl rules.

## How
Implemented the autocomplete component based on the rdf-resource-search component.
Integrated the component in the ACL management view.

Integrated the autocomplete in the acl view

Make autocomplete to wrap uris in `<...>` because it's expected by the acl service that triples will be encoded as n-triples

Fix text and index column size which needs to fit properly the rule indexes at least to four digits

Cleanup the code

Removed hardcoded test uris

Fix uri wrapping for prefixes

Reset state of the ACL on repo change

Fix selection from suggested uris by mouse click.

Make the autosuggest menu visible when there are no rules in the ACL. This was broken by the table-responsive css class which used to make the table `overflow-x: auto` and this clip the menu. Removed the responsive class because the table doesn't scoll anyway.

Handle blur event in a timeout in order to allow if it was triggered by a click on the dropdown menu itself. Hiding the menu immediately otherwise would cause the selection to fail because the blur event happens before the click.

* flaky test: wait for query to be visible in the editor
  • Loading branch information
svilenvelikov authored Oct 11, 2023
1 parent 114855c commit f83cd34
Show file tree
Hide file tree
Showing 16 changed files with 627 additions and 137 deletions.
4 changes: 3 additions & 1 deletion src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'angular/core/directives/languageselector/language-selector.directive';
import 'angular/core/directives/angulartooltips/angular-tooltips.js';
import 'angular/core/directives/uppercased.directive';
import 'angular/core/directives/operations-statuses-monitor/operations-statuses-monitor.directive'
import 'angular/core/directives/autocomplete/autocomplete.directive'

// $translate.instant converts <b> from strings to &lt;b&gt
// and $sce.trustAsHtml could not recognise that this is valid html
Expand All @@ -34,7 +35,8 @@ const modules = [
'graphdb.framework.core.directives.angular-tooltips',
'graphdb.framework.core.directives.uppercased',
'graphdb.framework.guides.services',
'graphdb.framework.core.directives.operationsstatusesmonitor'
'graphdb.framework.core.directives.operationsstatusesmonitor',
'graphdb.framework.core.directives.autocomplete'
];

const providers = [
Expand Down
13 changes: 12 additions & 1 deletion src/css/aclmanagement.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
table-layout: fixed;
}

.acl-management-view .acl-rules .labels-row th {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;;
}

.acl-management-view .acl-rules .toolbar {
height: 35px;
padding: 0;
Expand All @@ -18,13 +24,18 @@
}

.acl-management-view .acl-rules .index-column {
width: 2%;
width: 4ch;
}

.acl-management-view .acl-rules .reorder-column {
width: 25px;
}

.acl-management-view .acl-rules .index-cell {
padding: 0;
text-align: center;
}

.acl-management-view .acl-rules .reorder-cell {
padding: 0;
}
Expand Down
62 changes: 62 additions & 0 deletions src/css/autocomplete-select.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
.autocomplete-select-wrapper {
position: relative;
}

.autocomplete-select-wrapper .autocomplete-results-wrapper {
position: absolute;
top: 100%;
left: 0;
max-height: 204px;
margin-bottom: 0;
overflow: auto;
background-color: #fff;
}

.autocomplete-select-wrapper .autocomplete-results-wrapper div:hover {
background-color: var(--autocomplete-background);
cursor: pointer;
}

.autocomplete-select-wrapper .autocomplete-results-wrapper div.active {
background-color: var(--autocomplete-background);
cursor: pointer;
}

.autocomplete-select-wrapper .autocomplete-results-wrapper div.selected {
background-color: var(--autocomplete-background-selected);
cursor: pointer;
}

.autocomplete-select-wrapper .autocomplete-results-wrapper div p b,
.autocomplete-select-wrapper .autocomplete-results-wrapper div.active p b {
color: var(--autocomplete-match);
}

.autocomplete-select-wrapper .autocomplete-results-wrapper div p {
margin-bottom: 0;
padding: 5px 25px;
white-space: nowrap;
}

.autocomplete-select-wrapper .autocomplete-select {
color: red;
}

.templates .tag {
cursor: pointer;
font-size: 100%;
}

.autocomplete-loader {
position: relative;
z-index: 100000;
}

.autocomplete-loader .ot-loader-new-content {
position: absolute;
z-index: 100000;
width: 100%;
height: calc(100vh - 120px);
padding-top: calc((100vh - 300px) / 2);
background-color: rgba(255,255,255,0.66);
}
43 changes: 38 additions & 5 deletions src/js/angular/aclmanagement/controllers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'angular/rest/plugins.rest.service';
import 'angular/rest/aclmanagement.rest.service';
import {mapAclRulesResponse} from "../rest/mappers/aclmanagement-mapper";
import {isEqual} from 'lodash';
import {mapNamespacesResponse} from "../rest/mappers/namespaces-mapper";

const modules = [
'graphdb.framework.rest.plugins.service',
Expand All @@ -12,9 +13,11 @@ angular
.module('graphdb.framework.aclmanagement.controllers', modules)
.controller('AclManagementCtrl', AclManagementCtrl);

AclManagementCtrl.$inject = ['$scope', '$location', 'toastr', 'AclManagementRestService', '$repositories', '$translate', 'ModalService'];
AclManagementCtrl.$inject = ['$scope', '$location', 'toastr', 'AclManagementRestService', '$repositories', '$translate', 'ModalService', 'RDF4JRepositoriesRestService', 'AutocompleteRestService'];

function AclManagementCtrl($scope, $location, toastr, AclManagementRestService, $repositories, $translate, ModalService) {
function AclManagementCtrl($scope, $location, toastr, AclManagementRestService, $repositories, $translate, ModalService, RDF4JRepositoriesRestService, AutocompleteRestService) {

$scope.contextValue = undefined;

//
// Private fields
Expand Down Expand Up @@ -42,6 +45,12 @@ function AclManagementCtrl($scope, $location, toastr, AclManagementRestService,
*/
$scope.loading = false;

/**
* Namespaces model loaded in advance and passed to all autocomplete fields.
* @type {{uri: string, prefix: string}[]}
*/
$scope.namespaces = [];

/**
* A list with ACL rules that will be managed in this view.
* @type {undefined|ACListModel}
Expand Down Expand Up @@ -224,7 +233,6 @@ function AclManagementCtrl($scope, $location, toastr, AclManagementRestService,
return AclManagementRestService.updateAcl(repositoryId, $scope.rulesModel.toJSON())
.then(() => {
toastr.success($translate.instant('acl_management.rulestable.messages.rules_updated'));
return true;
});
};

Expand All @@ -240,6 +248,13 @@ function AclManagementCtrl($scope, $location, toastr, AclManagementRestService,
}
};

const resetPageState = () => {
loadRules();
$scope.editedRuleIndex = undefined;
$scope.modelIsDirty = false;
$scope.editedRuleCopy = undefined;
};

/**
* Updates the modelIsDirty flag by comparing the model with its copy created after it was loaded initially.
*/
Expand All @@ -259,6 +274,18 @@ function AclManagementCtrl($scope, $location, toastr, AclManagementRestService,
toastr.error($translate.instant('acl_management.errors.duplicated_rules'));
};

const loadNamespaces = () => {
RDF4JRepositoriesRestService.getNamespaces($repositories.getActiveRepository())
.then(mapNamespacesResponse)
.then((namespacesModel) => {
$scope.namespaces = namespacesModel;
})
.catch((response) => {
const msg = getError(response);
toastr.error(msg, $translate.instant('error.getting.namespaces.for.repo'));
});
};

/**
* Should warn the user if he tries to close the browser tab while there are unsaved changes.
* @param {{returnValue: boolean}} event
Expand Down Expand Up @@ -298,12 +325,18 @@ function AclManagementCtrl($scope, $location, toastr, AclManagementRestService,
}
};

const checkAutocompleteStatus = () => {
$scope.getAutocompletePromise = AutocompleteRestService.checkAutocompleteStatus();
};

/**
* Initialized the view controller.
*/
const init = () => {
// Watching for repository changes and reload the rules, because they are stored per repository.
subscriptions.push($scope.$watch(getActiveRepositoryId, loadRules));
loadNamespaces();
subscriptions.push($scope.$on('autocompleteStatus', checkAutocompleteStatus));
// Watching for repository changes and reload the rules, because they are stored per repository and reset page state.
subscriptions.push($scope.$watch(getActiveRepositoryId, resetPageState));
// Watching for url changes
subscriptions.push($scope.$on('$locationChangeStart', locationChangedHandler));
// Watching for component destroy
Expand Down
Loading

0 comments on commit f83cd34

Please sign in to comment.