Joining lib, rest and web
This commit is contained in:
parent
3f8dc3cf87
commit
ec432d122a
|
@ -379,4 +379,4 @@ public class LdapCacheTestImpl implements LdapCache {
|
|||
new AccessIdResource("haftpflicht", "cn=haftpflicht,ou=groups,o=TaskanaTest"),
|
||||
new AccessIdResource("bauspar", "cn=bauspar,ou=groups,o=TaskanaTest")));
|
||||
|
||||
}
|
||||
}
|
|
@ -19,6 +19,8 @@ import pro.taskana.exceptions.NotAuthorizedException;
|
|||
import pro.taskana.rest.resource.WorkbasketAccesItemExtendedResource;
|
||||
import pro.taskana.rest.resource.assembler.WorkbasketAccessItemExtendedAssembler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -85,7 +87,7 @@ public class WorkbasketAccessItemController extends AbstractPagingController {
|
|||
private WorkbasketAccessItemExtendedQuery getAccessIds(WorkbasketAccessItemExtendedQuery query,
|
||||
MultiValueMap<String, String> params) throws InvalidArgumentException {
|
||||
if (params.containsKey(ACCESS_IDS)) {
|
||||
String[] accessIds = extractCommaSeparatedFields(params.get(ACCESS_IDS));
|
||||
String[] accessIds = extractVerticalBarSeparatedFields(params.get(ACCESS_IDS));
|
||||
query.accessIdIn(accessIds);
|
||||
params.remove(ACCESS_IDS);
|
||||
}
|
||||
|
@ -142,4 +144,12 @@ public class WorkbasketAccessItemController extends AbstractPagingController {
|
|||
return query;
|
||||
}
|
||||
|
||||
private String[] extractVerticalBarSeparatedFields(List<String> searchFor) {
|
||||
List<String> values = new ArrayList<>();
|
||||
if (searchFor != null) {
|
||||
searchFor.forEach(item -> values.addAll(Arrays.asList(item.split("\\|"))));
|
||||
}
|
||||
return values.toArray(new String[0]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,10 +7,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
<<<<<<< HEAD
|
||||
import pro.taskana.WorkbasketAccessItem;
|
||||
=======
|
||||
>>>>>>> a89fa20c... TSK-694 - Show list of all access items valid for a user (REST)
|
||||
import pro.taskana.WorkbasketAccessItemExtended;
|
||||
import pro.taskana.WorkbasketService;
|
||||
import pro.taskana.impl.WorkbasketAccessItemExtendedImpl;
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
<div class="panel panel-default">
|
||||
<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>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="col-md-6 col-md-offset-3 margin">
|
||||
<taskana-type-ahead #accesId="ngModel" name="accessIdSelected" [(ngModel)]="accessIdSelected" placeHolderMessage="Search for access id..."
|
||||
(onSelect)="onSelectAccessId($event)" displayError=true></taskana-type-ahead>
|
||||
</div>
|
||||
<div *ngIf="!AccessItemsForm" class="center-block no-detail col-xs-12">
|
||||
<h3 class="grey">Select an access id</h3>
|
||||
<svg-icon class="empty-icon" src="./assets/icons/users.svg"></svg-icon>
|
||||
</div>
|
||||
<div *ngIf="AccessItemsForm" class="row col-xs-12">
|
||||
<form [formGroup]="AccessItemsForm">
|
||||
<table id="table-access-items" class="table table-striped table-center">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<taskana-sort [sortingFields]="sortingFields" (performSorting)="sorting($event)" menuPosition="left"></taskana-sort>
|
||||
</th>
|
||||
<th class="text-align min-width">Workbasket Key</th>
|
||||
<th colspan="2" class="text-align">Access Id</th>
|
||||
<th>Read</th>
|
||||
<th>Open</th>
|
||||
<th>Append</th>
|
||||
<th>Transfer</th>
|
||||
<th>Distribute</th>
|
||||
<th *ngIf="custom1Field.visible">{{custom1Field.field}}</th>
|
||||
<th *ngIf="custom2Field.visible">{{custom2Field.field}}</th>
|
||||
<th *ngIf="custom3Field.visible">{{custom3Field.field}}</th>
|
||||
<th *ngIf="custom4Field.visible">{{custom4Field.field}}</th>
|
||||
<th *ngIf="custom5Field.visible">{{custom5Field.field}}</th>
|
||||
<th *ngIf="custom6Field.visible">{{custom6Field.field}}</th>
|
||||
<th *ngIf="custom7Field.visible">{{custom7Field.field}}</th>
|
||||
<th *ngIf="custom8Field.visible">{{custom8Field.field}}</th>
|
||||
<th *ngIf="custom9Field.visible">{{custom9Field.field}}</th>
|
||||
<th *ngIf="custom10Field.visible">{{custom10Field.field}}</th>
|
||||
<th *ngIf="custom11Field.visible">{{custom11Field.field}}</th>
|
||||
<th *ngIf="custom12Field.visible">{{custom12Field.field}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="2" class="text-align"><input type="text" formControlName="workbasketKeyFilter" (keyup.enter)="searchForAccessItemsWorkbaskets()"
|
||||
class="form-control" placeholder="Workbasket filter"></th>
|
||||
<th class="text-align"><input type="text" formControlName="accessIdFilter" (keyup.enter)="searchForAccessItemsWorkbaskets()"
|
||||
class="form-control" placeholder="Access id filter"></th>
|
||||
<th>
|
||||
<button type="button" (click)="searchForAccessItemsWorkbaskets()" class="btn btn-default" data-toggle="tooltip" title="Search">
|
||||
<span class="glyphicon glyphicon-search blue" aria-hidden="true"></span>
|
||||
</button>
|
||||
</th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody formArrayName="accessItemsGroups">
|
||||
<tr *ngFor="let accessItem of accessItemsGroups.controls; let index = index;" [formGroupName]="index">
|
||||
<td colspan="2">
|
||||
<label class="wrap">{{accessItem.value.workbasketKey}}</label>
|
||||
</td>
|
||||
<td *ngIf="accessIdField.lookupField else accessIdInput" colspan="2" class="text-align text-width taskana-type-ahead">
|
||||
<div>
|
||||
<taskana-type-ahead formControlName="accessId" placeHolderMessage="* Access id is required" [validationValue]="toogleValidationAccessIdMap.get(index)"
|
||||
[displayError]="!isFieldValid('accessItem.value.accessId', index)" [disable]=true></taskana-type-ahead>
|
||||
</div>
|
||||
</td>
|
||||
<ng-template #accessIdInput>
|
||||
<td colspan="2" class="text-align text-width">
|
||||
<div>
|
||||
<input type="text" class="form-control" formControlName="accessId" placeholder="{{accessItem.invalid?
|
||||
'* Access id is required': ''}}">
|
||||
</div>
|
||||
</td>
|
||||
</ng-template>
|
||||
<td>
|
||||
<input id="checkbox-{{index}}-0" type="checkbox" formControlName="permRead" class="regular-checkbox">
|
||||
<label for="checkbox-{{index}}-0"></label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="checkbox-{{index}}-1" type="checkbox" formControlName="permOpen">
|
||||
<label for="checkbox-{{index}}-1"></label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="checkbox-{{index}}-2" type="checkbox" formControlName="permAppend">
|
||||
<label for="checkbox-{{index}}-2"></label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="checkbox-{{index}}-3" type="checkbox" formControlName="permTransfer">
|
||||
<label for="checkbox-{{index}}-3"></label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="checkbox-{{index}}-4" type="checkbox" formControlName="permDistribute">
|
||||
<label for="checkbox-{{index}}-4"></label>
|
||||
</td>
|
||||
<td *ngIf="custom1Field.visible">
|
||||
<input id="checkbox-{{index}}-5" type="checkbox" formControlName="permCustom1">
|
||||
<label for="checkbox-{{index}}-5"></label>
|
||||
</td>
|
||||
<td *ngIf="custom2Field.visible">
|
||||
<input id="checkbox-{{index}}-6" type="checkbox" formControlName="permCustom2">
|
||||
<label for="checkbox-{{index}}-6"></label>
|
||||
</td>
|
||||
<td *ngIf="custom3Field.visible">
|
||||
<input id="checkbox-{{index}}-7" type="checkbox" formControlName="permCustom3">
|
||||
<label for="checkbox-{{index}}-7"></label>
|
||||
</td>
|
||||
<td *ngIf="custom4Field.visible">
|
||||
<input id="checkbox-{{index}}-8" type="checkbox" formControlName="permCustom4">
|
||||
<label for="checkbox-{{index}}-8"></label>
|
||||
</td>
|
||||
<td *ngIf="custom5Field.visible">
|
||||
<input id="checkbox-{{index}}-9" type="checkbox" formControlName="permCustom5">
|
||||
<label for="checkbox-{{index}}-9"></label>
|
||||
</td>
|
||||
<td *ngIf="custom6Field.visible">
|
||||
<input id="checkbox-{{index}}-10" type="checkbox" formControlName="permCustom6">
|
||||
<label for="checkbox-{{index}}-10"></label>
|
||||
</td>
|
||||
<td *ngIf="custom7Field.visible">
|
||||
<input id="checkbox-{{index}}-11" type="checkbox" formControlName="permCustom7">
|
||||
<label for="checkbox-{{index}}-11"></label>
|
||||
</td>
|
||||
<td *ngIf="custom8Field.visible">
|
||||
<input id="checkbox-{{index}}-12" type="checkbox" formControlName="permCustom8">
|
||||
<label for="checkbox-{{index}}-12"></label>
|
||||
</td>
|
||||
<td *ngIf="custom9Field.visible">
|
||||
<input id="checkbox-{{index}}-13" type="checkbox" formControlName="permCustom9">
|
||||
<label for="checkbox-{{index}}-13"></label>
|
||||
</td>
|
||||
<td *ngIf="custom10Field.visible">
|
||||
<input id="checkbox-{{index}}-14" type="checkbox" formControlName="permCustom10">
|
||||
<label for="checkbox-{{index}}-14"></label>
|
||||
</td>
|
||||
<td *ngIf="custom11Field.visible">
|
||||
<input id="checkbox-{{index}}-15" type="checkbox" formControlName="permCustom11">
|
||||
<label for="checkbox-{{index}}-15"></label>
|
||||
</td>
|
||||
<td *ngIf="custom12Field.visible">
|
||||
<input id="checkbox-{{index}}-16" type="checkbox" formControlName="permCustom12">
|
||||
<label for="checkbox-{{index}}-16"></label>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,33 @@
|
|||
@import './src/assets/_colors';
|
||||
|
||||
.margin {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.required-header:after {
|
||||
|
||||
content:" *";
|
||||
color: $invalid;
|
||||
}
|
||||
|
||||
td {
|
||||
&.has-changes {
|
||||
border-bottom: 1px solid $brown;
|
||||
}
|
||||
}
|
||||
.table > thead > tr > th {
|
||||
max-width: 150px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.table > thead > tr:last-child > th {
|
||||
max-width: 150px;
|
||||
border-bottom: 2px solid $grey;
|
||||
}
|
||||
|
||||
.wrap{
|
||||
max-width: 150px;
|
||||
word-wrap:break-word;
|
||||
}
|
||||
.min-width{ min-width: 135px;}
|
|
@ -0,0 +1,41 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AccessItemsManagementComponent } from './access-items-management.component';
|
||||
import { configureTests } from 'app/app.test.configuration';
|
||||
import { AccessIdsService } from 'app/shared/services/access-ids/access-ids.service';
|
||||
import { FormsValidatorService } from 'app/shared/services/forms/forms-validator.service';
|
||||
import { AccessIdDefinition } from 'app/models/access-id';
|
||||
import { AccessItemsWorkbasketResource } from 'app/models/access-item-workbasket-resource';
|
||||
import { of } from 'rxjs';
|
||||
|
||||
|
||||
describe('AccessItemsManagementComponent', () => {
|
||||
let component: AccessItemsManagementComponent;
|
||||
let fixture: ComponentFixture<AccessItemsManagementComponent>;
|
||||
let accessIdsService;
|
||||
|
||||
|
||||
beforeEach(done => {
|
||||
const configure = (testBed: TestBed) => {
|
||||
testBed.configureTestingModule({
|
||||
imports: [],
|
||||
declarations: [AccessItemsManagementComponent],
|
||||
providers: [ AccessIdsService, FormsValidatorService]
|
||||
})
|
||||
};
|
||||
|
||||
configureTests(configure).then(testBed => {
|
||||
fixture = TestBed.createComponent(AccessItemsManagementComponent);
|
||||
component = fixture.componentInstance;
|
||||
accessIdsService = TestBed.get(AccessIdsService);
|
||||
spyOn(accessIdsService, 'getAccessItemsPermissions').and.returnValue(of(new Array<AccessIdDefinition>()));
|
||||
spyOn(accessIdsService, 'getAccessItemsInformation').and.returnValue(of(new AccessItemsWorkbasketResource()));
|
||||
fixture.detectChanges();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,153 @@
|
|||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { FormBuilder, FormArray, Validators, FormGroup, FormControl } from '@angular/forms';
|
||||
import { CustomFieldsService } from 'app/services/custom-fields/custom-fields.service';
|
||||
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { FormsValidatorService } from 'app/shared/services/forms/forms-validator.service';
|
||||
import { AccessIdDefinition } from '../../models/access-id';
|
||||
import { AccessItemsWorkbasketResource } from 'app/models/access-item-workbasket-resource';
|
||||
import { AccessItemWorkbasket } from 'app/models/access-item-workbasket';
|
||||
import { AccessIdsService } from '../../shared/services/access-ids/access-ids.service';
|
||||
import { SortingModel } from 'app/models/sorting';
|
||||
import { RequestInProgressService } from '../../services/requestInProgress/request-in-progress.service';
|
||||
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
||||
import { ErrorModel } from 'app/models/modal-error';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-access-items-management',
|
||||
templateUrl: './access-items-management.component.html',
|
||||
styleUrls: ['./access-items-management.component.scss']
|
||||
})
|
||||
export class AccessItemsManagementComponent implements OnInit, OnDestroy {
|
||||
|
||||
accessIdSelected;
|
||||
accessIdPrevious;
|
||||
|
||||
AccessItemsForm: FormGroup;
|
||||
toogleValidationAccessIdMap = new Map<number, boolean>();
|
||||
accessItemPermissionsSubscription: Subscription;
|
||||
accessItemInformationsubscription: Subscription;
|
||||
accessIdsWithGroups: Array<AccessIdDefinition>;
|
||||
sortingFields = new Map([['workbasket-key', 'Workbasket Key'], ['access-id', 'Access id']]);
|
||||
sortModel: SortingModel;
|
||||
|
||||
|
||||
accessIdField = this.customFieldsService.getCustomField('Owner', 'workbaskets.access-items.accessId');
|
||||
custom1Field = this.customFieldsService.getCustomField('Custom 1', 'workbaskets.access-items.custom1');
|
||||
custom2Field = this.customFieldsService.getCustomField('Custom 2', 'workbaskets.access-items.custom2');
|
||||
custom3Field = this.customFieldsService.getCustomField('Custom 3', 'workbaskets.access-items.custom3');
|
||||
custom4Field = this.customFieldsService.getCustomField('Custom 4', 'workbaskets.access-items.custom4');
|
||||
custom5Field = this.customFieldsService.getCustomField('Custom 5', 'workbaskets.access-items.custom5');
|
||||
custom6Field = this.customFieldsService.getCustomField('Custom 6', 'workbaskets.access-items.custom6');
|
||||
custom7Field = this.customFieldsService.getCustomField('Custom 7', 'workbaskets.access-items.custom7');
|
||||
custom8Field = this.customFieldsService.getCustomField('Custom 8', 'workbaskets.access-items.custom8');
|
||||
custom9Field = this.customFieldsService.getCustomField('Custom 9', 'workbaskets.access-items.custom9');
|
||||
custom10Field = this.customFieldsService.getCustomField('Custom 10', 'workbaskets.access-items.custom10');
|
||||
custom11Field = this.customFieldsService.getCustomField('Custom 11', 'workbaskets.access-items.custom11');
|
||||
custom12Field = this.customFieldsService.getCustomField('Custom 12', 'workbaskets.access-items.custom12');
|
||||
|
||||
setAccessItemsGroups(accessItems: Array<AccessItemWorkbasket>) {
|
||||
const AccessItemsFormGroups = accessItems.map(accessItem => this.formBuilder.group(accessItem));
|
||||
AccessItemsFormGroups.map(accessItemGroup => {
|
||||
accessItemGroup.controls['accessId'].setValidators(Validators.required);
|
||||
for (const key of Object.keys(accessItemGroup.controls)) {
|
||||
accessItemGroup.controls[key].disable();
|
||||
}
|
||||
});
|
||||
const AccessItemsFormArray = this.formBuilder.array(AccessItemsFormGroups);
|
||||
if (!this.AccessItemsForm) { this.AccessItemsForm = this.formBuilder.group({}); }
|
||||
this.AccessItemsForm.setControl('accessItemsGroups', AccessItemsFormArray);
|
||||
if (!this.AccessItemsForm.value['workbasketKeyFilter']) { this.AccessItemsForm.addControl('workbasketKeyFilter', new FormControl()) }
|
||||
if (!this.AccessItemsForm.value['accessIdFilter']) { this.AccessItemsForm.addControl('accessIdFilter', new FormControl()) }
|
||||
};
|
||||
|
||||
get accessItemsGroups(): FormArray {
|
||||
return this.AccessItemsForm ? this.AccessItemsForm.get('accessItemsGroups') as FormArray : null;
|
||||
};
|
||||
|
||||
constructor(private formBuilder: FormBuilder,
|
||||
private customFieldsService: CustomFieldsService,
|
||||
private accessIdsService: AccessIdsService,
|
||||
private formsValidatorService: FormsValidatorService,
|
||||
private requestInProgressService: RequestInProgressService,
|
||||
private errorModalService: ErrorModalService) { }
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
onSelectAccessId(selected: AccessIdDefinition) {
|
||||
if (!selected) {
|
||||
this.AccessItemsForm = null;
|
||||
return;
|
||||
}
|
||||
if (!this.AccessItemsForm || this.accessIdPrevious !== selected.accessId) {
|
||||
this.accessIdPrevious = selected.accessId
|
||||
|
||||
this.unSubscribe(this.accessItemInformationsubscription)
|
||||
this.accessItemInformationsubscription = this.accessIdsService.getAccessItemsInformation(selected.accessId, true)
|
||||
.subscribe((accessIdsWithGroups: Array<AccessIdDefinition>) => {
|
||||
this.accessIdsWithGroups = accessIdsWithGroups;
|
||||
this.searchForAccessItemsWorkbaskets();
|
||||
},
|
||||
error => {
|
||||
this.requestInProgressService.setRequestInProgress(false);
|
||||
this.errorModalService.triggerError(
|
||||
new ErrorModel(
|
||||
'There was error while retrieving your access ids with groups',
|
||||
error
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
isFieldValid(field: string, index: number): boolean {
|
||||
return this.formsValidatorService.isFieldValid(this.accessItemsGroups[index], field);
|
||||
}
|
||||
|
||||
sorting(sort: SortingModel) {
|
||||
this.sortModel = sort;
|
||||
this.searchForAccessItemsWorkbaskets();
|
||||
}
|
||||
|
||||
searchForAccessItemsWorkbaskets() {
|
||||
this.requestInProgressService.setRequestInProgress(true);
|
||||
this.unSubscribe(this.accessItemPermissionsSubscription)
|
||||
this.accessItemPermissionsSubscription = this.accessIdsService.getAccessItemsPermissions(
|
||||
this.accessIdsWithGroups,
|
||||
this.AccessItemsForm ? this.AccessItemsForm.value.accessIdFilter : undefined,
|
||||
this.AccessItemsForm ? this.AccessItemsForm.value.workbasketKeyFilter : undefined,
|
||||
this.sortModel,
|
||||
true)
|
||||
.subscribe((accessItemsResource: AccessItemsWorkbasketResource) => {
|
||||
this.setAccessItemsGroups(accessItemsResource._embedded ? accessItemsResource._embedded.accessItems : []);
|
||||
this.requestInProgressService.setRequestInProgress(false);
|
||||
},
|
||||
error => {
|
||||
this.requestInProgressService.setRequestInProgress(false);
|
||||
this.errorModalService.triggerError(
|
||||
new ErrorModel(
|
||||
'There was error while retrieving your access items',
|
||||
error
|
||||
)
|
||||
);
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
revokeAccess() {
|
||||
|
||||
}
|
||||
|
||||
private unSubscribe(subscription: Subscription): void {
|
||||
if (subscription) { subscription.unsubscribe(); }
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.unSubscribe(this.accessItemPermissionsSubscription)
|
||||
this.unSubscribe(this.accessItemInformationsubscription)
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import { MasterAndDetailComponent } from 'app/shared/master-and-detail/master-an
|
|||
import { ClassificationListComponent } from 'app/administration/classification/master/list/classification-list.component';
|
||||
import { ClassificationDetailsComponent } from 'app/administration/classification/details/classification-details.component';
|
||||
import { DomainGuard } from 'app/guards/domain-guard';
|
||||
import { AccessItemsManagementComponent } from './access-items-management/access-items-management.component';
|
||||
|
||||
|
||||
const routes: Routes = [
|
||||
|
@ -35,7 +36,7 @@ const routes: Routes = [
|
|||
{
|
||||
path: 'classifications',
|
||||
component: MasterAndDetailComponent,
|
||||
canActivate: [DomainGuard],
|
||||
canActivate: [DomainGuard],
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
|
@ -49,6 +50,11 @@ const routes: Routes = [
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'access-items-management',
|
||||
component: AccessItemsManagementComponent,
|
||||
canActivate: [DomainGuard]
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
redirectTo: 'workbaskets',
|
||||
|
|
|
@ -16,7 +16,6 @@ import {WorkbasketInformationComponent} from './workbasket/details/information/w
|
|||
import {DistributionTargetsComponent} from './workbasket/details/distribution-targets/distribution-targets.component';
|
||||
import {DualListComponent} from './workbasket/details/distribution-targets/dual-list/dual-list.component';
|
||||
import {AccessItemsComponent} from './workbasket/details/access-items/access-items.component';
|
||||
import {IconTypeComponent} from './components/type-icon/icon-type.component';
|
||||
import {PaginationComponent} from './workbasket/master/list/pagination/pagination.component';
|
||||
import {ClassificationListComponent} from './classification/master/list/classification-list.component';
|
||||
import {ClassificationDetailsComponent} from './classification/details/classification-details.component';
|
||||
|
@ -31,6 +30,7 @@ import {ClassificationDefinitionService} from './services/classification-definit
|
|||
import {WorkbasketDefinitionService} from './services/workbasket-definition/workbasket-definition.service';
|
||||
import {ClassificationsService} from './services/classifications/classifications.service';
|
||||
import {ClassificationCategoriesService} from './services/classification-categories-service/classification-categories.service';
|
||||
import { AccessItemsManagementComponent } from 'app/administration/access-items-management/access-items-management.component';
|
||||
|
||||
const MODULES = [
|
||||
CommonModule,
|
||||
|
@ -55,7 +55,8 @@ const DECLARATIONS = [
|
|||
ClassificationListComponent,
|
||||
ImportExportComponent,
|
||||
ClassificationTypesSelectorComponent,
|
||||
ClassificationDetailsComponent
|
||||
ClassificationDetailsComponent,
|
||||
AccessItemsManagementComponent
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</ul>
|
||||
<div id="classification" class="panel panel-default classification">
|
||||
<div class="panel-heading">
|
||||
<div class="pull-right">
|
||||
<div class="pull-right btn-group">
|
||||
<button type="button" (click)="onSubmit()" class="btn btn-default btn-primary" data-toggle="tooltip" title="Save">
|
||||
<span class="glyphicon glyphicon-floppy-save" aria-hidden="true"></span>
|
||||
</button>
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
|
||||
.classification.panel{
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
margin-bottom: 0px;
|
||||
&> .panel-body {
|
||||
height: 85vh;
|
||||
max-height: 85vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<div *ngIf="workbasket" id="wb-information" class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="pull-right">
|
||||
<div class="pull-right btn-group">
|
||||
<button type="button" (click)="onSubmit()" [disabled]="action === 'COPY'" class="btn btn-default btn-primary" data-toggle="tooltip"
|
||||
title="Save">
|
||||
<span class="glyphicon glyphicon-floppy-save" aria-hidden="true"></span>
|
||||
|
|
|
@ -26,7 +26,3 @@ td {
|
|||
max-width: 150px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.has-warning.taskana-type-ahead {
|
||||
border-bottom: 1px solid #f0ad4e;
|
||||
}
|
|
@ -35,19 +35,19 @@ export class AccessItemsComponent implements OnChanges, OnDestroy {
|
|||
active: string;
|
||||
badgeMessage = '';
|
||||
|
||||
accessIdField = this.customFieldService.getCustomField('Owner', 'workbaskets.access-items.accessId');
|
||||
custom1Field = this.customFieldService.getCustomField('Custom 1', 'workbaskets.access-items.custom1');
|
||||
custom2Field = this.customFieldService.getCustomField('Custom 2', 'workbaskets.access-items.custom2');
|
||||
custom3Field = this.customFieldService.getCustomField('Custom 3', 'workbaskets.access-items.custom3');
|
||||
custom4Field = this.customFieldService.getCustomField('Custom 4', 'workbaskets.access-items.custom4');
|
||||
custom5Field = this.customFieldService.getCustomField('Custom 5', 'workbaskets.access-items.custom5');
|
||||
custom6Field = this.customFieldService.getCustomField('Custom 6', 'workbaskets.access-items.custom6');
|
||||
custom7Field = this.customFieldService.getCustomField('Custom 7', 'workbaskets.access-items.custom7');
|
||||
custom8Field = this.customFieldService.getCustomField('Custom 8', 'workbaskets.access-items.custom8');
|
||||
custom9Field = this.customFieldService.getCustomField('Custom 9', 'workbaskets.access-items.custom9');
|
||||
custom10Field = this.customFieldService.getCustomField('Custom 10', 'workbaskets.access-items.custom10');
|
||||
custom11Field = this.customFieldService.getCustomField('Custom 11', 'workbaskets.access-items.custom11');
|
||||
custom12Field = this.customFieldService.getCustomField('Custom 12', 'workbaskets.access-items.custom12');
|
||||
accessIdField = this.customFieldsService.getCustomField('Owner', 'workbaskets.access-items.accessId');
|
||||
custom1Field = this.customFieldsService.getCustomField('Custom 1', 'workbaskets.access-items.custom1');
|
||||
custom2Field = this.customFieldsService.getCustomField('Custom 2', 'workbaskets.access-items.custom2');
|
||||
custom3Field = this.customFieldsService.getCustomField('Custom 3', 'workbaskets.access-items.custom3');
|
||||
custom4Field = this.customFieldsService.getCustomField('Custom 4', 'workbaskets.access-items.custom4');
|
||||
custom5Field = this.customFieldsService.getCustomField('Custom 5', 'workbaskets.access-items.custom5');
|
||||
custom6Field = this.customFieldsService.getCustomField('Custom 6', 'workbaskets.access-items.custom6');
|
||||
custom7Field = this.customFieldsService.getCustomField('Custom 7', 'workbaskets.access-items.custom7');
|
||||
custom8Field = this.customFieldsService.getCustomField('Custom 8', 'workbaskets.access-items.custom8');
|
||||
custom9Field = this.customFieldsService.getCustomField('Custom 9', 'workbaskets.access-items.custom9');
|
||||
custom10Field = this.customFieldsService.getCustomField('Custom 10', 'workbaskets.access-items.custom10');
|
||||
custom11Field = this.customFieldsService.getCustomField('Custom 11', 'workbaskets.access-items.custom11');
|
||||
custom12Field = this.customFieldsService.getCustomField('Custom 12', 'workbaskets.access-items.custom12');
|
||||
|
||||
accessItemsResource: WorkbasketAccessItemsResource;
|
||||
accessItemsClone: Array<WorkbasketAccessItems>;
|
||||
|
@ -83,7 +83,7 @@ export class AccessItemsComponent implements OnChanges, OnDestroy {
|
|||
private errorModalService: ErrorModalService,
|
||||
private savingWorkbaskets: SavingWorkbasketService,
|
||||
private requestInProgressService: RequestInProgressService,
|
||||
private customFieldService: CustomFieldsService,
|
||||
private customFieldsService: CustomFieldsService,
|
||||
private formBuilder: FormBuilder,
|
||||
private formsValidatorService: FormsValidatorService) {
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div *ngIf="workbasket" id="wb-information" class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="pull-right">
|
||||
<div class="pull-right btn-group">
|
||||
<button type="button" (click)="onSave()" [disabled]="action === 'COPY'" class="btn btn-default btn-primary" data-toggle="tooltip"
|
||||
title="Save">
|
||||
<span class="glyphicon glyphicon-floppy-save" aria-hidden="true"></span>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<taskana-spinner [isRunning]="requestInProgress" class="floating"></taskana-spinner>
|
||||
<div *ngIf="workbasket" id="wb-information" class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="pull-right">
|
||||
<div class="pull-right btn-group">
|
||||
<button type="button" (click)="onSubmit()" class="btn btn-default btn-primary" data-toggle="tooltip" title="Save">
|
||||
<span class="glyphicon glyphicon-floppy-save" aria-hidden="true"></span>
|
||||
</button>
|
||||
|
@ -30,7 +30,7 @@
|
|||
<input type="text" required #key="ngModel" class="form-control" id="wb-key" placeholder="Key" [(ngModel)]="workbasket.key"
|
||||
name="workbasket.key">
|
||||
<taskana-field-error-display [displayError]="!isFieldValid('workbasket.key')" [validationTrigger]="this.toogleValidationMap.get('workbasket.key')"
|
||||
errorMessage="* Key is required">
|
||||
errorMessage="* Key is required" >
|
||||
</taskana-field-error-display>
|
||||
</div>
|
||||
<div class="form-group required">
|
||||
|
@ -41,11 +41,11 @@
|
|||
errorMessage="* Name is required">
|
||||
</taskana-field-error-display>
|
||||
</div>
|
||||
<div class="form-group required">
|
||||
<label for="wb-owner" class="control-label">Owner</label>
|
||||
<div class="input-group form-group required">
|
||||
<label for="wb-owner" class="control-label ">Owner</label>
|
||||
<taskana-type-ahead *ngIf="ownerField.lookupField else ownerInput" required #owner="ngModel" name="workbasket.owner" [(ngModel)]="workbasket.owner"
|
||||
placeHolderMessage="* Owner is required" [validationValue]="this.toogleValidationMap.get('workbasket.owner')"
|
||||
[displayError]="!isFieldValid('workbasket.owner')"></taskana-type-ahead>
|
||||
[displayError]="!isFieldValid('workbasket.owner')" width="100%"></taskana-type-ahead>
|
||||
<ng-template #ownerInput>
|
||||
<input type="text" required #owner="ngModel" class="form-control" id="wb-owner" placeholder="Owner" [(ngModel)]="workbasket.owner"
|
||||
name="workbasket.owner">
|
||||
|
|
|
@ -4,21 +4,18 @@
|
|||
<button type="button" (click)="addWorkbasket()" data-toggle="tooltip" title="Add" class="btn btn-default">
|
||||
<span class="glyphicon glyphicon-plus green-blue" aria-hidden="true"></span>
|
||||
</button>
|
||||
<taskana-import-export-component (importSucessful)="importEvent()"
|
||||
[currentSelection]="selectionToImport"></taskana-import-export-component>
|
||||
<taskana-import-export-component (importSucessful)="importEvent()" [currentSelection]="selectionToImport"></taskana-import-export-component>
|
||||
</div>
|
||||
<div class="pull-right margin-right">
|
||||
<taskana-sort
|
||||
[sortingFields]="sortingFields"
|
||||
(performSorting)="sorting($event)"></taskana-sort>
|
||||
<button class="btn btn-default collapsed" type="button" id="collapsedMenufilterWb" aria-expanded="false"
|
||||
(click)="toolbarState=!toolbarState" data-toggle="tooltip" title="Filter">
|
||||
<div class="margin-right pull-right ">
|
||||
<button class="btn btn-default collapsed" type="button" id="collapsedMenufilterWb" aria-expanded="false" (click)="toolbarState=!toolbarState"
|
||||
data-toggle="tooltip" title="Filter">
|
||||
<span class="glyphicon glyphicon-filter blue"></span>
|
||||
</button>
|
||||
<taskana-sort [sortingFields]="sortingFields" (performSorting)="sorting($event)" class="btn-group"></taskana-sort>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div [@toggleDown]="toolbarState" class="row no-overflow">
|
||||
<taskana-filter (performFilter)="filtering($event)"></taskana-filter>
|
||||
</div>
|
||||
</li>
|
||||
</li>
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
.workbasket-list-full-height{
|
||||
height: calc(100vh - 55px);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,9 @@ import { SelectedRouteService } from './services/selected-route/selected-route';
|
|||
import { FormsValidatorService } from './shared/services/forms/forms-validator.service';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { SharedModule } from './shared/shared.module';
|
||||
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||
|
||||
export const configureTests = (configure: (testBed: TestBed) => void) => {
|
||||
const testBed = getTestBed();
|
||||
|
@ -36,7 +38,7 @@ export const configureTests = (configure: (testBed: TestBed) => void) => {
|
|||
|
||||
configure(testBed);
|
||||
testBed.configureTestingModule({
|
||||
imports: [BrowserAnimationsModule, SharedModule],
|
||||
imports: [BrowserAnimationsModule, SharedModule, FormsModule, ReactiveFormsModule, HttpClientModule, AngularSvgIconModule],
|
||||
providers: [{ provide: TaskanaEngineService, useClass: TaskanaEngineServiceMock },
|
||||
{ provide: DomainService, useClass: DomainServiceMock }, CustomFieldsService, RemoveConfirmationService,
|
||||
AlertService, ErrorModalService, RequestInProgressService, OrientationService, SelectedRouteService, FormsValidatorService]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<nav class="navbar navbar-fixed-top">
|
||||
<div class="navbar no-border-radius navbar-inverse no-gutter col-xs-12">
|
||||
<nav class="navbar main navbar-fixed-top">
|
||||
<div class="navbar no-border-radius navbar-inverse no-gutter col-xs-12">
|
||||
<div class="pull-left col-sm-3 col-md-4">
|
||||
<button type="button" *ngIf="!showNavbar" class="btn btn-default navbar-toggle show pull-left" (click)="toogleNavBar();"
|
||||
aria-expanded="true" aria-controls="navbar" data-toggle="tooltip" title="Menu">
|
||||
|
@ -53,6 +53,10 @@
|
|||
<span (click)="toogleNavBar()" class="col-xs-6" routerLink="administration/classifications" aria-controls="Classifications"
|
||||
routerLinkActive="active">Classifications</span>
|
||||
</div>
|
||||
<div class="row submenu" [ngClass]="{'selected': selectedRoute.indexOf('access-items-management') !== -1}">
|
||||
<span (click)="toogleNavBar()" class="col-xs-6" routerLink="administration/access-items-management" aria-controls="Access items"
|
||||
routerLinkActive="active">Access items</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="monitorAccess" class="row menu" [ngClass]="{'selected': selectedRoute.indexOf('monitor') !== -1}">
|
||||
<span (click)="toogleNavBar()" routerLink="{{monitorUrl}}" aria-controls="Monitor" routerLinkActive="active">Monitor</span>
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
$background-color: #224562;
|
||||
$background-color-sidenav: #175263;
|
||||
$selected-border-color: #22a39f;
|
||||
$unselected-text: #9d9d9d;
|
||||
@import './src/assets/_variables';
|
||||
|
||||
.navbar.main:before {
|
||||
@include degraded-bar(right, 100%, 5px)
|
||||
}
|
||||
|
||||
.navbar-inverse {
|
||||
border:none;
|
||||
background-color: $background-color;
|
||||
box-shadow: 0px 1px 10px -1px $background-color;
|
||||
|
||||
background-color: $dark-green;
|
||||
box-shadow: 0px 1px 5px -1px black;
|
||||
}
|
||||
|
||||
.navbar-toggle{
|
||||
margin: 5px 0px;
|
||||
margin: 3px 0px;
|
||||
font-size: 20px;
|
||||
&.logout{
|
||||
font-size: 20px;
|
||||
|
@ -19,7 +19,7 @@ $unselected-text: #9d9d9d;
|
|||
|
||||
}
|
||||
button.navbar-toggle:hover > span{
|
||||
color:$selected-border-color;
|
||||
color:$aquamarine;
|
||||
}
|
||||
ul.nav > p {
|
||||
white-space: nowrap;
|
||||
|
@ -35,15 +35,15 @@ ul.nav > p {
|
|||
svg-icon.logo {
|
||||
float: left;
|
||||
width: 150px;
|
||||
height: 55px;
|
||||
padding: 6px 5px 5px 5px;
|
||||
height: 50px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
h2.navbar-brand{
|
||||
vertical-align: middle;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
padding: 17px 0px 0px 0px;
|
||||
padding: 15px 0px 0px 0px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
|
@ -65,10 +65,10 @@ h2.navbar-brand{
|
|||
cursor: pointer;
|
||||
> button {
|
||||
color: white;
|
||||
background-color: $background-color;
|
||||
background-color: $dark-green;
|
||||
border: none;
|
||||
font-size: 16px;
|
||||
border-bottom: 1px solid grey;
|
||||
border-bottom: 1px solid $dark-green;
|
||||
margin-left:5px;
|
||||
}
|
||||
}
|
||||
|
@ -79,11 +79,10 @@ h2.navbar-brand{
|
|||
}
|
||||
|
||||
.nav-version {
|
||||
color: $unselected-text;
|
||||
margin: 5px;
|
||||
color: $grey;
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
font-size: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -105,22 +104,22 @@ h2.navbar-brand{
|
|||
.sidenav {
|
||||
position:fixed;
|
||||
z-index:999;
|
||||
margin-top: -1px;
|
||||
box-shadow: none;
|
||||
height: 100%;
|
||||
background-color: $background-color-sidenav;
|
||||
box-shadow: 3px 0px 10px -1px $background-color;
|
||||
background-color: $dark-green;
|
||||
box-shadow: 3px 0px 10px -1px $dark-green;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
height: 55px;
|
||||
height: 50px;
|
||||
margin-bottom: 0px;
|
||||
|
||||
}
|
||||
|
||||
.menu,.submenu > span {
|
||||
margin-top: 15px;
|
||||
font-size: 20px;
|
||||
|
||||
width: 100%;
|
||||
font-family: inherit;
|
||||
font-weight: 500;
|
||||
line-height: 1.1;
|
||||
|
@ -128,7 +127,7 @@ h2.navbar-brand{
|
|||
|
||||
.menu,.submenu > span {
|
||||
padding-left: 12px;
|
||||
color: $unselected-text;
|
||||
color: $grey;
|
||||
outline: none;
|
||||
|
||||
}
|
||||
|
@ -136,8 +135,7 @@ h2.navbar-brand{
|
|||
background-color: transparent;
|
||||
&> span{
|
||||
padding-left: 10px;
|
||||
border-left: $selected-border-color 5px solid;
|
||||
|
||||
border-left: $pallete-green 5px solid;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +145,7 @@ h2.navbar-brand{
|
|||
}
|
||||
|
||||
a {
|
||||
color: $unselected-text;
|
||||
color: $grey;
|
||||
&:hover{
|
||||
color:white;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import { WindowRefService } from 'app/services/window/window.service';
|
|||
import { UserGuard } from 'app/guards/user-guard';
|
||||
import { TaskanaEngineService } from '../../services/taskana-engine/taskana-engine.service';
|
||||
import { expandRight } from 'app/shared/animations/expand.animation';
|
||||
import { VersionModel } from 'app/models/version';
|
||||
@Component({
|
||||
selector: 'taskana-nav-bar',
|
||||
templateUrl: './nav-bar.component.html',
|
||||
|
@ -25,6 +24,7 @@ export class NavBarComponent implements OnInit, OnDestroy {
|
|||
titleAdministration = 'Administration';
|
||||
titleWorkbaskets = 'Workbaskets';
|
||||
titleClassifications = 'Classifications';
|
||||
titleAccessItems = 'Access items';
|
||||
titleMonitor = 'Monitor';
|
||||
titleWorkplace = 'Workplace';
|
||||
showNavbar = false;
|
||||
|
@ -101,6 +101,8 @@ export class NavBarComponent implements OnInit, OnDestroy {
|
|||
this.title = this.titleMonitor;
|
||||
} else if (value.indexOf('workplace') === 0) {
|
||||
this.title = this.titleWorkplace;
|
||||
} else if (value.indexOf('access-items') === 0) {
|
||||
this.title = this.titleAccessItems;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@import './src/assets/_variables';
|
||||
|
||||
.big {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
|
@ -20,9 +22,9 @@
|
|||
position: relative;
|
||||
& > .icon-wrap {
|
||||
border-radius: 50%;
|
||||
border: solid 3px #22a39f;
|
||||
width: 74px;
|
||||
height: 74px;
|
||||
border: solid 2px #22a39f;
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
overflow: hidden;
|
||||
background-color: #175263;
|
||||
position: absolute;
|
||||
|
@ -42,10 +44,10 @@
|
|||
|
||||
.icon:before { content: '';
|
||||
position: absolute;
|
||||
border-bottom: solid 3px #22a39f;
|
||||
@include degraded-bar(right, 100%, 4px);
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
transform: translateY(-33%);
|
||||
height: 2px;
|
||||
transform: translateY(33px);
|
||||
-webkit-box-shadow: 0px 3px 3px #416b6a;
|
||||
-moz-box-shadow: 0px 3px 3px #416b6a;
|
||||
box-shadow: 0px 3px 3px #416b6a;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import { Links } from './links';
|
||||
import { AccessItemWorkbasket } from './access-item-workbasket';
|
||||
|
||||
export class AccessItemsWorkbasketResource {
|
||||
constructor(
|
||||
public _embedded: { 'accessItems': Array<AccessItemWorkbasket> } = { 'accessItems': [] },
|
||||
public _links: Links = undefined
|
||||
) { }
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
import { Links } from './links';
|
||||
|
||||
export class AccessItemWorkbasket {
|
||||
constructor(
|
||||
public accessItemId: string = '',
|
||||
public workbasketKey: string = '',
|
||||
public accessId: string = '',
|
||||
public permRead: boolean = false,
|
||||
public permOpen: boolean = false,
|
||||
public permAppend: boolean = false,
|
||||
public permTransfer: boolean = false,
|
||||
public permDistribute: boolean = false,
|
||||
public permCustom1: boolean = false,
|
||||
public permCustom2: boolean = false,
|
||||
public permCustom3: boolean = false,
|
||||
public permCustom4: boolean = false,
|
||||
public permCustom5: boolean = false,
|
||||
public permCustom6: boolean = false,
|
||||
public permCustom7: boolean = false,
|
||||
public permCustom8: boolean = false,
|
||||
public permCustom9: boolean = false,
|
||||
public permCustom10: boolean = false,
|
||||
public permCustom11: boolean = false,
|
||||
public permCustom12: boolean = false,
|
||||
public _links: Links = undefined
|
||||
) { }
|
||||
}
|
|
@ -7,7 +7,7 @@ export class SelectedRouteService {
|
|||
|
||||
public selectedRouteTriggered = new Subject<string>();
|
||||
|
||||
private detailRoutes: Array<string> = ['workbaskets', 'classifications', 'monitor', 'workplace'];
|
||||
private detailRoutes: Array<string> = ['workbaskets', 'classifications', 'monitor', 'workplace', 'access-items-management'];
|
||||
|
||||
constructor(private router: Router) { }
|
||||
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
<h3 class="grey">Select a classification</h3>
|
||||
<svg-icon class="img-responsive empty-icon" src="./assets/icons/classification-empty.svg"></svg-icon>
|
||||
</div>
|
||||
<div *ngIf="currentRoute === 'tasks'" class="center-block no-detail">
|
||||
<h3 class="grey">Select a Task</h3>
|
||||
<span class="glyphicon glyphicon-object-align-bottom"></span>
|
||||
</div>
|
||||
<div *ngIf="currentRoute === 'tasks'" class="center-block no-detail">
|
||||
<h3 class="grey">Select a Task</h3>
|
||||
<span class="glyphicon glyphicon-object-align-bottom"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,24 +1,47 @@
|
|||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { environment } from 'environments/environment';
|
||||
|
||||
|
||||
import { AccessIdDefinition } from 'app/models/access-id';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { AccessItemsWorkbasketResource } from 'app/models/access-item-workbasket-resource';
|
||||
import { TaskanaQueryParameters } from 'app/shared/util/query-parameters';
|
||||
import { SortingModel } from 'app/models/sorting';
|
||||
|
||||
@Injectable()
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AccessIdsService {
|
||||
|
||||
private url = environment.taskanaRestUrl + '/v1/access-ids';
|
||||
|
||||
private accessItemsRef: Observable<AccessItemsWorkbasketResource> = new Observable();
|
||||
constructor(
|
||||
private httpClient: HttpClient) { }
|
||||
|
||||
getAccessItemsInformation(token: string): Observable<Array<AccessIdDefinition>> {
|
||||
getAccessItemsInformation(token: string, searchInGroups = false): Observable<Array<AccessIdDefinition>> {
|
||||
if (!token || token.length < 3) {
|
||||
return of([]);
|
||||
}
|
||||
return this.httpClient.get<Array<AccessIdDefinition>>(`${this.url}?searchFor=${token}`);
|
||||
return this.httpClient.get<Array<AccessIdDefinition>>(`${this.url}?searchFor=${token}&searchInGroups=${searchInGroups}`);
|
||||
};
|
||||
|
||||
getAccessItemsPermissions(
|
||||
accessIds: Array<AccessIdDefinition>,
|
||||
accessIdLike: string = undefined,
|
||||
workbasketKeyLike: string = undefined,
|
||||
sortModel: SortingModel = new SortingModel('workbasket-key'),
|
||||
forceRequest: boolean = false): Observable<AccessItemsWorkbasketResource> {
|
||||
|
||||
if (this.accessItemsRef && !forceRequest) {
|
||||
return this.accessItemsRef;
|
||||
}
|
||||
|
||||
return this.accessItemsRef = this.httpClient.get<AccessItemsWorkbasketResource>(encodeURI(
|
||||
`${environment.taskanaRestUrl}/v1/workbasket-access/${TaskanaQueryParameters.getQueryParameters(sortModel.sortBy,
|
||||
sortModel.sortDirection,
|
||||
undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined,
|
||||
accessIds.map((values: AccessIdDefinition) => {
|
||||
return values.accessId
|
||||
}).join('|'),
|
||||
accessIdLike, workbasketKeyLike)}`))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,29 +1,28 @@
|
|||
<div class="dropdown clearfix btn-group">
|
||||
<button [disabled]="!enabled" class="btn btn-default" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
<span class="glyphicon {{sort.sortDirection === 'asc'? 'glyphicon-sort-by-attributes-alt' : 'glyphicon-sort-by-attributes' }} blue"
|
||||
data-toggle= "tooltip" title="{{sort.sortDirection === 'asc'? 'A-Z' : 'Z-A' }}"></span>
|
||||
</button>
|
||||
|
||||
<div class="dropdown-menu dropdown-menu-right sortby-dropdown popup" aria-labelledby="sortingDropdown">
|
||||
<div>
|
||||
<div class="col-xs-6">
|
||||
<h5>Sort By</h5>
|
||||
</div>
|
||||
<button id="sort-by-direction-asc" type="button" (click)="changeOrder('asc')" data-toggle="tooltip" title="A-Z" class="btn btn-default {{sort.sortDirection === 'asc'? 'selected' : '' }}">
|
||||
<div class="dropdown">
|
||||
<button [disabled]="!enabled" class="btn btn-default" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
<span class="glyphicon {{sort.sortDirection === 'asc'? 'glyphicon-sort-by-attributes-alt' : 'glyphicon-sort-by-attributes' }} blue"
|
||||
data-toggle="tooltip" title="{{sort.sortDirection === 'asc'? 'A-Z' : 'Z-A' }}"></span>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-{{menuPosition}} sortby-dropdown popup" aria-labelledby="sortingDropdown">
|
||||
<div>
|
||||
<div class="col-xs-6">
|
||||
<h5>Sort By</h5>
|
||||
</div>
|
||||
<button id="sort-by-direction-asc" type="button" (click)="changeOrder('asc')" data-toggle="tooltip" title="A-Z" class="btn btn-default {{sort.sortDirection === 'asc'? 'selected' : '' }}">
|
||||
<span class="glyphicon glyphicon-sort-by-attributes-alt blue" aria-hidden="true"></span>
|
||||
</button>
|
||||
<button id= "sort-by-direction-desc" type="button" (click)="changeOrder('desc')" data-toggle="tooltip" title="Z-A" class="btn btn-default {{sort.sortDirection === 'desc'? 'selected' : '' }}" >
|
||||
<span class="glyphicon glyphicon-sort-by-attributes blue" aria-hidden="true"></span>
|
||||
</button>
|
||||
</button>
|
||||
<button id="sort-by-direction-desc" type="button" (click)="changeOrder('desc')" data-toggle="tooltip" title="Z-A" class="btn btn-default {{sort.sortDirection === 'desc'? 'selected' : '' }}">
|
||||
<span class="glyphicon glyphicon-sort-by-attributes blue" aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div role="separator" class="divider"></div>
|
||||
<li id="sort-by-{{sortingField.key}}" (click)="changeSortBy(sortingField.key)" *ngFor="let sortingField of sortingFields | mapValues">
|
||||
<a>
|
||||
<label>
|
||||
<span class="glyphicon {{sort.sortBy === sortingField.key? 'glyphicon-check': 'glyphicon-unchecked'}} blue" aria-hidden="true"></span>
|
||||
{{sortingField.value}}
|
||||
</label>
|
||||
</a>
|
||||
</li>
|
||||
</div>
|
||||
<div role="separator" class="divider"></div>
|
||||
<li id="sort-by-{{sortingField.key}}" (click)="changeSortBy(sortingField.key)" *ngFor="let sortingField of sortingFields | mapValues">
|
||||
<a>
|
||||
<label>
|
||||
<span class="glyphicon {{sort.sortBy === sortingField.key? 'glyphicon-check': 'glyphicon-unchecked'}} blue" aria-hidden="true"></span>
|
||||
{{sortingField.value}}
|
||||
</label>
|
||||
</a>
|
||||
</li>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -9,6 +9,7 @@ import {Direction, SortingModel} from 'app/models/sorting';
|
|||
export class SortComponent implements OnInit {
|
||||
@Input() sortingFields: Map<string, string>;
|
||||
@Input() enabled = true;
|
||||
@Input() menuPosition = 'right';
|
||||
|
||||
@Output() performSorting = new EventEmitter<SortingModel>();
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div *ngIf="dataSource" class="custom-form-control">
|
||||
<div *ngIf="dataSource" class="custom-form-control" [ngStyle]="{'width': width ? width : auto }">
|
||||
<ng-template class="wrapper-text" #customItemTemplate let-model="item" let-index="indexTemplate" let-query="query">
|
||||
<div (mousedown)="typeaheadOnSelect({'item':model})">
|
||||
<div>
|
||||
|
@ -11,13 +11,19 @@
|
|||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
<div [ngClass]="{'hidden': !dataSource.selected || typing}" class="wrapper-text" (click)="setTyping(true)">
|
||||
<div [ngClass]="{'hidden': !dataSource.selected || typing,
|
||||
'disable': disable}" class="wrapper-text" (click)="setTyping(true)">
|
||||
<span>
|
||||
<label>
|
||||
{{dataSource.selected?.accessId}}
|
||||
</label>
|
||||
</span>
|
||||
<div>{{dataSource.selected?.name}}</div>
|
||||
<div class="input-group">
|
||||
<div>{{dataSource.selected?.name}}</div>
|
||||
<button *ngIf="!disable" type="button" (click)="clear()" title="clear search" class="btn rounded remove">
|
||||
<span class="glyphicon glyphicon-remove-sign" aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div [ngClass]="{'hidden': dataSource.selected && !typing}">
|
||||
<span class="field-label-wrapper">
|
||||
|
@ -25,13 +31,19 @@
|
|||
{{dataSource.selected?.name}}
|
||||
</label>
|
||||
</span>
|
||||
<div *ngIf="typeaheadLoading" class="loading">
|
||||
<taskana-spinner [isRunning]="typeaheadLoading" positionClass="type-ahead-spinner"></taskana-spinner>
|
||||
|
||||
<div class="input-group">
|
||||
<input #inputTypeAhead class=" form-control input-text" (blur)="typeaheadOnSelect({'item':dataSource.selected})" name="accessItem-{{index}}"
|
||||
required #accessItemName="ngModel" [(ngModel)]="value" [typeahead]="dataSource" typeaheadOptionField="name" [typeaheadItemTemplate]="customItemTemplate"
|
||||
(typeaheadOnSelect)="typeaheadOnSelect($event, index)" [typeaheadScrollable]="true" [typeaheadOptionsInScrollableView]="typeaheadOptionsInScrollableView"
|
||||
[typeaheadMinLength]="typeaheadMinLength" [typeaheadWaitMs]="typeaheadWaitMs" (typeaheadLoading)="changeTypeaheadLoading($event)"
|
||||
placeholder="{{displayError? placeHolderMessage: ''}}" [@validation]="validationValue">
|
||||
<button *ngIf="!typeaheadLoading" type="button" title="search" class="btn rounded blue">
|
||||
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
|
||||
</button>
|
||||
<div *ngIf="typeaheadLoading" class="loading">
|
||||
<taskana-spinner [isRunning]="typeaheadLoading" positionClass="type-ahead-spinner"></taskana-spinner>
|
||||
</div>
|
||||
</div>
|
||||
<input #inputTypeAhead class=" form-control input-text" (blur)="typeaheadOnSelect({'item':dataSource.selected})" name="accessItem-{{index}}"
|
||||
required #accessItemName="ngModel" [(ngModel)]="value" [typeahead]="dataSource" typeaheadOptionField="name" [typeaheadItemTemplate]="customItemTemplate"
|
||||
(typeaheadOnSelect)="typeaheadOnSelect($event, index)" [typeaheadScrollable]="true" [typeaheadOptionsInScrollableView]="typeaheadOptionsInScrollableView"
|
||||
[typeaheadMinLength]="typeaheadMinLength" [typeaheadWaitMs]="typeaheadWaitMs" (typeaheadLoading)="changeTypeaheadLoading($event)"
|
||||
placeholder="{{displayError? placeHolderMessage: ''}}" [@validation]="validationValue">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,25 +1,34 @@
|
|||
$blue: #2e9eca;
|
||||
$grey: #ddd;
|
||||
$invalid: #a94442;
|
||||
@import './src/assets/_colors';
|
||||
|
||||
.wrapper-text {
|
||||
min-width: 150px;
|
||||
height: 47px;
|
||||
& label {
|
||||
width: 100%;
|
||||
margin-bottom: 0px;
|
||||
padding-left: 12px;
|
||||
font-style: italic;
|
||||
overflow: hidden;
|
||||
}
|
||||
& div {
|
||||
width: 100%;
|
||||
border-bottom: 1px solid $grey;
|
||||
margin-top:6px;
|
||||
padding-left: 12px;
|
||||
&> div{
|
||||
&> div {
|
||||
border-bottom: 1px solid $light-grey;
|
||||
margin-top:6px;
|
||||
padding-left: 12px;
|
||||
min-width: 175px;
|
||||
}
|
||||
}
|
||||
> div{
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
padding-left: 12px;
|
||||
padding-right: 35px;
|
||||
}
|
||||
|
||||
}
|
||||
.custom-form-control {
|
||||
height: 50px;
|
||||
& .input-group{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,34 +38,44 @@ $invalid: #a94442;
|
|||
border: none;
|
||||
padding: 0px;
|
||||
border-radius: 0px;
|
||||
//margin-top: 18px;
|
||||
height: 22px;
|
||||
border-bottom: 1px solid $grey;
|
||||
min-width: 150px;
|
||||
height: 28px;
|
||||
border-bottom: 1px solid $light-grey;
|
||||
&:focus{
|
||||
border-bottom: 1px solid $blue;
|
||||
border-bottom: 1px solid $aquamarine;
|
||||
}
|
||||
padding-left: 12px;
|
||||
padding-right: 35px;
|
||||
|
||||
}
|
||||
|
||||
.field-label-wrapper{
|
||||
position: relative;
|
||||
//left: 8px;
|
||||
height: 28px;
|
||||
padding-left: 12px;
|
||||
box-sizing: content-box;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
.form-control:focus {
|
||||
border-color: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.loading {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.btn.rounded {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
|
||||
}
|
||||
|
||||
::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
|
||||
color: $invalid;
|
||||
opacity: 1; /* Firefox */
|
||||
|
@ -67,4 +86,8 @@ $invalid: #a94442;
|
|||
|
||||
::-ms-input-placeholder { /* Microsoft Edge */
|
||||
color: $invalid;
|
||||
}
|
||||
|
||||
.disable {
|
||||
cursor: not-allowed;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, OnInit, Input, ViewChild, forwardRef } from '@angular/core';
|
||||
import { Component, OnInit, Input, ViewChild, forwardRef, Output, EventEmitter } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { TypeaheadMatch } from 'ngx-bootstrap/typeahead';
|
||||
|
||||
|
@ -6,7 +6,7 @@ import { AccessIdsService } from 'app/shared/services/access-ids/access-ids.serv
|
|||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
import { highlight } from 'app/shared/animations/validation.animation';
|
||||
import { mergeMap } from 'rxjs/operators';
|
||||
|
||||
import { AccessIdDefinition } from 'app/models/access-id';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-type-ahead',
|
||||
|
@ -35,6 +35,15 @@ export class TypeAheadComponent implements OnInit, ControlValueAccessor {
|
|||
@Input()
|
||||
displayError;
|
||||
|
||||
@Input()
|
||||
width;
|
||||
|
||||
@Input()
|
||||
disable;
|
||||
|
||||
@Output()
|
||||
onSelect = new EventEmitter<AccessIdDefinition>();
|
||||
|
||||
@ViewChild('inputTypeAhead')
|
||||
private inputTypeAhead;
|
||||
|
||||
|
@ -107,11 +116,13 @@ export class TypeAheadComponent implements OnInit, ControlValueAccessor {
|
|||
if (event && event.item) {
|
||||
this.value = event.item.accessId;
|
||||
this.dataSource.selected = event.item;
|
||||
this.onSelect.emit(this.dataSource.selected)
|
||||
}
|
||||
this.setTyping(false);
|
||||
}
|
||||
|
||||
setTyping(value) {
|
||||
if (this.disable) { return true; }
|
||||
if (value) {
|
||||
setTimeout(() => {
|
||||
this.inputTypeAhead.nativeElement.focus();
|
||||
|
@ -129,4 +140,11 @@ export class TypeAheadComponent implements OnInit, ControlValueAccessor {
|
|||
return text.toLocaleLowerCase().split(str).join(`<strong>${str}</strong>`);
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.value = null;
|
||||
this.innerValue = null;
|
||||
this.dataSource.selected = null
|
||||
this.onSelect.emit(this.dataSource.selected)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,10 +12,14 @@ export class TaskanaQueryParameters {
|
|||
static OWNERLIKE = 'owner-like';
|
||||
static TYPE = 'type';
|
||||
static KEY = 'key';
|
||||
static WORKBASKET_KEY = 'workbasket-key';
|
||||
static KEYLIKE = 'key-like';
|
||||
|
||||
// Access
|
||||
static REQUIREDPERMISSION = 'required-permission';
|
||||
static ACCESSIDS = 'access-ids';
|
||||
static ACCESSIDLIKE = 'access-id-like';
|
||||
static WORKBASKETKEYLIKE = 'workbasket-key-like';
|
||||
|
||||
// Pagination
|
||||
static PAGE = 'page';
|
||||
|
@ -26,7 +30,6 @@ export class TaskanaQueryParameters {
|
|||
// Domain
|
||||
static DOMAIN = 'domain';
|
||||
|
||||
|
||||
public static getQueryParameters(sortBy: string = undefined,
|
||||
order: string = undefined,
|
||||
name: string = undefined,
|
||||
|
@ -40,7 +43,10 @@ export class TaskanaQueryParameters {
|
|||
requiredPermission: string = undefined,
|
||||
page: number = undefined,
|
||||
pageSize: number = undefined,
|
||||
domain: string = undefined): string {
|
||||
domain: string = undefined,
|
||||
accessIds: string = undefined,
|
||||
accessIdLike: string = undefined,
|
||||
workbasketKeyLike: string = undefined): string {
|
||||
let query = '?';
|
||||
query += sortBy ? `${this.SORTBY}=${sortBy}&` : '';
|
||||
query += order ? `${this.ORDER}=${order}&` : '';
|
||||
|
@ -55,7 +61,10 @@ export class TaskanaQueryParameters {
|
|||
query += requiredPermission ? `${this.REQUIREDPERMISSION}=${requiredPermission}&` : '';
|
||||
query += page ? `${this.PAGE}=${page}&` : '';
|
||||
query += pageSize ? `${this.PAGESIZE}=${pageSize}&` : '';
|
||||
query += domain !== undefined ? `${this.DOMAIN}=${domain}&` : '';
|
||||
query += domain ? `${this.DOMAIN}=${domain}&` : '';
|
||||
query += accessIds ? `${this.ACCESSIDS}=${accessIds}&` : '';
|
||||
query += accessIdLike ? `${this.ACCESSIDLIKE}=${accessIdLike}&` : '';
|
||||
query += workbasketKeyLike ? `${this.WORKBASKETKEYLIKE}=${workbasketKeyLike}&` : '';
|
||||
|
||||
if (query.lastIndexOf('&') === query.length - 1) {
|
||||
query = query.slice(0, query.lastIndexOf('&'))
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
$blue-green: #11c584;
|
||||
$blue: #2e9eca;
|
||||
$green: #246972;
|
||||
$dark-green: #175263;
|
||||
$grey: grey;
|
||||
$light-grey: #ddd;
|
||||
$brown: #f0ad4e;
|
||||
$invalid: #a94442;
|
||||
$aquamarine: #22a39f;
|
||||
$pallete-blue: #36bcee;
|
||||
$pallete-green: #5fbca1;
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
.placeholder {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
|
||||
.placeholder img {
|
||||
display: inline-block;
|
||||
|
@ -201,6 +199,10 @@ svg-icon.fa-fw > svg {
|
|||
vertical-align: middle;
|
||||
}
|
||||
|
||||
body{
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.table-center > tbody > tr > td {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
|
@ -231,7 +233,7 @@ svg-icon.fa-fw > svg {
|
|||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
|
||||
.dropdown-menu {
|
||||
display: block;
|
||||
opacity: 0;
|
||||
|
@ -271,22 +273,28 @@ svg-icon.fa-fw > svg {
|
|||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.container {
|
||||
@media (min-width: 1200px){
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
taskana-workbasket-information, taskana-workbasket-access-items, taskana-workbaskets-distribution-targets, taskana-monitor-tasks, taskana-monitor-workbaskets, taskana-monitor-classification-tasks {
|
||||
&> .panel{
|
||||
taskana-workbasket-information, taskana-workbasket-access-items, taskana-workbaskets-distribution-targets, taskana-monitor-tasks,
|
||||
taskana-monitor-workbaskets, taskana-monitor-classification-tasks, taskana-access-items-management, taskana-classification-details,taskana-workbasket-details {
|
||||
& .panel{
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
margin-bottom: 0px;
|
||||
&> .panel-body {
|
||||
height: 80vh;
|
||||
max-height: 80vh;
|
||||
height: calc(100vh - 108px);
|
||||
max-height: calc(100vh - 108px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
taskana-monitor-tasks, taskana-monitor-workbaskets, taskana-monitor-classification-tasks {
|
||||
&> .panel {
|
||||
taskana-monitor-tasks, taskana-monitor-workbaskets, taskana-monitor-classification-tasks, taskana-access-items-management {
|
||||
& .panel {
|
||||
&> .panel-heading {
|
||||
border-left: 1px solid #ddd;
|
||||
border-right: 1px solid #ddd;
|
||||
|
@ -336,3 +344,11 @@ li.list-group-item:hover, {
|
|||
.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn.rounded {
|
||||
border-radius: 50%;
|
||||
background-color: transparent;
|
||||
&:focus, &:active:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
|
||||
typeahead-container >ul.dropdown-menu{
|
||||
width: 215px;
|
||||
max-width: 600px;
|
||||
& >li.active {
|
||||
&>a {
|
||||
background-color: $green;
|
||||
background-color: $blue;
|
||||
}
|
||||
&>a:hover {
|
||||
background-color: $green;
|
||||
background-color: $blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,2 +1,10 @@
|
|||
@import '_colors';
|
||||
$icon-font-path: '../../node_modules/bootstrap-sass/assets/fonts/bootstrap/';
|
||||
|
||||
@mixin degraded-bar ($direction, $width, $height) {
|
||||
display: block;
|
||||
width: $width;
|
||||
height: $height;
|
||||
background-image: linear-gradient(to $direction, $pallete-blue 30%, $pallete-green 50%);
|
||||
content: ' ';
|
||||
}
|
Loading…
Reference in New Issue