TSK-714 - Improve all workbasket access items for a user screen
This commit is contained in:
parent
b7aee393ae
commit
3d1a921394
|
@ -288,8 +288,8 @@ public class LdapCacheTestImpl implements LdapCache {
|
||||||
new AccessIdResource("team_4", "cn=team_4" + ",ou=groups,o=TaskanaTest")));
|
new AccessIdResource("team_4", "cn=team_4" + ",ou=groups,o=TaskanaTest")));
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<AccessIdResource> findMatchingAccessId(String searchFor, int maxNumerOfReturnedAccessIds) {
|
public List<AccessIdResource> findMatchingAccessId(String searchFor, int maxNumberOfReturnedAccessIds) {
|
||||||
return findAccessIdResource(searchFor, maxNumerOfReturnedAccessIds, false);
|
return findAcessIdResource(searchFor, maxNumberOfReturnedAccessIds, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -297,10 +297,17 @@ public class LdapCacheTestImpl implements LdapCache {
|
||||||
if (users == null) {
|
if (users == null) {
|
||||||
addUsersToGroups();
|
addUsersToGroups();
|
||||||
}
|
}
|
||||||
return findAccessIdResource(searchFor, maxNumberOfReturnedAccessIds, true);
|
return findAcessIdResource(searchFor, maxNumberOfReturnedAccessIds, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<AccessIdResource> findAccessIdResource(String searchFor, int maxNumerOfReturnedAccessIds,
|
@Override
|
||||||
|
public List<AccessIdResource> validateAccessId(String accessId) {
|
||||||
|
return accessIds.stream()
|
||||||
|
.filter(t -> (t.getAccessId().equalsIgnoreCase(accessId.toLowerCase())))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<AccessIdResource> findAcessIdResource(String searchFor, int maxNumberOfReturnedAccessIds,
|
||||||
boolean groupMember) {
|
boolean groupMember) {
|
||||||
List<AccessIdResource> usersAndGroups = accessIds.stream()
|
List<AccessIdResource> usersAndGroups = accessIds.stream()
|
||||||
.filter(t -> (t.getName().toLowerCase().contains(searchFor.toLowerCase())
|
.filter(t -> (t.getName().toLowerCase().contains(searchFor.toLowerCase())
|
||||||
|
@ -321,7 +328,7 @@ public class LdapCacheTestImpl implements LdapCache {
|
||||||
});
|
});
|
||||||
|
|
||||||
List<AccessIdResource> result = usersAndGroups.subList(0,
|
List<AccessIdResource> result = usersAndGroups.subList(0,
|
||||||
Math.min(usersAndGroups.size(), maxNumerOfReturnedAccessIds));
|
Math.min(usersAndGroups.size(), maxNumberOfReturnedAccessIds));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class AccessIdValidationControllerTest {
|
||||||
headers.add("Authorization", "Basic dGVhbWxlYWRfMTp0ZWFtbGVhZF8x");
|
headers.add("Authorization", "Basic dGVhbWxlYWRfMTp0ZWFtbGVhZF8x");
|
||||||
HttpEntity<String> request = new HttpEntity<String>(headers);
|
HttpEntity<String> request = new HttpEntity<String>(headers);
|
||||||
ResponseEntity<List<AccessIdResource>> response = template.exchange(
|
ResponseEntity<List<AccessIdResource>> response = template.exchange(
|
||||||
"http://127.0.0.1:" + port + "/v1/access-ids?searchFor=ali", HttpMethod.GET, request,
|
"http://127.0.0.1:" + port + "/v1/access-ids?search-for=ali", HttpMethod.GET, request,
|
||||||
new ParameterizedTypeReference<List<AccessIdResource>>() {
|
new ParameterizedTypeReference<List<AccessIdResource>>() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -73,7 +73,7 @@ public class AccessIdValidationControllerTest {
|
||||||
HttpEntity<String> request = new HttpEntity<String>(headers);
|
HttpEntity<String> request = new HttpEntity<String>(headers);
|
||||||
try {
|
try {
|
||||||
template.exchange(
|
template.exchange(
|
||||||
"http://127.0.0.1:" + port + "/v1/access-ids?searchFor=al", HttpMethod.GET, request,
|
"http://127.0.0.1:" + port + "/v1/access-ids?search-for=al", HttpMethod.GET, request,
|
||||||
new ParameterizedTypeReference<List<AccessIdResource>>() {
|
new ParameterizedTypeReference<List<AccessIdResource>>() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -90,7 +90,7 @@ public class GenenalExceptionHandlingTest {
|
||||||
|
|
||||||
AccessIdController.setLdapCache(new LdapCacheTestImpl());
|
AccessIdController.setLdapCache(new LdapCacheTestImpl());
|
||||||
template.exchange(
|
template.exchange(
|
||||||
server + port + "/v1/access-ids?searchFor=al", HttpMethod.GET, request,
|
server + port + "/v1/access-ids?search-for=al", HttpMethod.GET, request,
|
||||||
new ParameterizedTypeReference<List<AccessIdResource>>() {
|
new ParameterizedTypeReference<List<AccessIdResource>>() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,17 +16,24 @@ public interface LdapCache {
|
||||||
*
|
*
|
||||||
* @param searchFor
|
* @param searchFor
|
||||||
* the search string. The search is performed over names and ids of users and groups.
|
* the search string. The search is performed over names and ids of users and groups.
|
||||||
* @param maxNumerOfReturnedAccessIds
|
* @param maxNumberOfReturnedAccessIds
|
||||||
* the maximum number of results to return.
|
* the maximum number of results to return.
|
||||||
* @return a List of access ids for users and group where the name or id contains the search string.
|
* @return a List of access ids for users and group where the name or id contains the search string.
|
||||||
*/
|
*/
|
||||||
List<AccessIdResource> findMatchingAccessId(String searchFor, int maxNumerOfReturnedAccessIds);
|
List<AccessIdResource> findMatchingAccessId(String searchFor, int maxNumberOfReturnedAccessIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Find the groups belong to a user.
|
||||||
* @param searchFor the search string. The search is performed over names and ids of group .
|
* @param searchFor the search string. The search is performed over names and ids of group .
|
||||||
* @param maxNumerOfReturnedAccessIds
|
* @param maxNumberOfReturnedAccessIds the maximum number of results to return.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
List<AccessIdResource> findGroupsOfUser(String searchFor, int maxNumerOfReturnedAccessIds);
|
List<AccessIdResource> findGroupsOfUser(String searchFor, int maxNumberOfReturnedAccessIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate a access id.
|
||||||
|
* @param accessId the search string.
|
||||||
|
* @return the corresponding access id.
|
||||||
|
*/
|
||||||
|
List<AccessIdResource> validateAccessId(String accessId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,28 +35,40 @@ public class AccessIdController {
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public ResponseEntity<List<AccessIdResource>> validateAccessIds(
|
public ResponseEntity<List<AccessIdResource>> validateAccessIds(
|
||||||
@RequestParam String searchFor, @RequestParam(required = false) boolean searchInGroups) throws InvalidArgumentException {
|
@RequestParam("search-for") String searchFor) throws InvalidArgumentException {
|
||||||
if (searchFor.length() < ldapClient.getMinSearchForLength()) {
|
if (searchFor.length() < ldapClient.getMinSearchForLength()) {
|
||||||
throw new InvalidArgumentException("searchFor string '" + searchFor + "' is too short. Minimum searchFor length = "
|
throw new InvalidArgumentException(
|
||||||
+ ldapClient.getMinSearchForLength());
|
"searchFor string '" + searchFor + "' is too short. Minimum searchFor length = "
|
||||||
|
+ ldapClient.getMinSearchForLength());
|
||||||
}
|
}
|
||||||
if (ldapClient.useLdap()) {
|
if (ldapClient.useLdap()) {
|
||||||
List<AccessIdResource> accessIdUsers = ldapClient.searchUsersAndGroups(searchFor);
|
List<AccessIdResource> accessIdUsers = ldapClient.searchUsersAndGroups(searchFor);
|
||||||
if (searchInGroups) {
|
|
||||||
List<AccessIdResource> accessIdGroups = ldapClient.searchGroupsofUsersIsMember(searchFor);
|
|
||||||
accessIdUsers.addAll(accessIdGroups);
|
|
||||||
}
|
|
||||||
return new ResponseEntity<>(accessIdUsers, HttpStatus.OK);
|
return new ResponseEntity<>(accessIdUsers, HttpStatus.OK);
|
||||||
} else if (ldapCache != null) {
|
} else if (ldapCache != null) {
|
||||||
if (searchInGroups) {
|
return new ResponseEntity<>(
|
||||||
return new ResponseEntity<>(
|
ldapCache.findMatchingAccessId(searchFor, ldapClient.getMaxNumberOfReturnedAccessIds()),
|
||||||
ldapCache.findGroupsOfUser(searchFor, ldapClient.getMaxNumberOfReturnedAccessIds()),
|
HttpStatus.OK);
|
||||||
HttpStatus.OK);
|
} else {
|
||||||
} else {
|
return new ResponseEntity<>(new ArrayList<>(), HttpStatus.NOT_FOUND);
|
||||||
return new ResponseEntity<>(
|
}
|
||||||
ldapCache.findMatchingAccessId(searchFor, ldapClient.getMaxNumberOfReturnedAccessIds()),
|
}
|
||||||
HttpStatus.OK);
|
|
||||||
|
@GetMapping(path = "/groups")
|
||||||
|
public ResponseEntity<List<AccessIdResource>> getGroupsByAccessId(
|
||||||
|
@RequestParam("access-id") String accessId) throws InvalidArgumentException {
|
||||||
|
if (ldapClient.useLdap() || ldapCache != null) {
|
||||||
|
if (!validateAccessId(accessId)) {
|
||||||
|
throw new InvalidArgumentException("The accessId is invalid");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
List<AccessIdResource> accessIdUsers;
|
||||||
|
if (ldapClient.useLdap()) {
|
||||||
|
accessIdUsers = ldapClient.searchUsersAndGroups(accessId);
|
||||||
|
accessIdUsers.addAll(ldapClient.searchGroupsofUsersIsMember(accessId));
|
||||||
|
return new ResponseEntity<>(accessIdUsers, HttpStatus.OK);
|
||||||
|
} else if (ldapCache != null) {
|
||||||
|
accessIdUsers = ldapCache.findGroupsOfUser(accessId, ldapClient.getMaxNumberOfReturnedAccessIds());
|
||||||
|
return new ResponseEntity<>(accessIdUsers, HttpStatus.OK);
|
||||||
} else {
|
} else {
|
||||||
return new ResponseEntity<>(new ArrayList<>(), HttpStatus.NOT_FOUND);
|
return new ResponseEntity<>(new ArrayList<>(), HttpStatus.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
@ -66,4 +78,9 @@ public class AccessIdController {
|
||||||
ldapCache = cache;
|
ldapCache = cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean validateAccessId(String accessId) throws InvalidArgumentException {
|
||||||
|
return (ldapClient.useLdap() && ldapClient.searchUsersAndGroups(accessId).size() == 1) || (!ldapClient.useLdap()
|
||||||
|
&& ldapCache.validateAccessId(accessId).size() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<div class="pull-right btn-group">
|
|
||||||
<button *ngIf="AccessItemsForm" type="button" (click)="revokeAccess()" class="btn btn-default" data-toggle="tooltip" title="Revoke access">
|
|
||||||
<span class="glyphicon glyphicon-remove red" aria-hidden="true"></span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<h4 class="panel-header">Acces items management</h4>
|
<h4 class="panel-header">Acces items management</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
@ -13,8 +8,8 @@
|
||||||
(onSelect)="onSelectAccessId($event)" displayError=true></taskana-type-ahead>
|
(onSelect)="onSelectAccessId($event)" displayError=true></taskana-type-ahead>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="!AccessItemsForm" class="center-block no-detail col-xs-12">
|
<div *ngIf="!AccessItemsForm" class="center-block no-detail col-xs-12">
|
||||||
<h3 class="grey">Select an access id</h3>
|
<h3 class="grey">Select an access id</h3>
|
||||||
<svg-icon class="empty-icon" src="./assets/icons/users.svg"></svg-icon>
|
<svg-icon class="empty-icon" src="./assets/icons/users.svg"></svg-icon>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="AccessItemsForm" class="row col-xs-12">
|
<div *ngIf="AccessItemsForm" class="row col-xs-12">
|
||||||
<form [formGroup]="AccessItemsForm">
|
<form [formGroup]="AccessItemsForm">
|
||||||
|
@ -50,7 +45,8 @@
|
||||||
<th class="text-align"><input type="text" formControlName="accessIdFilter" (keyup.enter)="searchForAccessItemsWorkbaskets()"
|
<th class="text-align"><input type="text" formControlName="accessIdFilter" (keyup.enter)="searchForAccessItemsWorkbaskets()"
|
||||||
class="form-control" placeholder="Access id filter"></th>
|
class="form-control" placeholder="Access id filter"></th>
|
||||||
<th>
|
<th>
|
||||||
<button type="button" (click)="searchForAccessItemsWorkbaskets()" class="btn btn-default" data-toggle="tooltip" title="Search">
|
<button type="button" (click)="searchForAccessItemsWorkbaskets()" class="btn btn-default" data-toggle="tooltip"
|
||||||
|
title="Search">
|
||||||
<span class="glyphicon glyphicon-search blue" aria-hidden="true"></span>
|
<span class="glyphicon glyphicon-search blue" aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
</th>
|
</th>
|
||||||
|
@ -80,8 +76,9 @@
|
||||||
</td>
|
</td>
|
||||||
<td *ngIf="accessIdField.lookupField else accessIdInput" colspan="2" class="text-align text-width taskana-type-ahead">
|
<td *ngIf="accessIdField.lookupField else accessIdInput" colspan="2" class="text-align text-width taskana-type-ahead">
|
||||||
<div>
|
<div>
|
||||||
<taskana-type-ahead formControlName="accessId" placeHolderMessage="* Access id is required" [validationValue]="toogleValidationAccessIdMap.get(index)"
|
<taskana-type-ahead formControlName="accessId" placeHolderMessage="* Access id is required"
|
||||||
[displayError]="!isFieldValid('accessItem.value.accessId', index)" [disable]=true></taskana-type-ahead>
|
[validationValue]="toogleValidationAccessIdMap.get(index)" [displayError]="!isFieldValid('accessItem.value.accessId', index)"
|
||||||
|
[disable]=true></taskana-type-ahead>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<ng-template #accessIdInput>
|
<ng-template #accessIdInput>
|
||||||
|
@ -163,6 +160,41 @@
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<button *ngIf="!isGroup" class="pull-left btn-group" type="button" class="btn btn-primary" data-toggle="modal"
|
||||||
|
data-target="#myModal">
|
||||||
|
Belonging groups
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="modal" id="myModal">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 class="modal-title">Belonging groups</h4>
|
||||||
|
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-body">
|
||||||
|
<ul *ngIf="belongingGroups !== undefined && belongingGroups.length > 0 " class="list-group">
|
||||||
|
<li *ngFor="let group of belongingGroups" class="list-group-item">{{group.name}}</li>
|
||||||
|
</ul>
|
||||||
|
<p *ngIf="belongingGroups === undefined || belongingGroups.length === 0">The user is not associated to any groups</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pull-right btn-group">
|
||||||
|
<button *ngIf="AccessItemsForm" type="button" class="btn btn-default" data-toggle="tooltip" title="Revoke access"
|
||||||
|
[disabled]=isGroup>
|
||||||
|
<span class="glyphicon glyphicon-remove red" aria-hidden="true"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -31,3 +31,8 @@ td {
|
||||||
word-wrap:break-word;
|
word-wrap:break-word;
|
||||||
}
|
}
|
||||||
.min-width{ min-width: 135px;}
|
.min-width{ min-width: 135px;}
|
||||||
|
|
||||||
|
.modal-title {
|
||||||
|
font-weight: bold;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
|
@ -32,8 +32,11 @@ export class AccessItemsManagementComponent implements OnInit, OnDestroy {
|
||||||
accessItemPermissionsSubscription: Subscription;
|
accessItemPermissionsSubscription: Subscription;
|
||||||
accessItemInformationsubscription: Subscription;
|
accessItemInformationsubscription: Subscription;
|
||||||
accessIdsWithGroups: Array<AccessIdDefinition>;
|
accessIdsWithGroups: Array<AccessIdDefinition>;
|
||||||
|
belongingGroups: Array<AccessIdDefinition>;
|
||||||
sortingFields = new Map([['workbasket-key', 'Workbasket Key'], ['access-id', 'Access id']]);
|
sortingFields = new Map([['workbasket-key', 'Workbasket Key'], ['access-id', 'Access id']]);
|
||||||
sortModel: SortingModel;
|
sortModel: SortingModel;
|
||||||
|
isGroup: boolean;
|
||||||
|
groupsKey = 'ou=groups';
|
||||||
|
|
||||||
|
|
||||||
accessIdField = this.customFieldsService.getCustomField('Owner', 'workbaskets.access-items.accessId');
|
accessIdField = this.customFieldsService.getCustomField('Owner', 'workbaskets.access-items.accessId');
|
||||||
|
@ -89,11 +92,13 @@ export class AccessItemsManagementComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
if (!this.AccessItemsForm || this.accessIdPrevious !== selected.accessId) {
|
if (!this.AccessItemsForm || this.accessIdPrevious !== selected.accessId) {
|
||||||
this.accessIdPrevious = selected.accessId
|
this.accessIdPrevious = selected.accessId
|
||||||
|
this.isGroup = selected.accessId.includes(this.groupsKey);
|
||||||
|
|
||||||
this.unSubscribe(this.accessItemInformationsubscription)
|
this.unSubscribe(this.accessItemInformationsubscription)
|
||||||
this.accessItemInformationsubscription = this.accessIdsService.getAccessItemsInformation(selected.accessId, true)
|
this.accessItemInformationsubscription = this.accessIdsService.getAccessItemsInformation(selected.accessId, true)
|
||||||
.subscribe((accessIdsWithGroups: Array<AccessIdDefinition>) => {
|
.subscribe((accessIdsWithGroups: Array<AccessIdDefinition>) => {
|
||||||
this.accessIdsWithGroups = accessIdsWithGroups;
|
this.accessIdsWithGroups = accessIdsWithGroups;
|
||||||
|
this.belongingGroups = accessIdsWithGroups.filter(item => item.accessId.includes(this.groupsKey));
|
||||||
this.searchForAccessItemsWorkbaskets();
|
this.searchForAccessItemsWorkbaskets();
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
|
|
|
@ -21,7 +21,11 @@ export class AccessIdsService {
|
||||||
if (!token || token.length < 3) {
|
if (!token || token.length < 3) {
|
||||||
return of([]);
|
return of([]);
|
||||||
}
|
}
|
||||||
return this.httpClient.get<Array<AccessIdDefinition>>(`${this.url}?searchFor=${token}&searchInGroups=${searchInGroups}`);
|
if (searchInGroups) {
|
||||||
|
return this.httpClient.get<Array<AccessIdDefinition>>(`${this.url}/groups?access-id=${token}`);
|
||||||
|
} else {
|
||||||
|
return this.httpClient.get<Array<AccessIdDefinition>>(`${this.url}?search-for=${token}`);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
getAccessItemsPermissions(
|
getAccessItemsPermissions(
|
||||||
|
|
|
@ -6,3 +6,7 @@
|
||||||
.sortby-dropdown {
|
.sortby-dropdown {
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input #inputTypeAhead class=" form-control input-text" (blur)="typeaheadOnSelect({'item':dataSource.selected})" name="accessItem-{{index}}"
|
<input #inputTypeAhead class=" form-control input-text" [ngClass]="{'invalid': dataSource.length == null}" (blur)="typeaheadOnSelect({'item':dataSource.selected})" name="accessItem-{{index}}"
|
||||||
required #accessItemName="ngModel" [(ngModel)]="value" [typeahead]="dataSource" typeaheadOptionField="name" [typeaheadItemTemplate]="customItemTemplate"
|
required #accessItemName="ngModel" [(ngModel)]="value" [typeahead]="dataSource" typeaheadOptionField="name" [typeaheadItemTemplate]="customItemTemplate"
|
||||||
(typeaheadOnSelect)="typeaheadOnSelect($event, index)" [typeaheadScrollable]="true" [typeaheadOptionsInScrollableView]="typeaheadOptionsInScrollableView"
|
(typeaheadOnSelect)="typeaheadOnSelect($event, index)" [typeaheadScrollable]="true" [typeaheadOptionsInScrollableView]="typeaheadOptionsInScrollableView"
|
||||||
[typeaheadMinLength]="typeaheadMinLength" [typeaheadWaitMs]="typeaheadWaitMs" (typeaheadLoading)="changeTypeaheadLoading($event)"
|
[typeaheadMinLength]="typeaheadMinLength" [typeaheadWaitMs]="typeaheadWaitMs" (typeaheadLoading)="changeTypeaheadLoading($event)"
|
||||||
|
|
|
@ -91,3 +91,7 @@
|
||||||
.disable {
|
.disable {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.invalid {
|
||||||
|
color: $invalid;
|
||||||
|
}
|
||||||
|
|
|
@ -9,3 +9,4 @@ $invalid: #d82626;
|
||||||
$aquamarine: #22a39f;
|
$aquamarine: #22a39f;
|
||||||
$pallete-blue: #36bcee;
|
$pallete-blue: #36bcee;
|
||||||
$pallete-green: #5fbca1;
|
$pallete-green: #5fbca1;
|
||||||
|
$transparent-grey: rgba(192, 192, 192, 0.65);
|
||||||
|
|
|
@ -353,3 +353,7 @@ li.list-group-item:hover {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-backdrop.show {
|
||||||
|
background-color: $transparent-grey;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue