Browse Source

App context removed.

pull/271/head
Sebastian Stehle 9 years ago
parent
commit
a3538bad26
  1. 18
      src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts
  2. 25
      src/Squidex/app/features/administration/pages/users/user-page.component.ts
  3. 4
      src/Squidex/app/features/administration/pages/users/users-page.component.html
  4. 25
      src/Squidex/app/features/administration/pages/users/users-page.component.ts
  5. 22
      src/Squidex/app/features/administration/state/users.state.ts
  6. 40
      src/Squidex/app/features/schemas/state/schemas.state.ts
  7. 60
      src/Squidex/app/framework/angular/http-extensions-impl.ts
  8. 1
      src/Squidex/app/framework/declarations.ts
  9. 16
      src/Squidex/app/framework/services/dialog.service.ts
  10. 40
      src/Squidex/app/framework/utils/error.spec.ts
  11. 57
      src/Squidex/app/framework/utils/error.ts
  12. 11
      src/Squidex/app/framework/utils/version.spec.ts
  13. 8
      src/Squidex/app/framework/utils/version.ts

18
src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts

@ -9,8 +9,8 @@ import { Component, OnDestroy, OnInit } from '@angular/core';
import { Observable, Subscription } from 'rxjs';
import {
AppContext,
fadeAnimation,
DialogService,
ImmutableArray,
ModalView
} from 'shared';
@ -21,9 +21,6 @@ import { EventConsumerDto, EventConsumersService } from './../../services/event-
selector: 'sqx-event-consumers-page',
styleUrls: ['./event-consumers-page.component.scss'],
templateUrl: './event-consumers-page.component.html',
providers: [
AppContext
],
animations: [
fadeAnimation
]
@ -35,7 +32,8 @@ export class EventConsumersPageComponent implements OnDestroy, OnInit {
public eventConsumerError = '';
public eventConsumers = ImmutableArray.empty<EventConsumerDto>();
constructor(public readonly ctx: AppContext,
constructor(
private readonly dialogs: DialogService,
private readonly eventConsumersService: EventConsumersService
) {
}
@ -59,11 +57,11 @@ export class EventConsumersPageComponent implements OnDestroy, OnInit {
this.eventConsumers = ImmutableArray.of(dtos);
if (showInfo) {
this.ctx.notifyInfo('Event Consumers reloaded.');
this.dialogs.notifyInfo('Event Consumers reloaded.');
}
}, error => {
if (showError) {
this.ctx.notifyError(error);
this.dialogs.notifyError(error);
}
});
}
@ -73,7 +71,7 @@ export class EventConsumersPageComponent implements OnDestroy, OnInit {
.subscribe(() => {
this.eventConsumers = this.eventConsumers.replaceBy('name', consumer.start());
}, error => {
this.ctx.notifyError(error);
this.dialogs.notifyError(error);
});
}
@ -82,7 +80,7 @@ export class EventConsumersPageComponent implements OnDestroy, OnInit {
.subscribe(() => {
this.eventConsumers = this.eventConsumers.replaceBy('name', consumer.stop());
}, error => {
this.ctx.notifyError(error);
this.dialogs.notifyError(error);
});
}
@ -91,7 +89,7 @@ export class EventConsumersPageComponent implements OnDestroy, OnInit {
.subscribe(() => {
this.eventConsumers = this.eventConsumers.replaceBy('name', consumer.reset());
}, error => {
this.ctx.notifyError(error);
this.dialogs.notifyError(error);
});
}

25
src/Squidex/app/features/administration/pages/users/user-page.component.ts

