mirror of https://github.com/apache/archiva.git
Components for new angular app
This commit is contained in:
parent
0e2187bf0e
commit
ec828c8745
|
@ -43,6 +43,8 @@ import { ManageUsersListComponent } from './modules/user/users/manage-users-list
|
|||
import { ManageUsersAddComponent } from './modules/user/users/manage-users-add/manage-users-add.component';
|
||||
import { NgbPaginationModule, NgbTooltipModule} from "@ng-bootstrap/ng-bootstrap";
|
||||
import { PaginatedEntitiesComponent } from './modules/general/paginated-entities/paginated-entities.component';
|
||||
import { SortedTableHeaderComponent } from './modules/general/sorted-table-header/sorted-table-header.component';
|
||||
import { SortedTableHeaderRowComponent } from './modules/general/sorted-table-header-row/sorted-table-header-row.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
|
@ -65,6 +67,8 @@ import { PaginatedEntitiesComponent } from './modules/general/paginated-entities
|
|||
ManageUsersListComponent,
|
||||
ManageUsersAddComponent,
|
||||
PaginatedEntitiesComponent,
|
||||
SortedTableHeaderComponent,
|
||||
SortedTableHeaderRowComponent,
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
|
|
|
@ -24,5 +24,5 @@ import {Observable} from "rxjs";
|
|||
* @typeparam T The type of the entity that is returned from the service
|
||||
*/
|
||||
export interface EntityService<T> {
|
||||
(searchTerm:string,offset:number,limit:number,orderBy:string,order:string):Observable<PagedResult<T>>
|
||||
(searchTerm:string,offset:number,limit:number,orderBy:string[],order:string):Observable<PagedResult<T>>
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export interface FieldToggle {
|
||||
toggleField(fieldName: string[]);
|
||||
}
|
|
@ -16,12 +16,11 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import {Component, OnInit, Input, Output, EventEmitter} from '@angular/core';
|
||||
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {merge, Observable, Subject} from "rxjs";
|
||||
import {UserInfo} from "../../../model/user-info";
|
||||
import {TranslateService} from "@ngx-translate/core";
|
||||
import {debounceTime, distinctUntilChanged, map, mergeMap, pluck, share, startWith} from "rxjs/operators";
|
||||
import {EntityService} from "../../../model/entity-service";
|
||||
import {FieldToggle} from "../../../model/field-toggle";
|
||||
|
||||
|
||||
/**
|
||||
|
@ -44,95 +43,154 @@ import {EntityService} from "../../../model/entity-service";
|
|||
* @typeparam T The type of the retrieved entity elements.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'app-paginated-entities',
|
||||
templateUrl: './paginated-entities.component.html',
|
||||
styleUrls: ['./paginated-entities.component.scss']
|
||||
selector: 'app-paginated-entities',
|
||||
templateUrl: './paginated-entities.component.html',
|
||||
styleUrls: ['./paginated-entities.component.scss']
|
||||
})
|
||||
export class PaginatedEntitiesComponent<T> implements OnInit {
|
||||
export class PaginatedEntitiesComponent<T> implements OnInit, FieldToggle {
|
||||
|
||||
/**
|
||||
* This must be set, if you use the component. This service retrieves the entity data.
|
||||
*/
|
||||
@Input() service : EntityService<T>;
|
||||
/**
|
||||
* This must be set, if you use the component. This service retrieves the entity data.
|
||||
*/
|
||||
@Input() service: EntityService<T>;
|
||||
|
||||
/**
|
||||
* The number of elements per page retrieved
|
||||
*/
|
||||
@Input() pageSize = 10;
|
||||
/**
|
||||
* The number of elements per page retrieved
|
||||
*/
|
||||
@Input() pageSize = 10;
|
||||
|
||||
/**
|
||||
* Pagination controls
|
||||
*/
|
||||
@Input() pagination = {
|
||||
maxSize:5,
|
||||
rotate:true,
|
||||
boundaryLinks:true,
|
||||
ellipses:false
|
||||
}
|
||||
/**
|
||||
* Two-Way-Binding attribute for sorting field
|
||||
*/
|
||||
@Input() sortField = [];
|
||||
/**
|
||||
* Two-Way Binding attribute for sort order
|
||||
*/
|
||||
@Input() sortOrder = "asc";
|
||||
|
||||
/**
|
||||
* The current page that is selected
|
||||
*/
|
||||
page = 1;
|
||||
/**
|
||||
* The current search term entered in the search field
|
||||
*/
|
||||
searchTerm: string;
|
||||
/**
|
||||
* Pagination controls
|
||||
*/
|
||||
@Input() pagination = {
|
||||
maxSize: 5,
|
||||
rotate: true,
|
||||
boundaryLinks: true,
|
||||
ellipses: false
|
||||
}
|
||||
|
||||
/**
|
||||
* Event thrown, if the page value changes
|
||||
*/
|
||||
@Output() pageEvent : EventEmitter<number> = new EventEmitter<number>();
|
||||
/**
|
||||
* Event thrown, if the search term changes
|
||||
*/
|
||||
@Output() searchTermEvent: EventEmitter<string> = new EventEmitter<string>();
|
||||
/**
|
||||
* The current page that is selected
|
||||
*/
|
||||
page = 1;
|
||||
/**
|
||||
* The current search term entered in the search field
|
||||
*/
|
||||
searchTerm: string;
|
||||
|
||||
/**
|
||||
* The total number of elements available for the given search term
|
||||
*/
|
||||
total$: Observable<number>;
|
||||
/**
|
||||
* The entity items retrieved from the service
|
||||
*/
|
||||
items$: Observable<T[]>;
|
||||
/**
|
||||
* Event thrown, if the page value changes
|
||||
*/
|
||||
@Output() pageChange: EventEmitter<number> = new EventEmitter<number>();
|
||||
/**
|
||||
* Event thrown, if the search term changes
|
||||
*/
|
||||
@Output() searchTermChange: EventEmitter<string> = new EventEmitter<string>();
|
||||
|
||||
private pageStream: Subject<number> = new Subject<number>();
|
||||
private searchTermStream: Subject<string> = new Subject<string>();
|
||||
@Output() sortFieldChange: EventEmitter<string[]> = new EventEmitter<string[]>();
|
||||
|
||||
constructor() { }
|
||||
@Output() sortOrderChange: EventEmitter<string> = new EventEmitter<string>();
|
||||
|
||||
ngOnInit(): void {
|
||||
// We combine the sources for the page and the search input field to a observable 'source'
|
||||
const pageSource = this.pageStream.pipe(map(pageNumber => {
|
||||
return {search: this.searchTerm, page: pageNumber}
|
||||
}));
|
||||
const searchSource = this.searchTermStream.pipe(
|
||||
debounceTime(1000),
|
||||
distinctUntilChanged(),
|
||||
map(searchTerm => {
|
||||
this.searchTerm = searchTerm;
|
||||
return {search: searchTerm, page: 1}
|
||||
/**
|
||||
* The total number of elements available for the given search term
|
||||
*/
|
||||
total$: Observable<number>;
|
||||
/**
|
||||
* The entity items retrieved from the service
|
||||
*/
|
||||
items$: Observable<T[]>;
|
||||
|
||||
private pageStream: Subject<number> = new Subject<number>();
|
||||
private searchTermStream: Subject<string> = new Subject<string>();
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
// We combine the sources for the page and the search input field to a observable 'source'
|
||||
const pageSource = this.pageStream.pipe(map(pageNumber => {
|
||||
return {search: this.searchTerm, page: pageNumber}
|
||||
}));
|
||||
const source = merge(pageSource, searchSource).pipe(
|
||||
startWith({search: this.searchTerm, page: this.page}),
|
||||
mergeMap((params: { search: string, page: number }) => {
|
||||
return this.service(params.search, (params.page - 1) * this.pageSize, this.pageSize, "", "asc");
|
||||
}),share());
|
||||
this.total$ = source.pipe(pluck('pagination','totalCount'));
|
||||
this.items$ = source.pipe(pluck('data'));
|
||||
}
|
||||
const searchSource = this.searchTermStream.pipe(
|
||||
debounceTime(1000),
|
||||
distinctUntilChanged(),
|
||||
map(searchTerm => {
|
||||
this.searchTerm = searchTerm;
|
||||
return {search: searchTerm, page: 1}
|
||||
}));
|
||||
const source = merge(pageSource, searchSource).pipe(
|
||||
startWith({search: this.searchTerm, page: this.page}),
|
||||
mergeMap((params: { search: string, page: number }) => {
|
||||
return this.service(params.search, (params.page - 1) * this.pageSize, this.pageSize, this.sortField, this.sortOrder);
|
||||
}), share());
|
||||
this.total$ = source.pipe(pluck('pagination', 'totalCount'));
|
||||
this.items$ = source.pipe(pluck('data'));
|
||||
}
|
||||
|
||||
search(terms: string) {
|
||||
// console.log("Keystroke " + terms);
|
||||
this.searchTermEvent.emit(terms);
|
||||
this.searchTermStream.next(terms)
|
||||
}
|
||||
search(terms: string) {
|
||||
// console.log("Keystroke " + terms);
|
||||
this.searchTermChange.emit(terms);
|
||||
this.searchTermStream.next(terms)
|
||||
}
|
||||
|
||||
changePage(pageNumber : number) {
|
||||
// console.log("Page change " +pageNumber);
|
||||
this.pageEvent.emit(pageNumber);
|
||||
this.pageStream.next(pageNumber);
|
||||
}
|
||||
changePage(pageNumber: number) {
|
||||
// console.log("Page change " +pageNumber);
|
||||
this.pageChange.emit(pageNumber);
|
||||
this.pageStream.next(pageNumber);
|
||||
}
|
||||
|
||||
private compareArrays(a1: string[], a2: string[]) {
|
||||
let i = a1.length;
|
||||
while (i--) {
|
||||
if (a1[i] !== a2[i]) return false;
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
toggleSortField(fieldName: string) {
|
||||
this.toggleField([fieldName]);
|
||||
}
|
||||
|
||||
toggleField(fieldArray: string[]) {
|
||||
console.log("Changing sort field " + fieldArray);
|
||||
let sortOrderChanged: boolean = false;
|
||||
let sortFieldChanged: boolean = false;
|
||||
if (!this.compareArrays(this.sortField, fieldArray)) {
|
||||
console.log("Fields differ: " + this.sortField + " - " + fieldArray);
|
||||
this.sortField = fieldArray;
|
||||
if (this.sortOrder != 'asc') {
|
||||
this.sortOrder = 'asc';
|
||||
sortOrderChanged = true;
|
||||
}
|
||||
sortFieldChanged = true;
|
||||
} else {
|
||||
if (this.sortOrder == "asc") {
|
||||
this.sortOrder = "desc";
|
||||
} else {
|
||||
this.sortOrder = "asc";
|
||||
}
|
||||
console.log("Toggled sort order: " + this.sortOrder);
|
||||
sortOrderChanged = true;
|
||||
}
|
||||
if (sortOrderChanged) {
|
||||
console.log("Sort order changed: "+this.sortOrder)
|
||||
this.sortOrderChange.emit(this.sortOrder);
|
||||
}
|
||||
if (sortFieldChanged) {
|
||||
this.sortFieldChange.emit(this.sortField);
|
||||
}
|
||||
if (sortFieldChanged || sortOrderChanged) {
|
||||
this.changePage(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one
|
||||
~ or more contributor license agreements. See the NOTICE file
|
||||
~ distributed with this work for additional information
|
||||
~ regarding copyright ownership. The ASF licenses this file
|
||||
~ to you under the Apache License, Version 2.0 (the
|
||||
~ "License"); you may not use this file except in compliance
|
||||
~ with the License. You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
|
||||
<ng-content ></ng-content>
|
|
@ -0,0 +1,18 @@
|
|||
/*!
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SortedTableHeaderRowComponent } from './sorted-table-header-row.component';
|
||||
|
||||
describe('SortedTableHeaderRowComponent', () => {
|
||||
let component: SortedTableHeaderRowComponent;
|
||||
let fixture: ComponentFixture<SortedTableHeaderRowComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ SortedTableHeaderRowComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SortedTableHeaderRowComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
AfterViewChecked, AfterViewInit,
|
||||
Component,
|
||||
Input,
|
||||
OnInit,
|
||||
QueryList,
|
||||
TemplateRef,
|
||||
ViewChild,
|
||||
ViewChildren,
|
||||
ViewContainerRef,
|
||||
ContentChildren, AfterContentInit, AfterContentChecked, ChangeDetectorRef, Output, EventEmitter
|
||||
} from '@angular/core';
|
||||
import {FieldToggle} from "../../../model/field-toggle";
|
||||
import {SortedTableHeaderComponent} from "../sorted-table-header/sorted-table-header.component";
|
||||
import { delay, startWith } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'tr[sorted]',
|
||||
templateUrl: './sorted-table-header-row.component.html',
|
||||
styleUrls: ['./sorted-table-header-row.component.scss']
|
||||
})
|
||||
export class SortedTableHeaderRowComponent implements OnInit, AfterViewInit, AfterContentInit, AfterContentChecked {
|
||||
|
||||
@Input() sortFieldEmitter: EventEmitter<string[]>;
|
||||
@Input() sortOrderEmitter: EventEmitter<string>;
|
||||
@Input() sortFields: string[];
|
||||
@Input() sortOrder: string;
|
||||
@Input() toggleObserver: FieldToggle;
|
||||
|
||||
@ContentChildren(SortedTableHeaderComponent, { descendants: true }) contentChilds: QueryList<SortedTableHeaderComponent>;
|
||||
|
||||
constructor(private readonly viewContainer: ViewContainerRef) {
|
||||
}
|
||||
|
||||
ngAfterContentChecked(): void {
|
||||
|
||||
|
||||
}
|
||||
|
||||
ngAfterContentInit(): void {
|
||||
this.contentChilds.changes.pipe(startWith(this.contentChilds), delay(0)).subscribe(() => {
|
||||
this.contentChilds.forEach((colComponent, index) => {
|
||||
console.log("Children " + colComponent);
|
||||
colComponent.registerSortFieldEmitter(this.sortFieldEmitter);
|
||||
colComponent.registerSortOrderEmitter(this.sortOrderEmitter);
|
||||
colComponent.sortOrder = this.sortOrder;
|
||||
colComponent.currentFieldArray = this.sortFields;
|
||||
colComponent.toggleObserver = this.toggleObserver;
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<!--
|
||||
~ Licensed to the Apache Software Foundation (ASF) under one
|
||||
~ or more contributor license agreements. See the NOTICE file
|
||||
~ distributed with this work for additional information
|
||||
~ regarding copyright ownership. The ASF licenses this file
|
||||
~ to you under the Apache License, Version 2.0 (the
|
||||
~ "License"); you may not use this file except in compliance
|
||||
~ with the License. You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
|
||||
<ng-template #content>
|
||||
<th scope="col" (click)="toggleSortField()">
|
||||
<ng-container *ngIf="contentText!=null && contentText!=''" >{{contentText | translate}}</ng-container>
|
||||
<ng-content></ng-content>
|
||||
<span *ngIf="sortCheck()" class="fas" [ngClass]="isAscending()?'fa-sort-alpha-up':'fa-sort-alpha-down'"></span></th>
|
||||
</ng-template>
|
|
@ -0,0 +1,18 @@
|
|||
/*!
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SortedTableHeaderComponent } from './sorted-table-header.component';
|
||||
|
||||
describe('SortedTableHeaderComponent', () => {
|
||||
let component: SortedTableHeaderComponent;
|
||||
let fixture: ComponentFixture<SortedTableHeaderComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ SortedTableHeaderComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SortedTableHeaderComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
Input,
|
||||
ViewContainerRef,
|
||||
ViewChild,
|
||||
TemplateRef,
|
||||
ChangeDetectorRef,
|
||||
AfterViewChecked, EventEmitter, Output
|
||||
} from '@angular/core';
|
||||
import {FieldToggle} from "../../../model/field-toggle";
|
||||
import { ChangeDetectionStrategy } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
host: { style: 'display:none' },
|
||||
selector: 'app-th-sorted',
|
||||
templateUrl: './sorted-table-header.component.html',
|
||||
styleUrls: ['./sorted-table-header.component.scss']
|
||||
})
|
||||
export class SortedTableHeaderComponent implements OnInit, AfterViewChecked {
|
||||
|
||||
@Input() fieldArray: string[];
|
||||
currentFieldArray: string[];
|
||||
sortOrder: string;
|
||||
toggleObserver: FieldToggle;
|
||||
@Input() contentText:string;
|
||||
|
||||
@ViewChild('content', { static: true }) content: TemplateRef<{}>;
|
||||
|
||||
|
||||
constructor(private readonly viewContainer: ViewContainerRef) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.viewContainer.createEmbeddedView(this.content);
|
||||
}
|
||||
ngAfterViewChecked() {
|
||||
}
|
||||
|
||||
toggleSortField() {
|
||||
console.log("Toggling sort field " + this.fieldArray);
|
||||
this.toggleObserver.toggleField(this.fieldArray);
|
||||
}
|
||||
|
||||
private compareArrays(a1: string[], a2: string[]) {
|
||||
if (a1==null || a2==null) {
|
||||
return false;
|
||||
}
|
||||
let i = a1.length;
|
||||
while (i--) {
|
||||
if (a1[i] !== a2[i]) return false;
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
sortCheck() {
|
||||
return this.compareArrays(this.fieldArray, this.currentFieldArray);
|
||||
}
|
||||
|
||||
isAscending() :boolean {
|
||||
console.log("Is ascending: " + this.sortOrder);
|
||||
return this.sortOrder == 'asc';
|
||||
}
|
||||
|
||||
registerSortOrderEmitter(emitter : EventEmitter<string>) {
|
||||
emitter.subscribe((field) => this.sortOrder = field);
|
||||
}
|
||||
|
||||
registerSortFieldEmitter(emitter : EventEmitter<string[]>) {
|
||||
emitter.subscribe((field) => this.currentFieldArray = field);
|
||||
}
|
||||
|
||||
}
|
|
@ -17,24 +17,28 @@
|
|||
~ under the License.
|
||||
-->
|
||||
|
||||
<app-paginated-entities [service]="service" pageSize="5"We #parent>
|
||||
<app-paginated-entities [service]="service" pageSize="5" [(sortField)]="sortField" [(sortOrder)]="sortOrder"
|
||||
#parent>
|
||||
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th scope="col">{{'users.list.table.head.user_id' | translate}}</th>
|
||||
<th scope="col">{{'users.list.table.head.fullName' | translate}}</th>
|
||||
<th scope="col">{{'users.list.table.head.email' | translate}}</th>
|
||||
<th scope="col"><span class="fas fa-check" placement="top"
|
||||
[ngbTooltip]="heads.validated" [attr.aria-label]="heads.validated"></span>
|
||||
</th>
|
||||
<tr sorted [sortFieldEmitter]="parent.sortFieldChange" [sortOrder]="sortOrder" [sortFields]="sortField"
|
||||
[sortOrderEmitter]="parent.sortOrderChange" [toggleObserver]="parent" >
|
||||
<app-th-sorted [fieldArray]="['user_id']" contentText="users.list.table.head.user_id"></app-th-sorted>
|
||||
<app-th-sorted contentText="users.list.table.head.fullName" [fieldArray]="['fullName']" ></app-th-sorted>
|
||||
<app-th-sorted contentText="users.list.table.head.email" [fieldArray]="['email']"></app-th-sorted>
|
||||
<app-th-sorted [fieldArray]="['validated','user_id']">
|
||||
<span class="fas fa-check" placement="top"
|
||||
[ngbTooltip]="heads.validated" [attr.aria-label]="heads.validated">
|
||||
</span>
|
||||
</app-th-sorted>
|
||||
<th scope="col"><span class="fas fa-lock" placement="top"
|
||||
[ngbTooltip]="heads.locked" [attr.aria-label]="heads.locked"></span></th>
|
||||
<th scope="col"><span class="fa fa-chevron-circle-right" placement="top"
|
||||
[ngbTooltip]="heads.pwchange" [attr.aria-label]="heads.pwchange"></span>
|
||||
</th>
|
||||
<th scope="col">{{'users.list.table.head.lastLogin' | translate}}</th>
|
||||
<th scope="col">{{'users.list.table.head.created' | translate}}</th>
|
||||
<app-th-sorted contentText="users.list.table.head.created" [fieldArray]="['created']" ></app-th-sorted>
|
||||
<th scope="col">{{'users.list.table.head.lastPwChange' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
|
@ -25,7 +25,6 @@ import {EntityService} from "../../../../model/entity-service";
|
|||
import {Observable, of} from "rxjs";
|
||||
import {PagedResult} from "../../../../model/paged-result";
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-manage-users-list',
|
||||
templateUrl: './manage-users-list.component.html',
|
||||
|
@ -35,10 +34,13 @@ export class ManageUsersListComponent implements OnInit {
|
|||
|
||||
@Input() heads: any;
|
||||
service : EntityService<UserInfo>;
|
||||
sortField = ["user_id"];
|
||||
sortOrder = "asc";
|
||||
|
||||
|
||||
constructor(private translator: TranslateService, private userService : UserService) {
|
||||
this.service = function (searchTerm: string, offset: number, limit: number, orderBy: string, order: string) : Observable<PagedResult<UserInfo>> {
|
||||
this.service = function (searchTerm: string, offset: number, limit: number, orderBy: string[], order: string) : Observable<PagedResult<UserInfo>> {
|
||||
console.log("Retrieving data " + searchTerm + "," + offset + "," + limit + "," + orderBy + "," + order);
|
||||
return userService.query(searchTerm, offset, limit, orderBy, order);
|
||||
}
|
||||
|
||||
|
@ -53,9 +55,29 @@ export class ManageUsersListComponent implements OnInit {
|
|||
this.heads[suffix] = this.translator.instant('users.list.table.head.' + suffix);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
changeSortOrder(order:string) {
|
||||
if (this.sortOrder!=order) {
|
||||
this.sortOrder = order;
|
||||
}
|
||||
}
|
||||
|
||||
private compareArrays(a1: string[], a2: string[]) {
|
||||
let i = a1.length;
|
||||
while (i--) {
|
||||
if (a1[i] !== a2[i]) return false;
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
sortCheck(fieldArray:string[]) {
|
||||
return this.compareArrays(this.sortField, fieldArray);
|
||||
}
|
||||
|
||||
isAscending() : boolean {
|
||||
return this.sortOrder == "asc";
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -258,12 +258,15 @@ export class UserService implements OnInit, OnDestroy {
|
|||
this.authenticated = false;
|
||||
}
|
||||
|
||||
public query(searchTerm : string, offset : number = 0, limit : number = 10, orderBy : string = 'user_id', order: string = 'asc') : Observable<PagedResult<UserInfo>> {
|
||||
public query(searchTerm : string, offset : number = 0, limit : number = 10, orderBy : string[] = ['user_id'], order: string = 'asc') : Observable<PagedResult<UserInfo>> {
|
||||
console.log("getUserList " + searchTerm + "," + offset + "," + limit + "," + orderBy + "," + order);
|
||||
if (searchTerm==null) {
|
||||
searchTerm=""
|
||||
}
|
||||
return this.rest.executeRestCall<PagedResult<UserInfo>>("get", "redback", "users", {'q':searchTerm, 'offset':offset,'limit':limit});
|
||||
if (orderBy==null || orderBy.length==0) {
|
||||
orderBy = ['user_id'];
|
||||
}
|
||||
return this.rest.executeRestCall<PagedResult<UserInfo>>("get", "redback", "users", {'q':searchTerm, 'offset':offset,'limit':limit,'orderBy':orderBy,'order':order});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue