Revize 02818aaf
Přidáno uživatelem Ondřej Váně před téměř 5 roky(ů)
be/fulltextsearch/src/main/java/cz/zcu/kiv/aswi/fulltextsearch/IndexController.java | ||
---|---|---|
13 | 13 |
import javax.xml.bind.JAXBException; |
14 | 14 |
import java.io.IOException; |
15 | 15 |
import java.util.ArrayList; |
16 |
import java.util.Date; |
|
16 | 17 |
import java.util.List; |
17 | 18 |
|
18 | 19 |
@CrossOrigin(origins = "*", allowedHeaders = "*") |
... | ... | |
61 | 62 |
List<String> filenames = solrService.listAllFiles(); |
62 | 63 |
int id = 0; // todo |
63 | 64 |
for (String filename: filenames) { |
64 |
response.add(new DocumentResponse(filename, id++)); |
|
65 |
response.add(new DocumentResponse(filename, id++, new Date(), new Date()));
|
|
65 | 66 |
} |
66 | 67 |
} catch (IOException e) { |
67 | 68 |
// todo |
be/fulltextsearch/src/main/java/cz/zcu/kiv/aswi/fulltextsearch/model/DocumentResponse.java | ||
---|---|---|
1 | 1 |
package cz.zcu.kiv.aswi.fulltextsearch.model; |
2 | 2 |
|
3 |
import java.util.Date; |
|
4 |
|
|
3 | 5 |
public class DocumentResponse { |
4 | 6 |
|
5 | 7 |
private String documentName; |
6 | 8 |
private int id; |
9 |
private Date originDate; |
|
10 |
private Date uploadedDate; |
|
7 | 11 |
|
8 |
public DocumentResponse(String documentName, int id) { |
|
12 |
public DocumentResponse(String documentName, int id, Date originDate, Date uploadedDate) {
|
|
9 | 13 |
this.documentName = documentName; |
10 | 14 |
this.id = id; |
15 |
this.originDate = originDate; |
|
16 |
this.uploadedDate = uploadedDate; |
|
11 | 17 |
} |
12 | 18 |
|
13 | 19 |
public String getDocumentName() { |
14 | 20 |
return documentName; |
15 | 21 |
} |
16 | 22 |
|
17 |
public void setDocumentName(String documentName, int id) {
|
|
23 |
public void setDocumentName(String documentName) { |
|
18 | 24 |
this.documentName = documentName; |
19 | 25 |
} |
20 | 26 |
|
... | ... | |
25 | 31 |
public void setId(int id) { |
26 | 32 |
this.id = id; |
27 | 33 |
} |
34 |
|
|
35 |
public Date getOriginDate() { |
|
36 |
return originDate; |
|
37 |
} |
|
38 |
|
|
39 |
public void setOriginDate(Date originDate) { |
|
40 |
this.originDate = originDate; |
|
41 |
} |
|
42 |
|
|
43 |
public Date getUploadedDate() { |
|
44 |
return uploadedDate; |
|
45 |
} |
|
46 |
|
|
47 |
public void setUploadedDate(Date uploadedDate) { |
|
48 |
this.uploadedDate = uploadedDate; |
|
49 |
} |
|
28 | 50 |
} |
fe/fulltextsearch/src/app/app.module.ts | ||
---|---|---|
18 | 18 |
import { MatSelectModule } from '@angular/material/select'; |
19 | 19 |
import { SearchBoxComponent } from './components/shared-components/search-box/search-box.component'; |
20 | 20 |
import { MatProgressBarModule } from '@angular/material/progress-bar'; |
21 |
import { TableComponent } from './components/pages/browse/table/table.component'; |
|
22 |
import { MatTableModule } from '@angular/material/table'; |
|
23 |
import { MatPaginatorModule } from '@angular/material/paginator'; |
|
24 |
import { MatSortModule } from '@angular/material/sort'; |
|
21 | 25 |
|
22 | 26 |
@NgModule({ |
23 | 27 |
declarations: [ |
... | ... | |
28 | 32 |
BrowseComponent, |
29 | 33 |
UploadComponent, |
30 | 34 |
HelpComponent, |
31 |
SearchBoxComponent |
|
35 |
SearchBoxComponent, |
|
36 |
TableComponent |
|
32 | 37 |
], |
33 | 38 |
imports: [ |
34 | 39 |
BrowserModule, |
... | ... | |
40 | 45 |
MatButtonModule, |
41 | 46 |
MatIconModule, |
42 | 47 |
MatSelectModule, |
43 |
MatProgressBarModule |
|
48 |
MatProgressBarModule, |
|
49 |
MatTableModule, |
|
50 |
MatPaginatorModule, |
|
51 |
MatSortModule |
|
44 | 52 |
], |
45 | 53 |
providers: [], |
46 | 54 |
bootstrap: [AppComponent] |
fe/fulltextsearch/src/app/components/pages/browse/browse.component.css | ||
---|---|---|
1 |
h1 { |
|
2 |
font-size: xx-large; |
|
1 |
.text-box{ |
|
2 |
width: 80%; |
|
3 |
margin: 20px auto; |
|
3 | 4 |
} |
4 | 5 |
|
5 |
.text-box { |
|
6 |
margin: auto; |
|
7 |
width: 80%; |
|
8 |
padding: 10px; |
|
6 |
.card-header { |
|
7 |
margin-bottom: 0; |
|
9 | 8 |
} |
fe/fulltextsearch/src/app/components/pages/browse/browse.component.html | ||
---|---|---|
1 |
<div class="text-box"> |
|
1 |
<div class="text-box mat-elevation-z8">
|
|
2 | 2 |
<div class="card"> |
3 | 3 |
<h1 class="card-header">All documents</h1> |
4 |
<div class="card-body"> |
|
5 |
<ul class="list-group"> |
|
6 |
<li class="list-group-item" *ngFor="let documentResponse of documents"> |
|
7 |
<b>Id: </b>{{documentResponse.id}} |
|
8 |
<b>Document name: </b>{{documentResponse.documentName}} |
|
9 |
</li> |
|
10 |
</ul> |
|
11 |
</div> |
|
4 |
<div> |
|
5 |
<app-table-browse></app-table-browse> |
|
6 |
</div> |
|
12 | 7 |
</div> |
13 | 8 |
</div> |
9 |
|
fe/fulltextsearch/src/app/components/pages/browse/table/table-datasource.ts | ||
---|---|---|
1 |
import {DataSource} from '@angular/cdk/collections'; |
|
2 |
import {MatPaginator} from '@angular/material/paginator'; |
|
3 |
import {MatSort} from '@angular/material/sort'; |
|
4 |
import {map} from 'rxjs/operators'; |
|
5 |
import {merge, Observable, of as observableOf} from 'rxjs'; |
|
6 |
import {DocumentResponse} from '../../../../model/DocumentResponse'; |
|
7 |
|
|
8 |
/** |
|
9 |
* Data source for the Table view. This class should |
|
10 |
* encapsulate all logic for fetching and manipulating the displayed data |
|
11 |
* (including sorting, pagination, and filtering). |
|
12 |
*/ |
|
13 |
export class TableDataSource extends DataSource<DocumentResponse> { |
|
14 |
data: DocumentResponse[]; |
|
15 |
paginator: MatPaginator; |
|
16 |
sort: MatSort; |
|
17 |
|
|
18 |
constructor() { |
|
19 |
super(); |
|
20 |
} |
|
21 |
|
|
22 |
/** |
|
23 |
* Connect this data source to the table. The table will only update when |
|
24 |
* the returned stream emits new items. |
|
25 |
* @returns A stream of the items to be rendered. |
|
26 |
*/ |
|
27 |
connect(): Observable<DocumentResponse[]> { |
|
28 |
// Combine everything that affects the rendered data into one update |
|
29 |
// stream for the data-table to consume. |
|
30 |
const dataMutations = [ |
|
31 |
observableOf(this.data), |
|
32 |
this.paginator.page, |
|
33 |
this.sort.sortChange |
|
34 |
]; |
|
35 |
return merge(...dataMutations).pipe(map(() => { |
|
36 |
return this.getPagedData(this.getSortedData([...this.data])); |
|
37 |
})); |
|
38 |
} |
|
39 |
|
|
40 |
/** |
|
41 |
* Called when the table is being destroyed. Use this function, to clean up |
|
42 |
* any open connections or free any held resources that were set up during connect. |
|
43 |
*/ |
|
44 |
disconnect() {} |
|
45 |
|
|
46 |
/** |
|
47 |
* Paginate the data (client-side). If you're using server-side pagination, |
|
48 |
* this would be replaced by requesting the appropriate data from the server. |
|
49 |
*/ |
|
50 |
private getPagedData(data: DocumentResponse[]) { |
|
51 |
const startIndex = this.paginator.pageIndex * this.paginator.pageSize; |
|
52 |
return data.splice(startIndex, this.paginator.pageSize); |
|
53 |
} |
|
54 |
|
|
55 |
/** |
|
56 |
* Sort the data (client-side). If you're using server-side sorting, |
|
57 |
* this would be replaced by requesting the appropriate data from the server. |
|
58 |
*/ |
|
59 |
private getSortedData(data: DocumentResponse[]) { |
|
60 |
if (!this.sort.active || this.sort.direction === '') { |
|
61 |
return data; |
|
62 |
} |
|
63 |
|
|
64 |
return data.sort((a, b) => { |
|
65 |
const isAsc = this.sort.direction === 'asc'; |
|
66 |
switch (this.sort.active) { |
|
67 |
case 'name': return compare(a.documentName, b.documentName, isAsc); |
|
68 |
case 'id': return compare(+a.id, +b.id, isAsc); |
|
69 |
default: return 0; |
|
70 |
} |
|
71 |
}); |
|
72 |
} |
|
73 |
} |
|
74 |
|
|
75 |
/** Simple sort comparator for example ID/Name columns (for client-side sorting). */ |
|
76 |
function compare(a: string | number, b: string | number, isAsc: boolean) { |
|
77 |
return (a < b ? -1 : 1) * (isAsc ? 1 : -1); |
|
78 |
} |
fe/fulltextsearch/src/app/components/pages/browse/table/table.component.css | ||
---|---|---|
1 |
.full-width-table { |
|
2 |
width: 100%; |
|
3 |
} |
fe/fulltextsearch/src/app/components/pages/browse/table/table.component.html | ||
---|---|---|
1 |
<div> |
|
2 |
<table mat-table class="full-width-table" matSort aria-label="Elements"> |
|
3 |
<!-- Id Column --> |
|
4 |
<ng-container matColumnDef="id"> |
|
5 |
<th mat-header-cell *matHeaderCellDef mat-sort-header>Id</th> |
|
6 |
<td mat-cell *matCellDef="let row">{{row.id}}</td> |
|
7 |
</ng-container> |
|
8 |
|
|
9 |
<!-- Name Column --> |
|
10 |
<ng-container matColumnDef="documentName"> |
|
11 |
<th mat-header-cell *matHeaderCellDef mat-sort-header>Document name</th> |
|
12 |
<td mat-cell *matCellDef="let row">{{row.documentName}}</td> |
|
13 |
</ng-container> |
|
14 |
|
|
15 |
<!-- Test Column --> |
|
16 |
<ng-container matColumnDef="originDate"> |
|
17 |
<th mat-header-cell *matHeaderCellDef mat-sort-header>Origin date</th> |
|
18 |
<td mat-cell *matCellDef="let row">{{row.originDate | date:'d. M. yyyy'}}</td> |
|
19 |
</ng-container> |
|
20 |
|
|
21 |
<!-- Test Column --> |
|
22 |
<ng-container matColumnDef="uploadedDate"> |
|
23 |
<th mat-header-cell *matHeaderCellDef mat-sort-header>Uploaded date</th> |
|
24 |
<td mat-cell *matCellDef="let row">{{row.uploadedDate | date:'d. M. yyyy'}}</td> |
|
25 |
</ng-container> |
|
26 |
|
|
27 |
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> |
|
28 |
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> |
|
29 |
</table> |
|
30 |
|
|
31 |
<div class="row justify-content-center align-items-center"> |
|
32 |
|
|
33 |
<mat-paginator #paginator |
|
34 |
[length]="dataSource?.data.length" |
|
35 |
[pageIndex]="0" |
|
36 |
[pageSize]="10" |
|
37 |
[pageSizeOptions]="[5, 10, 25]"> |
|
38 |
</mat-paginator> |
|
39 |
</div> |
|
40 |
|
|
41 |
</div> |
fe/fulltextsearch/src/app/components/pages/browse/table/table.component.spec.ts | ||
---|---|---|
1 |
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; |
|
2 |
import { NoopAnimationsModule } from '@angular/platform-browser/animations'; |
|
3 |
import { MatPaginatorModule } from '@angular/material/paginator'; |
|
4 |
import { MatSortModule } from '@angular/material/sort'; |
|
5 |
import { MatTableModule } from '@angular/material/table'; |
|
6 |
|
|
7 |
import { TableComponent } from './table.component'; |
|
8 |
|
|
9 |
describe('TableComponent', () => { |
|
10 |
let component: TableComponent; |
|
11 |
let fixture: ComponentFixture<TableComponent>; |
|
12 |
|
|
13 |
beforeEach(async(() => { |
|
14 |
TestBed.configureTestingModule({ |
|
15 |
declarations: [ TableComponent ], |
|
16 |
imports: [ |
|
17 |
NoopAnimationsModule, |
|
18 |
MatPaginatorModule, |
|
19 |
MatSortModule, |
|
20 |
MatTableModule, |
|
21 |
] |
|
22 |
}).compileComponents(); |
|
23 |
})); |
|
24 |
|
|
25 |
beforeEach(() => { |
|
26 |
fixture = TestBed.createComponent(TableComponent); |
|
27 |
component = fixture.componentInstance; |
|
28 |
fixture.detectChanges(); |
|
29 |
}); |
|
30 |
|
|
31 |
it('should compile', () => { |
|
32 |
expect(component).toBeTruthy(); |
|
33 |
}); |
|
34 |
}); |
fe/fulltextsearch/src/app/components/pages/browse/table/table.component.ts | ||
---|---|---|
1 |
import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core'; |
|
2 |
import { MatPaginator } from '@angular/material/paginator'; |
|
3 |
import { MatSort } from '@angular/material/sort'; |
|
4 |
import { MatTable } from '@angular/material/table'; |
|
5 |
import { TableDataSource } from './table-datasource'; |
|
6 |
import { DocumentResponse } from '../../../../model/DocumentResponse'; |
|
7 |
import {QueryService} from '../../../../services/query.service'; |
|
8 |
|
|
9 |
@Component({ |
|
10 |
selector: 'app-table-browse', |
|
11 |
templateUrl: './table.component.html', |
|
12 |
styleUrls: ['./table.component.css'] |
|
13 |
}) |
|
14 |
export class TableComponent implements AfterViewInit, OnInit { |
|
15 |
@ViewChild(MatPaginator) paginator: MatPaginator; |
|
16 |
@ViewChild(MatSort) sort: MatSort; |
|
17 |
@ViewChild(MatTable) table: MatTable<DocumentResponse>; |
|
18 |
dataSource: TableDataSource; |
|
19 |
|
|
20 |
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ |
|
21 |
displayedColumns = ['id', 'documentName', 'originDate', 'uploadedDate']; |
|
22 |
|
|
23 |
constructor( private queryService: QueryService ) { } |
|
24 |
|
|
25 |
ngOnInit() { |
|
26 |
this.queryService.getDocuments().subscribe( documents => { |
|
27 |
this.dataSource.data = documents; |
|
28 |
}); |
|
29 |
this.dataSource = new TableDataSource(); |
|
30 |
} |
|
31 |
|
|
32 |
ngAfterViewInit() { |
|
33 |
this.dataSource.sort = this.sort; |
|
34 |
this.dataSource.paginator = this.paginator; |
|
35 |
this.table.dataSource = this.dataSource; |
|
36 |
} |
|
37 |
} |
fe/fulltextsearch/src/app/model/DocumentResponse.ts | ||
---|---|---|
1 | 1 |
export class DocumentResponse { |
2 | 2 |
public id: number; |
3 |
documentName: string; |
|
3 |
public documentName: string; |
|
4 |
public originDate: Date; |
|
5 |
public uploadedDate: Date; |
|
4 | 6 |
} |
fe/fulltextsearch/src/theme.css | ||
---|---|---|
5 | 5 |
--search-text-color: #ffffff; |
6 | 6 |
--search-background-color: #ffffff; |
7 | 7 |
--navbar-text-color: #ffffff; |
8 |
--grey-color: #DFE2E6; |
|
9 |
--black-color: #000000; |
|
8 | 10 |
} |
Také k dispozici: Unified diff
Re #7819: Úprava obrazovky browse
- upravena UI
- přidána tabulka se stránkováním
- přidány datum do modelové třídy (datum uploadu a datum původu)