mirror of https://github.com/Squidex/squidex.git
32 changed files with 360 additions and 41 deletions
@ -0,0 +1,19 @@ |
|||||
|
<sqx-title message="{app} | Contributors | Settings" parameter="app" value="{{appName() | async}}"></sqx-title> |
||||
|
|
||||
|
<div class="panel panel-light"> |
||||
|
<div class="panel-header"> |
||||
|
<h3 class="panel-title">History</h3> |
||||
|
|
||||
|
<a class="panel-close" routerLink="../"> |
||||
|
<i class="icon-close"></i> |
||||
|
</a> |
||||
|
</div> |
||||
|
|
||||
|
<div class="panel-main"> |
||||
|
<div class="panel-content panel-content-blank"> |
||||
|
<div *ngFor="let event of events"> |
||||
|
{{event.message}} |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
@ -0,0 +1,7 @@ |
|||||
|
@import '_vars'; |
||||
|
@import '_mixins'; |
||||
|
|
||||
|
.panel { |
||||
|
min-width: 220px; |
||||
|
max-width: 1220px80px; |
||||
|
} |
||||
@ -0,0 +1,59 @@ |
|||||
|
/* |
||||
|
* Squidex Headless CMS |
||||
|
* |
||||
|
* @license |
||||
|
* Copyright (c) Sebastian Stehle. All rights reserved |
||||
|
*/ |
||||
|
|
||||
|
import { Component, OnDestroy, OnInit } from '@angular/core'; |
||||
|
import { ActivatedRoute } from '@angular/router'; |
||||
|
|
||||
|
import { ImmutableArray, NotificationService } from 'framework'; |
||||
|
|
||||
|
import { AppComponentBase } from './../app-component-base'; |
||||
|
import { AppsStoreService } from './../services/apps-store.service'; |
||||
|
import { HistoryEventDto, HistoryService } from './../services/history.service'; |
||||
|
import { UsersProviderService } from './../services/users-provider.service'; |
||||
|
|
||||
|
const FALLBACK_NAME = 'my-app'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'sqx-history', |
||||
|
styleUrls: ['./history.component.scss'], |
||||
|
templateUrl: './history.component.html' |
||||
|
}) |
||||
|
export class HistoryComponent extends AppComponentBase implements OnDestroy, OnInit { |
||||
|
private interval: any; |
||||
|
|
||||
|
public events = ImmutableArray.empty(); |
||||
|
|
||||
|
constructor(appsStore: AppsStoreService, notifications: NotificationService, usersProvider: UsersProviderService, |
||||
|
private readonly historyService: HistoryService, |
||||
|
private readonly route: ActivatedRoute |
||||
|
) { |
||||
|
super(appsStore, notifications, usersProvider); |
||||
|
} |
||||
|
|
||||
|
public ngOnDestroy() { |
||||
|
clearInterval(this.interval); |
||||
|
} |
||||
|
|
||||
|
public ngOnInit() { |
||||
|
this.load(); |
||||
|
|
||||
|
this.interval = |
||||
|
setInterval(() => { |
||||
|
this.load(); |
||||
|
}, 10000); |
||||
|
} |
||||
|
|
||||
|
public load() { |
||||
|
const channel = this.route.snapshot.data['channel']; |
||||
|
|
||||
|
this.appName() |
||||
|
.switchMap(app => this.historyService.getHistory(app, channel).retry(2)) |
||||
|
.subscribe(dtos => { |
||||
|
this.events = ImmutableArray.of(dtos); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,65 @@ |
|||||
|
/* |
||||
|
* Squidex Headless CMS |
||||
|
* |
||||
|
* @license |
||||
|
* Copyright (c) Sebastian Stehle. All rights reserved |
||||
|
*/ |
||||
|
|
||||
|
import { Response, ResponseOptions } from '@angular/http'; |
||||
|
import { Observable } from 'rxjs'; |
||||
|
import { Mock, Times } from 'typemoq'; |
||||
|
|
||||
|
import { DateTime } from 'framework'; |
||||
|
|
||||
|
import { |
||||
|
ApiUrlConfig, |
||||
|
AuthService, |
||||
|
HistoryEventDto, |
||||
|
HistoryService |
||||
|
} from './../'; |
||||
|
|
||||
|
describe('HistoryService', () => { |
||||
|
let authService: Mock<AuthService>; |
||||
|
let languageService: HistoryService; |
||||
|
|
||||
|
beforeEach(() => { |
||||
|
authService = Mock.ofType(AuthService); |
||||
|
languageService = new HistoryService(authService.object, new ApiUrlConfig('http://service/p/')); |
||||
|
}); |
||||
|
|
||||
|
it('should make get request to get history events', () => { |
||||
|
authService.setup(x => x.authGet('http://service/p/api/apps/my-app/history?channel=settings.contributors')) |
||||
|
.returns(() => Observable.of( |
||||
|
new Response( |
||||
|
new ResponseOptions({ |
||||
|
body: [{ |
||||
|
user: 'User1', |
||||
|
eventId: '1', |
||||
|
message: 'Message 1', |
||||
|
created: '2016-12-12T10:10' |
||||
|
}, { |
||||
|
user: 'User2', |
||||
|
eventId: '2', |
||||
|
message: 'Message 2', |
||||
|
created: '2016-12-13T10:10' |
||||
|
}] |
||||
|
}) |
||||
|
) |
||||
|
)) |
||||
|
.verifiable(Times.once()); |
||||
|
|
||||
|
let events: HistoryEventDto[] = null; |
||||
|
|
||||
|
languageService.getHistory('my-app', 'settings.contributors').subscribe(result => { |
||||
|
events = result; |
||||
|
}).unsubscribe(); |
||||
|
|
||||
|
expect(events).toEqual( |
||||
|
[ |
||||
|
new HistoryEventDto('1', 'User1', 'Message 1', DateTime.parseISO_UTC('2016-12-12T10:10')), |
||||
|
new HistoryEventDto('2', 'User2', 'Message 2', DateTime.parseISO_UTC('2016-12-13T10:10')) |
||||
|
]); |
||||
|
|
||||
|
authService.verifyAll(); |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,55 @@ |
|||||
|
/* |
||||
|
* Squidex Headless CMS |
||||
|
* |
||||
|
* @license |
||||
|
* Copyright (c) Sebastian Stehle. All rights reserved |
||||
|
*/ |
||||
|
|
||||
|
import { Injectable } from '@angular/core'; |
||||
|
import { Observable } from 'rxjs'; |
||||
|
|
||||
|
import { |
||||
|
ApiUrlConfig, |
||||
|
DateTime, |
||||
|
handleError |
||||
|
} from 'framework'; |
||||
|
|
||||
|
import { AuthService } from './auth.service'; |
||||
|
|
||||
|
export class HistoryEventDto { |
||||
|
constructor( |
||||
|
public readonly eventId: string, |
||||
|
public readonly user: string, |
||||
|
public readonly message: string, |
||||
|
public readonly created: DateTime |
||||
|
) { |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Injectable() |
||||
|
export class HistoryService { |
||||
|
constructor( |
||||
|
private readonly authService: AuthService, |
||||
|
private readonly apiUrl: ApiUrlConfig |
||||
|
) { |
||||
|
} |
||||
|
|
||||
|
public getHistory(appName: string, channel: string): Observable<HistoryEventDto[]> { |
||||
|
const url = this.apiUrl.buildUrl(`api/apps/${appName}/history?channel=${channel}`); |
||||
|
|
||||
|
return this.authService.authGet(url) |
||||
|
.map(response => response.json()) |
||||
|
.map(response => { |
||||
|
const items: any[] = response; |
||||
|
|
||||
|
return items.map(item => { |
||||
|
return new HistoryEventDto( |
||||
|
item.eventId, |
||||
|
item.user, |
||||
|
item.message, |
||||
|
DateTime.parseISO_UTC(item.created)); |
||||
|
}); |
||||
|
}) |
||||
|
.catch(response => handleError('Failed to load history. Please reload', response)); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue