Browse Source

Components for new angular app

pull/61/head
Martin Stockhammer 3 years ago
parent
commit
ec828c8745
15 changed files with 551 additions and 105 deletions
  1. 4
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app.module.ts
  2. 1
    1
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/entity-service.ts
  3. 21
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/field-toggle.ts
  4. 149
    91
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/paginated-entities/paginated-entities.component.ts
  5. 19
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sorted-table-header-row/sorted-table-header-row.component.html
  6. 18
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sorted-table-header-row/sorted-table-header-row.component.scss
  7. 43
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sorted-table-header-row/sorted-table-header-row.component.spec.ts
  8. 79
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sorted-table-header-row/sorted-table-header-row.component.ts
  9. 24
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sorted-table-header/sorted-table-header.component.html
  10. 18
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sorted-table-header/sorted-table-header.component.scss
  11. 43
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sorted-table-header/sorted-table-header.component.spec.ts
  12. 90
    0
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sorted-table-header/sorted-table-header.component.ts
  13. 13
    9
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-list/manage-users-list.component.html
  14. 24
    2
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-list/manage-users-list.component.ts
  15. 5
    2
      archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/user.service.ts

+ 4
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/app.module.ts View File

@@ -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,

+ 1
- 1
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/entity-service.ts View File

@@ -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>>
}

+ 21
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/field-toggle.ts View File

@@ -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[]);
}

+ 149
- 91
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/paginated-entities/paginated-entities.component.ts View File

@@ -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 {

/**
* 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;

/**
* Pagination controls
*/
@Input() pagination = {
maxSize:5,
rotate:true,
boundaryLinks:true,
ellipses:false
}

/**
* The current page that is selected
*/
page = 1;
/**
* The current search term entered in the search field
*/
searchTerm: string;

/**
* 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 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 searchSource = this.searchTermStream.pipe(
debounceTime(1000),
distinctUntilChanged(),
map(searchTerm => {
this.searchTerm = searchTerm;
return {search: searchTerm, page: 1}
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>;

/**
* The number of elements per page retrieved
*/
@Input() pageSize = 10;

/**
* Two-Way-Binding attribute for sorting field
*/
@Input() sortField = [];
/**
* Two-Way Binding attribute for sort order
*/
@Input() sortOrder = "asc";

/**
* Pagination controls
*/
@Input() pagination = {
maxSize: 5,
rotate: true,
boundaryLinks: true,
ellipses: false
}

/**
* The current page that is selected
*/
page = 1;
/**
* The current search term entered in the search field
*/
searchTerm: string;

/**
* 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>();

@Output() sortFieldChange: EventEmitter<string[]> = new EventEmitter<string[]>();

@Output() sortOrderChange: EventEmitter<string> = new EventEmitter<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[]>;

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'));
}

search(terms: string) {
// console.log("Keystroke " + terms);
this.searchTermEvent.emit(terms);
this.searchTermStream.next(terms)
}

changePage(pageNumber : number) {
// console.log("Page change " +pageNumber);
this.pageEvent.emit(pageNumber);
this.pageStream.next(pageNumber);
}
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.searchTermChange.emit(terms);
this.searchTermStream.next(terms)
}

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);
}
}

}

+ 19
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sorted-table-header-row/sorted-table-header-row.component.html View File

@@ -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>

+ 18
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sorted-table-header-row/sorted-table-header-row.component.scss View File

@@ -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.
*/


+ 43
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sorted-table-header-row/sorted-table-header-row.component.spec.ts View File

@@ -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();
});
});

+ 79
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sorted-table-header-row/sorted-table-header-row.component.ts View File

@@ -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 {

}

}

+ 24
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sorted-table-header/sorted-table-header.component.html View File

@@ -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>

+ 18
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sorted-table-header/sorted-table-header.component.scss View File

@@ -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.
*/


+ 43
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sorted-table-header/sorted-table-header.component.spec.ts View File

@@ -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();
});
});

+ 90
- 0
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/general/sorted-table-header/sorted-table-header.component.ts View File

@@ -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);
}

}

+ 13
- 9
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-list/manage-users-list.component.html View File

@@ -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>

+ 24
- 2
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/user/users/manage-users-list/manage-users-list.component.ts View File

@@ -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";
}



+ 5
- 2
archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/services/user.service.ts View File

@@ -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…
Cancel
Save