@ -7,10 +7,10 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { ActivatedRoute, Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { AppContext, ValidatorsEx } from 'shared';
import { AuthService, ValidatorsEx } from 'shared';
import { UserDto } from './../../services/users.service';
import { UsersState } from './../../state/users.state';
@ -18,10 +18,7 @@ import { UsersState } from './../../state/users.state';
@Component({
selector: 'sqx-user-page',
styleUrls: ['./user-page.component.scss'],
templateUrl: './user-page.component.html',
providers: [
AppContext
]
templateUrl: './user-page.component.html'
})
export class UserPageComponent implements OnDestroy, OnInit {
private selectedUserSubscription: Subscription;
@ -55,10 +52,12 @@ export class UserPageComponent implements OnDestroy, OnInit {
public isCurrentUser = false;
constructor(public readonly ctx: AppContext,
constructor(
private readonly authService: AuthService,
private readonly formBuilder: FormBuilder,
private readonly route: ActivatedRoute,
private readonly router: Router,
private readonly state: UsersState
private readonly usersState: UsersState
) {
}
@ -68,7 +67,7 @@ export class UserPageComponent implements OnDestroy, OnInit {
public ngOnInit() {
this.selectedUserSubscription =
this.state.selectedUser.subscribe(user => this.setupAndPopulateForm(user!));
this.usersState.selectedUser.subscribe(user => this.setupAndPopulateForm(user!));
}
public save() {
@ -80,14 +79,14 @@ export class UserPageComponent implements OnDestroy, OnInit {
const requestDto = this.userForm.value;
if (!this.user) {
this.state.createUser(requestDto)
this.usersState.createUser(requestDto)
.subscribe(user => {
this.back();
}, error => {
this.resetFormState(error.displayMessage);
});
} else {
this.state.updateUser(this.user!, requestDto)
this.usersState.updateUser(this.user!, requestDto)
.subscribe(() => {
this.resetFormState();
}, error => {
@ -98,13 +97,13 @@ export class UserPageComponent implements OnDestroy, OnInit {
}
private back() {
this.router.navigate(['../'], { relativeTo: this.ctx.route, replaceUrl: true });
this.router.navigate(['../'], { relativeTo: this.route, replaceUrl: true });
}
private setupAndPopulateForm(user: UserDto | null) {
this.user = user;
this.isCurrentUser = user !== null && user.id === this.ctx.userId;
this.isCurrentUser = user !== null && user.id === this.authService.user!.id;
this.userForm.controls['password'].setValidators(
user ?

4
src/Squidex/app/features/administration/pages/users/users-page.component.html

@ -56,7 +56,7 @@
<div sqxIgnoreScrollbar>
<table class="table table-items table-fixed">
<tbody>
<ng-template ngFor let-user [ngForOf]="state.usersItems | async" [ngForTrackBy]="state.trackBy">
<ng-template ngFor let-user [ngForOf]="state.usersItems | async" [ngForTrackBy]="state.trackByUser">
<tr [routerLink]="user.id" routerLinkActive="active">
<td class="cell-user">
<img class="user-picture" [attr.title]="user.name" [attr.src]="user | sqxUserDtoPicture" />
@ -88,7 +88,7 @@
</div>
</div>
<ng-container *ngIf="state.usersPager | async as pager">
<ng-container *ngIf="usersState.usersPager | async as pager">
<div class="grid-footer clearfix" *ngIf="pager.numberOfItems > 0">
<div class="float-right pagination">
<span class="pagination-text">{{pager.itemFirst}}-{{pager.itemLast}} of {{pager.numberOfItems}}</span>

25
src/Squidex/app/features/administration/pages/users/users-page.component.ts

@ -8,7 +8,7 @@
import { Component, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { AppContext } from 'shared';
import { DialogService } from 'shared';
import { UserDto } from './../../services/users.service';
import { UsersState } from './../../state/users.state';
@ -16,16 +16,13 @@ import { UsersState } from './../../state/users.state';
@Component({
selector: 'sqx-users-page',
styleUrls: ['./users-page.component.scss'],
templateUrl: './users-page.component.html',
providers: [
AppContext
]
templateUrl: './users-page.component.html'
})
export class UsersPageComponent implements OnInit {
public usersFilter = new FormControl();
constructor(public readonly ctx: AppContext,
public readonly state: UsersState
constructor(public readonly usersState: UsersState,
private readonly dialogs: DialogService
) {
}
@ -34,32 +31,32 @@ export class UsersPageComponent implements OnInit {
}
public search() {
this.state.search(this.usersFilter.value).subscribe();
this.usersState.search(this.usersFilter.value).subscribe();
}
public load(showInfo = false) {
this.state.loadUsers()
this.usersState.loadUsers()
.subscribe(() => {
if (showInfo) {
this.ctx.notifyInfo('Users reloaded.');
this.dialogs.notifyInfo('Users reloaded.');
}
});
}
public lock(user: UserDto) {
this.state.lockUser(user).subscribe();
this.usersState.lockUser(user).subscribe();
}
public unlock(user: UserDto) {
this.state.unlockUser(user).subscribe();
this.usersState.unlockUser(user).subscribe();
}
public goPrev() {
this.state.goPrev().subscribe();
this.usersState.goPrev().subscribe();
}
public goNext() {
this.state.goNext().subscribe();
this.usersState.goNext().subscribe();
}
}

22
src/Squidex/app/features/administration/state/users.state.ts

@ -12,9 +12,7 @@ import 'framework/utils/rxjs-extensions';
import {
DialogService,
ErrorDto,
ImmutableArray,
Notification,
Pager
} from 'shared';
@ -59,7 +57,7 @@ export class UsersState {
public loadUsers(): Observable<any> {
return this.usersService.getUsers(this.usersPager.value.pageSize, this.usersPager.value.skip, this.usersQuery.value)
.catch(error => this.notifyError(error))
.catch(error => this.dialogs.notifyError(error))
.do(dtos => {
this.users.nextBy(v => ImmutableArray.of(dtos.items));
this.usersPager.nextBy(v => v.setCount(dtos.total));
@ -77,7 +75,7 @@ export class UsersState {
public updateUser(user: UserDto, request: CreateUserDto): Observable<any> {
return this.usersService.putUser(user.id, request)
.do(() => {
this.dialogs.notify(Notification.info('User saved successsfull'));
this.dialogs.notifyInfo('User saved successsfull');
this.replaceUser(user.update(request.email, request.displayName));
});
@ -85,7 +83,7 @@ export class UsersState {
public lockUser(user: UserDto): Observable<any> {
return this.usersService.lockUser(user.id)
.catch(error => this.notifyError(error))
.catch(error => this.dialogs.notifyError(error))
.do(() => {
this.replaceUser(user.lock());
});
@ -93,7 +91,7 @@ export class UsersState {
public unlockUser(user: UserDto): Observable<any> {
return this.usersService.unlockUser(user.id)
.catch(error => this.notifyError(error))
.catch(error => this.dialogs.notifyError(error))
.do(() => {
this.replaceUser(user.unlock());
});
@ -118,7 +116,7 @@ export class UsersState {
return this.loadUsers();
}
public trackBy(index: number, user: UserDto): any {
public trackByUser(index: number, user: UserDto): any {
return user.id;
}
@ -127,14 +125,4 @@ export class UsersState {
this.selectedUser.nextBy(v => v !== null && v.id === user.id ? user : v);
}
private notifyError(error: string | ErrorDto) {
if (error instanceof ErrorDto) {
this.dialogs.notify(Notification.error(error.displayMessage));
} else {
this.dialogs.notify(Notification.error(error));
}
return Observable.throw(error);
}
}

40
src/Squidex/app/features/schemas/state/schemas.state.ts

@ -17,10 +17,8 @@ import {
CreateSchemaDto,
DateTime,
DialogService,
ErrorDto,
FieldDto,
ImmutableArray,
Notification,
SchemaDto,
SchemaDetailsDto,
SchemasService,
@ -73,7 +71,7 @@ export class SchemasState {
public load(): Observable<any> {
return this.schemasService.getSchemas(this.app)
.catch(error => this.notifyError(error))
.catch(error => this.dialogs.notifyError(error))
.do(dtos => {
this.schemasItems.nextBy(v => ImmutableArray.of(dtos));
});
@ -95,7 +93,7 @@ export class SchemasState {
public publish(schema: SchemaDto): Observable<any> {
return this.schemasService.publishSchema(this.app, schema.name, schema.version)
.catch(error => this.notifyError(error))
.catch(error => this.dialogs.notifyError(error))
.do(dto => {
this.replaceSchema(schema.publish(this.user, dto.version));
});
@ -103,7 +101,7 @@ export class SchemasState {
public unpublish(schema: SchemaDto): Observable<any> {
return this.schemasService.unpublishSchema(this.app, schema.name, schema.version)
.catch(error => this.notifyError(error))
.catch(error => this.dialogs.notifyError(error))
.do(dto => {
this.replaceSchema(schema.unpublish(this.user, dto.version));
});
@ -111,7 +109,7 @@ export class SchemasState {
public enableField(schema: SchemaDetailsDto, field: FieldDto): Observable<any> {
return this.schemasService.enableField(this.app, schema.name, field.fieldId, schema.version)
.catch(error => this.notifyError(error))
.catch(error => this.dialogs.notifyError(error))
.do(dto => {
this.replaceSchema(schema.updateField(field.enable(), this.user, dto.version));
});
@ -119,7 +117,7 @@ export class SchemasState {
public disableField(schema: SchemaDetailsDto, field: FieldDto): Observable<any> {
return this.schemasService.disableField(this.app, schema.name, field.fieldId, schema.version)
.catch(error => this.notifyError(error))
.catch(error => this.dialogs.notifyError(error))
.do(dto => {
this.replaceSchema(schema.updateField(field.disable(), this.user, dto.version));
});
@ -127,7 +125,7 @@ export class SchemasState {
public lockField(schema: SchemaDetailsDto, field: FieldDto): Observable<any> {
return this.schemasService.lockField(this.app, schema.name, field.fieldId, schema.version)
.catch(error => this.notifyError(error))
.catch(error => this.dialogs.notifyError(error))
.do(dto => {
this.replaceSchema(schema.updateField(field.lock(), this.user, dto.version));
});
@ -135,7 +133,7 @@ export class SchemasState {
public showField(schema: SchemaDetailsDto, field: FieldDto): Observable<any> {
return this.schemasService.showField(this.app, schema.name, field.fieldId, schema.version)
.catch(error => this.notifyError(error))
.catch(error => this.dialogs.notifyError(error))
.do(dto => {
this.replaceSchema(schema.updateField(field.show(), this.user, dto.version));
});
@ -143,7 +141,7 @@ export class SchemasState {
public hideField(schema: SchemaDetailsDto, field: FieldDto): Observable<any> {
return this.schemasService.hideField(this.app, schema.name, field.fieldId, schema.version)
.catch(error => this.notifyError(error))
.catch(error => this.dialogs.notifyError(error))
.do(dto => {
this.replaceSchema(schema.updateField(field.hide(), this.user, dto.version));
});
@ -151,7 +149,7 @@ export class SchemasState {
public deleteField(schema: SchemaDetailsDto, field: FieldDto): Observable<any> {
return this.schemasService.deleteField(this.app, schema.name, field.fieldId, schema.version)
.catch(error => this.notifyError(error))
.catch(error => this.dialogs.notifyError(error))
.do(dto => {
this.replaceSchema(schema.removeField(field, this.user, dto.version));
});
@ -159,7 +157,7 @@ export class SchemasState {
public sortFields(schema: SchemaDetailsDto, fields: FieldDto[]): Observable<any> {
return this.schemasService.putFieldOrdering(this.app, schema.name, fields.map(t => t.fieldId), schema.version)
.catch(error => this.notifyError(error))
.catch(error => this.dialogs.notifyError(error))
.do(dto => {
this.replaceSchema(schema.replaceFields(fields, this.user, dto.version));
});
@ -167,7 +165,7 @@ export class SchemasState {
public updateField(schema: SchemaDetailsDto, field: FieldDto, request: UpdateFieldDto): Observable<any> {
return this.schemasService.putField(this.app, schema.name, field.fieldId, request, schema.version)
.catch(error => this.notifyError(error))
.catch(error => this.dialogs.notifyError(error))
.do(dto => {
this.replaceSchema(schema.updateField(field.update(request.properties), this.user, dto.version));
});
@ -175,7 +173,7 @@ export class SchemasState {
public configureScripts(schema: SchemaDetailsDto, request: UpdateSchemaScriptsDto): Observable<any> {
return this.schemasService.putSchemaScripts(this.app, schema.name, request, schema.version)
.catch(error => this.notifyError(error))
.catch(error => this.dialogs.notifyError(error))
.do(dto => {
this.replaceSchema(schema.configureScripts(request, this.user, dto.version));
});
@ -183,7 +181,7 @@ export class SchemasState {
public update(schema: SchemaDetailsDto, request: UpdateSchemaDto): Observable<any> {
return this.schemasService.putSchema(this.app, schema.name, request, schema.version)
.catch(error => this.notifyError(error))
.catch(error => this.dialogs.notifyError(error))
.do(dto => {
this.replaceSchema(schema.update(request, this.user, dto.version));
});
@ -191,7 +189,7 @@ export class SchemasState {
public delete(schema: SchemaDto): Observable<any> {
return this.schemasService.deleteSchema(this.app, schema.name, schema.version)
.catch(error => this.notifyError(error))
.catch(error => this.dialogs.notifyError(error))
.do(dto => {
this.schemasItems.nextBy(v => v.filter(s => s.id !== schema.id));
});
@ -210,14 +208,4 @@ export class SchemasState {
public trackByField(index: number, field: FieldDto): any {
return field.fieldId;
}
private notifyError(error: string | ErrorDto) {
if (error instanceof ErrorDto) {
this.dialogs.notify(Notification.error(error.displayMessage));
} else {
this.dialogs.notify(Notification.error(error));
}
return Observable.throw(error);
}
}

60
src/Squidex/app/framework/angular/http-extensions-impl.ts

@ -8,65 +8,9 @@
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Version } from './../utils/version';
import { ErrorDto } from './../utils/error';
export class Versioned<T> {
constructor(
public readonly version: Version,
public readonly payload: T
) {
}
}
function formatMessage(message: string, details?: string[]) {
const appendLast = (row: string, char: string) => {
const last = row[row.length - 1];
if (last !== char) {
return row + char;
} else {
return row;
}
};
const removeLast = (row: string, char: string) => {
const last = row[row.length - 1];
if (last === char) {
return row.substr(0, row.length - 1);
} else {
return row;
}
};
if (details && details.length > 1) {
let result = appendLast(message, '.') + '<ul>';
for (let detail of details) {
result += `<li>${appendLast(detail, '.')}</li>`;
}
result = result + '</ul>';
return result;
} else if (details && details.length === 1) {
return `${appendLast(removeLast(message, '.'), ':')} ${appendLast(details[0], '.')}`;
} else {
return appendLast(message, '.');
}
}
export class ErrorDto {
public readonly displayMessage: string;
constructor(
public readonly statusCode: number,
public readonly message: string,
public readonly details: string[] = []
) {
this.displayMessage = formatMessage(message, details);
}
}
import { Version, Versioned } from './../utils/version';
export module HTTP {
export function getVersioned<T>(http: HttpClient, url: string, version?: Version): Observable<Versioned<HttpResponse<T>>> {

1
src/Squidex/app/framework/declarations.ts

@ -67,6 +67,7 @@ export * from './services/title.service';
export * from './utils/date-helper';
export * from './utils/date-time';
export * from './utils/duration';
export * from './utils/error';
export * from './utils/immutable-array';
export * from './utils/math-helper';
export * from './utils/modal-view';

16
src/Squidex/app/framework/services/dialog.service.ts

@ -8,6 +8,8 @@
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { ErrorDto } from './../utils/error';
export const DialogServiceFactory = () => {
return new DialogService();
};
@ -61,6 +63,20 @@ export class DialogService {
return this.notificationsStream$;
}
public notifyError(error: string | ErrorDto) {
if (error instanceof ErrorDto) {
this.notify(Notification.error(error.displayMessage));
} else {
this.notify(Notification.error(error));
}
return Observable.throw(error);
}
public notifyInfo(text: string) {
this.notificationsStream$.next(Notification.info(text));
}
public notify(notification: Notification) {
this.notificationsStream$.next(notification);
}

40
src/Squidex/app/framework/utils/error.spec.ts

@ -0,0 +1,40 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { ErrorDto } from './../';
describe('ErrorDto', () => {
it('Should create simple message when no details are specified.', () => {
const error = new ErrorDto(500, 'Error Message.');
expect(error.displayMessage).toBe('Error Message.');
});
it('Should append dot to message', () => {
const error = new ErrorDto(500, 'Error Message');
expect(error.displayMessage).toBe('Error Message.');
});
it('Should create simple message when detail has one item', () => {
const error = new ErrorDto(500, 'Error Message.', ['Detail Message.']);
expect(error.displayMessage).toBe('Error Message: Detail Message.');
});
it('Should create append do to simple message when detail has one item', () => {
const error = new ErrorDto(500, 'Error Message', ['Detail Message']);
expect(error.displayMessage).toBe('Error Message: Detail Message.');
});
it('Should create html list when error has more items.', () => {
const error = new ErrorDto(500, 'Error Message', ['Detail1.', 'Detail2.']);
expect(error.displayMessage).toBe('Error Message.<ul><li>Detail1.</li><li>Detail2.</li></ul>');
});
});

57
src/Squidex/app/framework/utils/error.ts

@ -0,0 +1,57 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
export class ErrorDto {
public readonly displayMessage: string;
constructor(
public readonly statusCode: number,
public readonly message: string,
public readonly details: string[] = []
) {
this.displayMessage = formatMessage(message, details);
}
}
function formatMessage(message: string, details?: string[]) {
const appendLast = (row: string, char: string) => {
const last = row[row.length - 1];
if (last !== char) {
return row + char;
} else {
return row;
}
};
const removeLast = (row: string, char: string) => {
const last = row[row.length - 1];
if (last === char) {
return row.substr(0, row.length - 1);
} else {
return row;
}
};
if (details && details.length > 1) {
let result = appendLast(message, '.') + '<ul>';
for (let detail of details) {
result += `<li>${appendLast(detail, '.')}</li>`;
}
result = result + '</ul>';
return result;
} else if (details && details.length === 1) {
return `${appendLast(removeLast(message, '.'), ':')} ${appendLast(details[0], '.')}`;
} else {
return appendLast(message, '.');
}
}

11
src/Squidex/app/framework/utils/version.spec.ts

@ -5,7 +5,7 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { Version } from './../';
import { Version, Versioned } from './../';
describe('Version', () => {
it('should initialize with init value', () => {
@ -13,4 +13,13 @@ describe('Version', () => {
expect(version.value).toBe('1.0');
});
});
describe('Versioned', () => {
it('should initialize with version and payload', () => {
const versioned = new Versioned<number>(new Version('1.0'), 123);
expect(versioned.version.value).toBe('1.0');
expect(versioned.payload).toBe(123);
});
});

8
src/Squidex/app/framework/utils/version.ts

@ -10,4 +10,12 @@ export class Version {
public readonly value: string
) {
}
}
export class Versioned<T> {
constructor(
public readonly version: Version,
public readonly payload: T
) {
}
}
Loading…
Cancel
Save