Added history to frontend
This commit is contained in:
parent
1824ff7564
commit
165c140a25
@ -54,7 +54,7 @@ class DbModelABC(ABC):
|
|||||||
|
|
||||||
from data.schemas.administration.user_dao import userDao
|
from data.schemas.administration.user_dao import userDao
|
||||||
|
|
||||||
return await userDao.get_by_id(self._editor_id)
|
return await userDao.find_single_by({"id": self._editor_id})
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def created(self) -> datetime:
|
def created(self) -> datetime:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { DbModel } from 'src/app/model/entities/db-model';
|
import { DbModelWithHistory } from 'src/app/model/entities/db-model';
|
||||||
|
|
||||||
export interface Domain extends DbModel {
|
export interface Domain extends DbModelWithHistory {
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { DbModel } from 'src/app/model/entities/db-model';
|
import { DbModelWithHistory } from 'src/app/model/entities/db-model';
|
||||||
import { Role } from 'src/app/model/entities/role';
|
import { Role } from 'src/app/model/entities/role';
|
||||||
|
|
||||||
export interface Group extends DbModel {
|
export interface Group extends DbModelWithHistory {
|
||||||
name: string;
|
name: string;
|
||||||
roles: Role[];
|
roles: Role[];
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { DbModel } from 'src/app/model/entities/db-model';
|
import { DbModelWithHistory } from 'src/app/model/entities/db-model';
|
||||||
import { Group } from 'src/app/model/entities/group';
|
import { Group } from 'src/app/model/entities/group';
|
||||||
import { Domain } from 'src/app/model/entities/domain';
|
import { Domain } from 'src/app/model/entities/domain';
|
||||||
|
|
||||||
export interface ShortUrl extends DbModel {
|
export interface ShortUrl extends DbModelWithHistory {
|
||||||
shortUrl: string;
|
shortUrl: string;
|
||||||
targetUrl: string;
|
targetUrl: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
@ -11,7 +11,10 @@ import { Filter } from 'src/app/model/graphql/filter/filter.model';
|
|||||||
import { Sort } from 'src/app/model/graphql/filter/sort.model';
|
import { Sort } from 'src/app/model/graphql/filter/sort.model';
|
||||||
import { Apollo, gql } from 'apollo-angular';
|
import { Apollo, gql } from 'apollo-angular';
|
||||||
import { QueryResult } from 'src/app/model/entities/query-result';
|
import { QueryResult } from 'src/app/model/entities/query-result';
|
||||||
import { DB_MODEL_FRAGMENT } from 'src/app/model/graphql/db-model.query';
|
import {
|
||||||
|
DB_HISTORY_MODEL_FRAGMENT,
|
||||||
|
DB_MODEL_FRAGMENT,
|
||||||
|
} from 'src/app/model/graphql/db-model.query';
|
||||||
import { catchError, map } from 'rxjs/operators';
|
import { catchError, map } from 'rxjs/operators';
|
||||||
import { SpinnerService } from 'src/app/service/spinner.service';
|
import { SpinnerService } from 'src/app/service/spinner.service';
|
||||||
import {
|
import {
|
||||||
@ -19,10 +22,11 @@ import {
|
|||||||
DomainCreateInput,
|
DomainCreateInput,
|
||||||
DomainUpdateInput,
|
DomainUpdateInput,
|
||||||
} from 'src/app/model/entities/domain';
|
} from 'src/app/model/entities/domain';
|
||||||
|
import { PageWithHistoryDataService } from 'src/app/core/base/page-with-history.data.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DomainsDataService
|
export class DomainsDataService
|
||||||
extends PageDataService<Domain>
|
extends PageWithHistoryDataService<Domain>
|
||||||
implements
|
implements
|
||||||
Create<Domain, DomainCreateInput>,
|
Create<Domain, DomainCreateInput>,
|
||||||
Update<Domain, DomainUpdateInput>,
|
Update<Domain, DomainUpdateInput>,
|
||||||
@ -109,6 +113,40 @@ export class DomainsDataService
|
|||||||
.pipe(map(result => result.data.domains.nodes[0]));
|
.pipe(map(result => result.data.domains.nodes[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadHistory(id: number) {
|
||||||
|
return this.apollo
|
||||||
|
.query<{ domains: QueryResult<Domain> }>({
|
||||||
|
query: gql`
|
||||||
|
query getDomainHistory($id: Int) {
|
||||||
|
domains(filter: { id: { equal: $id } }) {
|
||||||
|
count
|
||||||
|
totalCount
|
||||||
|
nodes {
|
||||||
|
history {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
|
||||||
|
...DB_HISTORY_MODEL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
${DB_HISTORY_MODEL_FRAGMENT}
|
||||||
|
`,
|
||||||
|
variables: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.pipe(
|
||||||
|
catchError(err => {
|
||||||
|
this.spinner.hide();
|
||||||
|
throw err;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.pipe(map(result => result.data?.domains?.nodes?.[0]?.history ?? []));
|
||||||
|
}
|
||||||
|
|
||||||
onChange(): Observable<void> {
|
onChange(): Observable<void> {
|
||||||
return this.apollo
|
return this.apollo
|
||||||
.subscribe<{ domainChange: void }>({
|
.subscribe<{ domainChange: void }>({
|
||||||
@ -238,6 +276,10 @@ export class DomainsDataService
|
|||||||
provide: PageDataService,
|
provide: PageDataService,
|
||||||
useClass: DomainsDataService,
|
useClass: DomainsDataService,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: PageWithHistoryDataService,
|
||||||
|
useClass: DomainsDataService,
|
||||||
|
},
|
||||||
DomainsDataService,
|
DomainsDataService,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import { DomainsPage } from 'src/app/modules/admin/domains/domains.page';
|
|||||||
import { DomainFormPageComponent } from 'src/app/modules/admin/domains/form-page/domain-form-page.component';
|
import { DomainFormPageComponent } from 'src/app/modules/admin/domains/form-page/domain-form-page.component';
|
||||||
import { DomainsDataService } from 'src/app/modules/admin/domains/domains.data.service';
|
import { DomainsDataService } from 'src/app/modules/admin/domains/domains.data.service';
|
||||||
import { DomainsColumns } from 'src/app/modules/admin/domains/domains.columns';
|
import { DomainsColumns } from 'src/app/modules/admin/domains/domains.columns';
|
||||||
|
import { HistoryComponent } from 'src/app/modules/admin/domains/history/history.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
@ -31,12 +32,20 @@ const routes: Routes = [
|
|||||||
permissions: [PermissionsEnum.apiKeysUpdate],
|
permissions: [PermissionsEnum.apiKeysUpdate],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'history/:historyId',
|
||||||
|
component: HistoryComponent,
|
||||||
|
canActivate: [PermissionGuard],
|
||||||
|
data: {
|
||||||
|
permissions: [PermissionsEnum.domains],
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [DomainsPage, DomainFormPageComponent],
|
declarations: [DomainsPage, DomainFormPageComponent, HistoryComponent],
|
||||||
imports: [CommonModule, SharedModule, RouterModule.forChild(routes)],
|
imports: [CommonModule, SharedModule, RouterModule.forChild(routes)],
|
||||||
providers: [DomainsDataService.provide(), DomainsColumns.provide()],
|
providers: [DomainsDataService.provide(), DomainsColumns.provide()],
|
||||||
})
|
})
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
[(skip)]="skip"
|
[(skip)]="skip"
|
||||||
[(take)]="take"
|
[(take)]="take"
|
||||||
(load)="load()"
|
(load)="load()"
|
||||||
|
[history]="true"
|
||||||
[create]="true"
|
[create]="true"
|
||||||
[update]="true"
|
[update]="true"
|
||||||
(delete)="delete($event)"
|
(delete)="delete($event)"
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
<app-history-sidebar
|
||||||
|
[loadHistory]="loadHistory"
|
||||||
|
[columns]="columns"></app-history-sidebar>
|
@ -0,0 +1,65 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { HistoryComponent } from './history.component';
|
||||||
|
import { SharedModule } from 'src/app/modules/shared/shared.module';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { AuthService } from 'src/app/service/auth.service';
|
||||||
|
import { KeycloakService } from 'keycloak-angular';
|
||||||
|
import { ErrorHandlingService } from 'src/app/service/error-handling.service';
|
||||||
|
import { ToastService } from 'src/app/service/toast.service';
|
||||||
|
import { ConfirmationService, MessageService } from 'primeng/api';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
import { PageDataService } from 'src/app/core/base/page.data.service';
|
||||||
|
import { IpListDataService } from 'src/app/modules/admin/tools/ip-list/ip-list.data.service';
|
||||||
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
import { PageColumns } from 'src/app/core/base/page.columns';
|
||||||
|
import { MockPageColumns } from 'src/app/modules/shared/test/page.columns.mock';
|
||||||
|
|
||||||
|
describe('HistoryComponent', () => {
|
||||||
|
let component: HistoryComponent<unknown>;
|
||||||
|
let fixture: ComponentFixture<HistoryComponent<unknown>>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [HistoryComponent],
|
||||||
|
imports: [
|
||||||
|
BrowserAnimationsModule,
|
||||||
|
SharedModule,
|
||||||
|
TranslateModule.forRoot(),
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
AuthService,
|
||||||
|
KeycloakService,
|
||||||
|
ErrorHandlingService,
|
||||||
|
ToastService,
|
||||||
|
MessageService,
|
||||||
|
ConfirmationService,
|
||||||
|
{
|
||||||
|
provide: ActivatedRoute,
|
||||||
|
useValue: {
|
||||||
|
snapshot: { params: { historyId: '3' } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: PageDataService,
|
||||||
|
useClass: IpListDataService,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: PageColumns,
|
||||||
|
useClass: MockPageColumns,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(HistoryComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
//eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
component.loadHistory = (id: number) => of([]);
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,18 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { PageWithHistoryDataService } from 'src/app/core/base/page-with-history.data.service';
|
||||||
|
import { PageColumns } from 'src/app/core/base/page.columns';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-history',
|
||||||
|
templateUrl: './history.component.html',
|
||||||
|
styleUrl: './history.component.scss',
|
||||||
|
})
|
||||||
|
export class HistoryComponent<T> {
|
||||||
|
loadHistory = (id: number) => this.data.loadHistory(id);
|
||||||
|
columns = this._columns.get();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public data: PageWithHistoryDataService<T>,
|
||||||
|
private _columns: PageColumns<T>
|
||||||
|
) {}
|
||||||
|
}
|
@ -11,7 +11,10 @@ import { Filter } from 'src/app/model/graphql/filter/filter.model';
|
|||||||
import { Sort } from 'src/app/model/graphql/filter/sort.model';
|
import { Sort } from 'src/app/model/graphql/filter/sort.model';
|
||||||
import { Apollo, gql } from 'apollo-angular';
|
import { Apollo, gql } from 'apollo-angular';
|
||||||
import { QueryResult } from 'src/app/model/entities/query-result';
|
import { QueryResult } from 'src/app/model/entities/query-result';
|
||||||
import { DB_MODEL_FRAGMENT } from 'src/app/model/graphql/db-model.query';
|
import {
|
||||||
|
DB_HISTORY_MODEL_FRAGMENT,
|
||||||
|
DB_MODEL_FRAGMENT,
|
||||||
|
} from 'src/app/model/graphql/db-model.query';
|
||||||
import { catchError, map } from 'rxjs/operators';
|
import { catchError, map } from 'rxjs/operators';
|
||||||
import { SpinnerService } from 'src/app/service/spinner.service';
|
import { SpinnerService } from 'src/app/service/spinner.service';
|
||||||
import {
|
import {
|
||||||
@ -19,10 +22,12 @@ import {
|
|||||||
GroupCreateInput,
|
GroupCreateInput,
|
||||||
GroupUpdateInput,
|
GroupUpdateInput,
|
||||||
} from 'src/app/model/entities/group';
|
} from 'src/app/model/entities/group';
|
||||||
|
import { PageWithHistoryDataService } from 'src/app/core/base/page-with-history.data.service';
|
||||||
|
import { Domain } from 'src/app/model/entities/domain';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GroupsDataService
|
export class GroupsDataService
|
||||||
extends PageDataService<Group>
|
extends PageWithHistoryDataService<Group>
|
||||||
implements
|
implements
|
||||||
Create<Group, GroupCreateInput>,
|
Create<Group, GroupCreateInput>,
|
||||||
Update<Group, GroupUpdateInput>,
|
Update<Group, GroupUpdateInput>,
|
||||||
@ -117,6 +122,40 @@ export class GroupsDataService
|
|||||||
.pipe(map(result => result.data.groups.nodes[0]));
|
.pipe(map(result => result.data.groups.nodes[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadHistory(id: number) {
|
||||||
|
return this.apollo
|
||||||
|
.query<{ groups: QueryResult<Group> }>({
|
||||||
|
query: gql`
|
||||||
|
query getGroupHistory($id: Int) {
|
||||||
|
groups(filter: { id: { equal: $id } }) {
|
||||||
|
count
|
||||||
|
totalCount
|
||||||
|
nodes {
|
||||||
|
history {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
|
||||||
|
...DB_HISTORY_MODEL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
${DB_HISTORY_MODEL_FRAGMENT}
|
||||||
|
`,
|
||||||
|
variables: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.pipe(
|
||||||
|
catchError(err => {
|
||||||
|
this.spinner.hide();
|
||||||
|
throw err;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.pipe(map(result => result.data?.groups?.nodes?.[0]?.history ?? []));
|
||||||
|
}
|
||||||
|
|
||||||
onChange(): Observable<void> {
|
onChange(): Observable<void> {
|
||||||
return this.apollo
|
return this.apollo
|
||||||
.subscribe<{ groupChange: void }>({
|
.subscribe<{ groupChange: void }>({
|
||||||
@ -248,6 +287,10 @@ export class GroupsDataService
|
|||||||
provide: PageDataService,
|
provide: PageDataService,
|
||||||
useClass: GroupsDataService,
|
useClass: GroupsDataService,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: PageWithHistoryDataService,
|
||||||
|
useClass: GroupsDataService,
|
||||||
|
},
|
||||||
GroupsDataService,
|
GroupsDataService,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
import { NgModule } from "@angular/core";
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from "@angular/common";
|
import { CommonModule } from '@angular/common';
|
||||||
import { SharedModule } from "src/app/modules/shared/shared.module";
|
import { SharedModule } from 'src/app/modules/shared/shared.module';
|
||||||
import { RouterModule, Routes } from "@angular/router";
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
import { PermissionGuard } from "src/app/core/guard/permission.guard";
|
import { PermissionGuard } from 'src/app/core/guard/permission.guard';
|
||||||
import { PermissionsEnum } from "src/app/model/auth/permissionsEnum";
|
import { PermissionsEnum } from 'src/app/model/auth/permissionsEnum';
|
||||||
import { GroupsPage } from "src/app/modules/admin/groups/groups.page";
|
import { GroupsPage } from 'src/app/modules/admin/groups/groups.page';
|
||||||
import { GroupFormPageComponent } from "src/app/modules/admin/groups/form-page/group-form-page.component";
|
import { GroupFormPageComponent } from 'src/app/modules/admin/groups/form-page/group-form-page.component';
|
||||||
import { GroupsDataService } from "src/app/modules/admin/groups/groups.data.service";
|
import { GroupsDataService } from 'src/app/modules/admin/groups/groups.data.service';
|
||||||
import { GroupsColumns } from "src/app/modules/admin/groups/groups.columns";
|
import { GroupsColumns } from 'src/app/modules/admin/groups/groups.columns';
|
||||||
|
import { HistoryComponent } from 'src/app/modules/admin/groups/history/history.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: "",
|
path: '',
|
||||||
title: "Groups",
|
title: 'Groups',
|
||||||
component: GroupsPage,
|
component: GroupsPage,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "create",
|
path: 'create',
|
||||||
component: GroupFormPageComponent,
|
component: GroupFormPageComponent,
|
||||||
canActivate: [PermissionGuard],
|
canActivate: [PermissionGuard],
|
||||||
data: {
|
data: {
|
||||||
@ -24,19 +25,27 @@ const routes: Routes = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "edit/:id",
|
path: 'edit/:id',
|
||||||
component: GroupFormPageComponent,
|
component: GroupFormPageComponent,
|
||||||
canActivate: [PermissionGuard],
|
canActivate: [PermissionGuard],
|
||||||
data: {
|
data: {
|
||||||
permissions: [PermissionsEnum.apiKeysUpdate],
|
permissions: [PermissionsEnum.apiKeysUpdate],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'history/:historyId',
|
||||||
|
component: HistoryComponent,
|
||||||
|
canActivate: [PermissionGuard],
|
||||||
|
data: {
|
||||||
|
permissions: [PermissionsEnum.domains],
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [GroupsPage, GroupFormPageComponent],
|
declarations: [GroupsPage, GroupFormPageComponent, HistoryComponent],
|
||||||
imports: [CommonModule, SharedModule, RouterModule.forChild(routes)],
|
imports: [CommonModule, SharedModule, RouterModule.forChild(routes)],
|
||||||
providers: [GroupsDataService.provide(), GroupsColumns.provide()],
|
providers: [GroupsDataService.provide(), GroupsColumns.provide()],
|
||||||
})
|
})
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
[(skip)]="skip"
|
[(skip)]="skip"
|
||||||
[(take)]="take"
|
[(take)]="take"
|
||||||
(load)="load()"
|
(load)="load()"
|
||||||
|
[history]="true"
|
||||||
[create]="true"
|
[create]="true"
|
||||||
[update]="true"
|
[update]="true"
|
||||||
(delete)="delete($event)"
|
(delete)="delete($event)"
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
<app-history-sidebar
|
||||||
|
[loadHistory]="loadHistory"
|
||||||
|
[columns]="columns"></app-history-sidebar>
|
@ -0,0 +1,65 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { HistoryComponent } from './history.component';
|
||||||
|
import { SharedModule } from 'src/app/modules/shared/shared.module';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { AuthService } from 'src/app/service/auth.service';
|
||||||
|
import { KeycloakService } from 'keycloak-angular';
|
||||||
|
import { ErrorHandlingService } from 'src/app/service/error-handling.service';
|
||||||
|
import { ToastService } from 'src/app/service/toast.service';
|
||||||
|
import { ConfirmationService, MessageService } from 'primeng/api';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
import { PageDataService } from 'src/app/core/base/page.data.service';
|
||||||
|
import { IpListDataService } from 'src/app/modules/admin/tools/ip-list/ip-list.data.service';
|
||||||
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
import { PageColumns } from 'src/app/core/base/page.columns';
|
||||||
|
import { MockPageColumns } from 'src/app/modules/shared/test/page.columns.mock';
|
||||||
|
|
||||||
|
describe('HistoryComponent', () => {
|
||||||
|
let component: HistoryComponent<unknown>;
|
||||||
|
let fixture: ComponentFixture<HistoryComponent<unknown>>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [HistoryComponent],
|
||||||
|
imports: [
|
||||||
|
BrowserAnimationsModule,
|
||||||
|
SharedModule,
|
||||||
|
TranslateModule.forRoot(),
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
AuthService,
|
||||||
|
KeycloakService,
|
||||||
|
ErrorHandlingService,
|
||||||
|
ToastService,
|
||||||
|
MessageService,
|
||||||
|
ConfirmationService,
|
||||||
|
{
|
||||||
|
provide: ActivatedRoute,
|
||||||
|
useValue: {
|
||||||
|
snapshot: { params: { historyId: '3' } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: PageDataService,
|
||||||
|
useClass: IpListDataService,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: PageColumns,
|
||||||
|
useClass: MockPageColumns,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(HistoryComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
//eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
component.loadHistory = (id: number) => of([]);
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,18 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { PageWithHistoryDataService } from 'src/app/core/base/page-with-history.data.service';
|
||||||
|
import { PageColumns } from 'src/app/core/base/page.columns';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-history',
|
||||||
|
templateUrl: './history.component.html',
|
||||||
|
styleUrl: './history.component.scss',
|
||||||
|
})
|
||||||
|
export class HistoryComponent<T> {
|
||||||
|
loadHistory = (id: number) => this.data.loadHistory(id);
|
||||||
|
columns = this._columns.get();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public data: PageWithHistoryDataService<T>,
|
||||||
|
private _columns: PageColumns<T>
|
||||||
|
) {}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
<app-history-sidebar
|
||||||
|
[loadHistory]="loadHistory"
|
||||||
|
[columns]="columns"></app-history-sidebar>
|
@ -0,0 +1,65 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { HistoryComponent } from './history.component';
|
||||||
|
import { SharedModule } from 'src/app/modules/shared/shared.module';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { AuthService } from 'src/app/service/auth.service';
|
||||||
|
import { KeycloakService } from 'keycloak-angular';
|
||||||
|
import { ErrorHandlingService } from 'src/app/service/error-handling.service';
|
||||||
|
import { ToastService } from 'src/app/service/toast.service';
|
||||||
|
import { ConfirmationService, MessageService } from 'primeng/api';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
import { PageDataService } from 'src/app/core/base/page.data.service';
|
||||||
|
import { IpListDataService } from 'src/app/modules/admin/tools/ip-list/ip-list.data.service';
|
||||||
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
import { PageColumns } from 'src/app/core/base/page.columns';
|
||||||
|
import { MockPageColumns } from 'src/app/modules/shared/test/page.columns.mock';
|
||||||
|
|
||||||
|
describe('HistoryComponent', () => {
|
||||||
|
let component: HistoryComponent<unknown>;
|
||||||
|
let fixture: ComponentFixture<HistoryComponent<unknown>>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [HistoryComponent],
|
||||||
|
imports: [
|
||||||
|
BrowserAnimationsModule,
|
||||||
|
SharedModule,
|
||||||
|
TranslateModule.forRoot(),
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
AuthService,
|
||||||
|
KeycloakService,
|
||||||
|
ErrorHandlingService,
|
||||||
|
ToastService,
|
||||||
|
MessageService,
|
||||||
|
ConfirmationService,
|
||||||
|
{
|
||||||
|
provide: ActivatedRoute,
|
||||||
|
useValue: {
|
||||||
|
snapshot: { params: { historyId: '3' } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: PageDataService,
|
||||||
|
useClass: IpListDataService,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: PageColumns,
|
||||||
|
useClass: MockPageColumns,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(HistoryComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
//eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
component.loadHistory = (id: number) => of([]);
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,18 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { PageWithHistoryDataService } from 'src/app/core/base/page-with-history.data.service';
|
||||||
|
import { PageColumns } from 'src/app/core/base/page.columns';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-history',
|
||||||
|
templateUrl: './history.component.html',
|
||||||
|
styleUrl: './history.component.scss',
|
||||||
|
})
|
||||||
|
export class HistoryComponent<T> {
|
||||||
|
loadHistory = (id: number) => this.data.loadHistory(id);
|
||||||
|
columns = this._columns.get();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public data: PageWithHistoryDataService<T>,
|
||||||
|
private _columns: PageColumns<T>
|
||||||
|
) {}
|
||||||
|
}
|
@ -11,7 +11,10 @@ import { Filter } from 'src/app/model/graphql/filter/filter.model';
|
|||||||
import { Sort } from 'src/app/model/graphql/filter/sort.model';
|
import { Sort } from 'src/app/model/graphql/filter/sort.model';
|
||||||
import { Apollo, gql } from 'apollo-angular';
|
import { Apollo, gql } from 'apollo-angular';
|
||||||
import { QueryResult } from 'src/app/model/entities/query-result';
|
import { QueryResult } from 'src/app/model/entities/query-result';
|
||||||
import { DB_MODEL_FRAGMENT } from 'src/app/model/graphql/db-model.query';
|
import {
|
||||||
|
DB_HISTORY_MODEL_FRAGMENT,
|
||||||
|
DB_MODEL_FRAGMENT,
|
||||||
|
} from 'src/app/model/graphql/db-model.query';
|
||||||
import { catchError, map } from 'rxjs/operators';
|
import { catchError, map } from 'rxjs/operators';
|
||||||
import { SpinnerService } from 'src/app/service/spinner.service';
|
import { SpinnerService } from 'src/app/service/spinner.service';
|
||||||
import {
|
import {
|
||||||
@ -21,6 +24,7 @@ import {
|
|||||||
} from 'src/app/model/entities/short-url';
|
} from 'src/app/model/entities/short-url';
|
||||||
import { Group } from 'src/app/model/entities/group';
|
import { Group } from 'src/app/model/entities/group';
|
||||||
import { Domain } from 'src/app/model/entities/domain';
|
import { Domain } from 'src/app/model/entities/domain';
|
||||||
|
import { PageWithHistoryDataService } from 'src/app/core/base/page-with-history.data.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ShortUrlsDataService
|
export class ShortUrlsDataService
|
||||||
@ -132,6 +136,52 @@ export class ShortUrlsDataService
|
|||||||
.pipe(map(result => result.data.shortUrls.nodes[0]));
|
.pipe(map(result => result.data.shortUrls.nodes[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadHistory(id: number) {
|
||||||
|
return this.apollo
|
||||||
|
.query<{ shortUrls: QueryResult<ShortUrl> }>({
|
||||||
|
query: gql`
|
||||||
|
query getDomainHistory($id: Int) {
|
||||||
|
shortUrls(filter: { id: { equal: $id } }) {
|
||||||
|
count
|
||||||
|
totalCount
|
||||||
|
nodes {
|
||||||
|
history {
|
||||||
|
id
|
||||||
|
shortUrl
|
||||||
|
targetUrl
|
||||||
|
description
|
||||||
|
loadingScreen
|
||||||
|
visits
|
||||||
|
group {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
domain {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
|
||||||
|
...DB_HISTORY_MODEL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
${DB_HISTORY_MODEL_FRAGMENT}
|
||||||
|
`,
|
||||||
|
variables: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.pipe(
|
||||||
|
catchError(err => {
|
||||||
|
this.spinner.hide();
|
||||||
|
throw err;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.pipe(map(result => result.data?.shortUrls?.nodes?.[0]?.history ?? []));
|
||||||
|
}
|
||||||
|
|
||||||
onChange(): Observable<void> {
|
onChange(): Observable<void> {
|
||||||
return merge(
|
return merge(
|
||||||
this.apollo
|
this.apollo
|
||||||
@ -329,6 +379,10 @@ export class ShortUrlsDataService
|
|||||||
provide: PageDataService,
|
provide: PageDataService,
|
||||||
useClass: ShortUrlsDataService,
|
useClass: ShortUrlsDataService,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: PageWithHistoryDataService,
|
||||||
|
useClass: ShortUrlsDataService,
|
||||||
|
},
|
||||||
ShortUrlsDataService,
|
ShortUrlsDataService,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import { ShortUrlsPage } from 'src/app/modules/admin/short-urls/short-urls.page'
|
|||||||
import { ShortUrlFormPageComponent } from 'src/app/modules/admin/short-urls/form-page/short-url-form-page.component';
|
import { ShortUrlFormPageComponent } from 'src/app/modules/admin/short-urls/form-page/short-url-form-page.component';
|
||||||
import { ShortUrlsDataService } from 'src/app/modules/admin/short-urls/short-urls.data.service';
|
import { ShortUrlsDataService } from 'src/app/modules/admin/short-urls/short-urls.data.service';
|
||||||
import { ShortUrlsColumns } from 'src/app/modules/admin/short-urls/short-urls.columns';
|
import { ShortUrlsColumns } from 'src/app/modules/admin/short-urls/short-urls.columns';
|
||||||
|
import { HistoryComponent } from 'src/app/modules/admin/short-urls/history/history.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
@ -31,12 +32,20 @@ const routes: Routes = [
|
|||||||
permissions: [PermissionsEnum.shortUrlsUpdate],
|
permissions: [PermissionsEnum.shortUrlsUpdate],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'history/:historyId',
|
||||||
|
component: HistoryComponent,
|
||||||
|
canActivate: [PermissionGuard],
|
||||||
|
data: {
|
||||||
|
permissions: [PermissionsEnum.domains],
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [ShortUrlsPage, ShortUrlFormPageComponent],
|
declarations: [ShortUrlsPage, ShortUrlFormPageComponent, HistoryComponent],
|
||||||
imports: [CommonModule, SharedModule, RouterModule.forChild(routes)],
|
imports: [CommonModule, SharedModule, RouterModule.forChild(routes)],
|
||||||
providers: [ShortUrlsDataService.provide(), ShortUrlsColumns.provide()],
|
providers: [ShortUrlsDataService.provide(), ShortUrlsColumns.provide()],
|
||||||
})
|
})
|
||||||
|
@ -67,6 +67,12 @@
|
|||||||
tooltipPosition="left"
|
tooltipPosition="left"
|
||||||
pTooltip="{{ 'table.restore' | translate }}"
|
pTooltip="{{ 'table.restore' | translate }}"
|
||||||
(click)="restore(url)"></p-button>
|
(click)="restore(url)"></p-button>
|
||||||
|
<p-button
|
||||||
|
class="icon-btn btn"
|
||||||
|
icon="pi pi-history"
|
||||||
|
tooltipPosition="left"
|
||||||
|
pTooltip="{{ 'table.history' | translate }}"
|
||||||
|
routerLink="history/{{ url.id }}"></p-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user