Merge pull request #4785 from FinnStutzenstein/historyQuicklink
Quicklink to history (closes #4777)
This commit is contained in:
commit
b71e73fe7f
@ -112,4 +112,29 @@ export class CollectionStringMapperService {
|
|||||||
public getAllRepositories(): BaseRepository<any, any, any>[] {
|
public getAllRepositories(): BaseRepository<any, any, any>[] {
|
||||||
return Object.values(this.collectionStringMapping).map((types: CollectionStringMappedTypes) => types[2]);
|
return Object.values(this.collectionStringMapping).map((types: CollectionStringMappedTypes) => types[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the given element id. It must have the form `<collection>:<id>`, with
|
||||||
|
* <collection> being a registered collection and the id a valid integer greater then 0.
|
||||||
|
*
|
||||||
|
* @param elementId The element id.
|
||||||
|
* @returns true, if the element id is valid.
|
||||||
|
*/
|
||||||
|
public isElementIdValid(elementId: any): boolean {
|
||||||
|
if (!elementId || typeof elementId !== 'string') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const splitted = elementId.split(':');
|
||||||
|
if (splitted.length !== 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const id = parseInt(splitted[1], 10);
|
||||||
|
if (isNaN(id) || id <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.keys(this.collectionStringMapping).some(collection => collection === splitted[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,13 @@ export abstract class BaseViewModel<M extends BaseModel = any>
|
|||||||
return this._collectionString;
|
return this._collectionString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the element id of the model
|
||||||
|
*/
|
||||||
|
public get elementId(): string {
|
||||||
|
return `${this.collectionString}:${this.id}`;
|
||||||
|
}
|
||||||
|
|
||||||
public getTitle: () => string;
|
public getTitle: () => string;
|
||||||
public getListTitle: () => string;
|
public getListTitle: () => string;
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { MatSnackBar, MatTableDataSource } from '@angular/material';
|
import { MatSnackBar, MatTableDataSource } from '@angular/material';
|
||||||
import { Router } from '@angular/router';
|
import { Router, ActivatedRoute } from '@angular/router';
|
||||||
import { Title } from '@angular/platform-browser';
|
import { Title } from '@angular/platform-browser';
|
||||||
|
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
@ -21,6 +21,7 @@ import { MotionRepositoryService } from 'app/core/repositories/motions/motion-re
|
|||||||
import { BaseViewModel } from 'app/site/base/base-view-model';
|
import { BaseViewModel } from 'app/site/base/base-view-model';
|
||||||
import { Motion } from 'app/shared/models/motions/motion';
|
import { Motion } from 'app/shared/models/motions/motion';
|
||||||
import { PromptService } from 'app/core/ui-services/prompt.service';
|
import { PromptService } from 'app/core/ui-services/prompt.service';
|
||||||
|
import { CollectionStringMapperService } from 'app/core/core-services/collection-string-mapper.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list view for the history.
|
* A list view for the history.
|
||||||
@ -40,10 +41,6 @@ export class HistoryListComponent extends BaseViewComponent implements OnInit {
|
|||||||
|
|
||||||
public dataSource: MatTableDataSource<History> = new MatTableDataSource<History>();
|
public dataSource: MatTableDataSource<History> = new MatTableDataSource<History>();
|
||||||
|
|
||||||
public get isSuperAdmin(): boolean {
|
|
||||||
return this.operator.isSuperAdmin();
|
|
||||||
}
|
|
||||||
|
|
||||||
public pageSizes = [50, 100, 150, 200, 250];
|
public pageSizes = [50, 100, 150, 200, 250];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,6 +64,10 @@ export class HistoryListComponent extends BaseViewComponent implements OnInit {
|
|||||||
return this.modelSelectForm.controls.model.value;
|
return this.modelSelectForm.controls.model.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get isSuperAdmin(): boolean {
|
||||||
|
return this.operator.isSuperAdmin();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for the history list component
|
* Constructor for the history list component
|
||||||
*
|
*
|
||||||
@ -89,7 +90,9 @@ export class HistoryListComponent extends BaseViewComponent implements OnInit {
|
|||||||
private http: HttpService,
|
private http: HttpService,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private motionRepo: MotionRepositoryService,
|
private motionRepo: MotionRepositoryService,
|
||||||
private promptService: PromptService
|
private promptService: PromptService,
|
||||||
|
private activatedRoute: ActivatedRoute,
|
||||||
|
private collectionMapper: CollectionStringMapperService
|
||||||
) {
|
) {
|
||||||
super(titleService, translate, matSnackBar);
|
super(titleService, translate, matSnackBar);
|
||||||
|
|
||||||
@ -99,7 +102,15 @@ export class HistoryListComponent extends BaseViewComponent implements OnInit {
|
|||||||
this.collectionObserver = this.motionRepo.getViewModelListBehaviorSubject();
|
this.collectionObserver = this.motionRepo.getViewModelListBehaviorSubject();
|
||||||
|
|
||||||
this.modelSelectForm.controls.model.valueChanges.subscribe((id: number) => {
|
this.modelSelectForm.controls.model.valueChanges.subscribe((id: number) => {
|
||||||
this.queryElementId(this.currentCollection, id);
|
const elementId = `${this.currentCollection}:${id}`;
|
||||||
|
this.queryByElementId(elementId);
|
||||||
|
|
||||||
|
// Update the URL.
|
||||||
|
this.router.navigate([], {
|
||||||
|
relativeTo: this.activatedRoute,
|
||||||
|
queryParams: { element: elementId },
|
||||||
|
replaceUrl: true
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,6 +147,18 @@ export class HistoryListComponent extends BaseViewComponent implements OnInit {
|
|||||||
.indexOf(filter) >= 0
|
.indexOf(filter) >= 0
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// If an element id is given, validate it and update the view.
|
||||||
|
const params = this.activatedRoute.snapshot.queryParams;
|
||||||
|
if (this.collectionMapper.isElementIdValid(params.element)) {
|
||||||
|
this.queryByElementId(params.element);
|
||||||
|
this.modelSelectForm.patchValue(
|
||||||
|
{
|
||||||
|
model: parseInt(params.element.split(':')[1], 10)
|
||||||
|
},
|
||||||
|
{ emitEvent: false }
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -201,7 +224,7 @@ export class HistoryListComponent extends BaseViewComponent implements OnInit {
|
|||||||
|
|
||||||
public refresh(): void {
|
public refresh(): void {
|
||||||
if (this.currentCollection && this.currentModelId) {
|
if (this.currentCollection && this.currentModelId) {
|
||||||
this.queryElementId(this.currentCollection, this.currentModelId);
|
this.queryByElementId(`${this.currentCollection}:${this.currentModelId}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,12 +261,12 @@ export class HistoryListComponent extends BaseViewComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the data source to the request element id given by the collection string and the id.
|
* Sets the data source to the requested element id.
|
||||||
*/
|
*/
|
||||||
private async queryElementId(collectionString: string, id: number): Promise<void> {
|
private async queryByElementId(elementId: string): Promise<void> {
|
||||||
const historyData = await this.http.get<History[]>(`${environment.urlPrefix}/core/history/information/`, null, {
|
const historyData = await this.http.get<History[]>(`${environment.urlPrefix}/core/history/information/`, null, {
|
||||||
type: 'element',
|
type: 'element',
|
||||||
value: `${collectionString}:${id}`
|
value: elementId
|
||||||
});
|
});
|
||||||
this.dataSource.data = historyData.map(data => new History(data));
|
this.dataSource.data = historyData.map(data => new History(data));
|
||||||
}
|
}
|
||||||
|
@ -101,6 +101,13 @@
|
|||||||
<span translate>Show entire motion text</span>
|
<span translate>Show entire motion text</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button mat-menu-item *osPerms="'core.can_see_history'" [routerLink]="['/history']" [queryParams]="{element: motion.elementId}">
|
||||||
|
<mat-icon>history</mat-icon>
|
||||||
|
<span translate>
|
||||||
|
History
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<div *ngIf="perms.isAllowed('manage')">
|
<div *ngIf="perms.isAllowed('manage')">
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
<!-- Delete -->
|
<!-- Delete -->
|
||||||
|
@ -504,7 +504,7 @@ class HistoryInformationView(utils_views.APIView):
|
|||||||
"""
|
"""
|
||||||
Checks permission and parses query parameters.
|
Checks permission and parses query parameters.
|
||||||
"""
|
"""
|
||||||
if not has_perm(self.request.user, "users.can_see_history"):
|
if not has_perm(self.request.user, "core.can_see_history"):
|
||||||
self.permission_denied(self.request)
|
self.permission_denied(self.request)
|
||||||
type = self.request.query_params.get("type")
|
type = self.request.query_params.get("type")
|
||||||
value = self.request.query_params.get("value")
|
value = self.request.query_params.get("value")
|
||||||
|
Loading…
Reference in New Issue
Block a user