mirror of https://github.com/Squidex/squidex.git
24 changed files with 160 additions and 429 deletions
@ -1,9 +1,13 @@ |
|||
<main> |
|||
<router-outlet (activate)="isLoaded = true"> |
|||
<div class="loading" *ngIf="!isLoaded"> |
|||
<img src="/images/loader.gif" /> |
|||
<sqx-root-view> |
|||
<sqx-dialog-renderer> |
|||
<router-outlet (activate)="isLoaded = true"> |
|||
<div class="loading" *ngIf="!isLoaded"> |
|||
<img src="/images/loader.gif" /> |
|||
|
|||
<div>Loading Squidex</div> |
|||
</div> |
|||
</router-outlet> |
|||
<div>Loading Squidex</div> |
|||
</div> |
|||
</router-outlet> |
|||
</sqx-dialog-renderer> |
|||
</sqx-root-view> |
|||
</main> |
|||
|
|||
@ -1,87 +0,0 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
/* |
|||
import { IMock, Mock } from 'typemoq'; |
|||
import { Observable } from 'rxjs'; |
|||
|
|||
import { UserManagementService } from 'shared'; |
|||
|
|||
import { ResolveUserGuard } from './resolve-user.guard'; |
|||
import { RouterMockup } from './router-mockup'; |
|||
|
|||
describe('ResolveUserGuard', () => { |
|||
const route = { |
|||
params: {}, |
|||
parent: { |
|||
params: { |
|||
userId: 'my-user' |
|||
} |
|||
} |
|||
}; |
|||
|
|||
let usersService: IMock<UserManagementService>; |
|||
|
|||
beforeEach(() => { |
|||
usersService = Mock.ofType(UserManagementService); |
|||
}); |
|||
|
|||
it('should throw if route does not contain parameter', () => { |
|||
const guard = new ResolveUserGuard(usersService.object, <any>new RouterMockup()); |
|||
|
|||
expect(() => guard.resolve(<any>{ params: {} }, <any>{})).toThrow('Route must contain user id.'); |
|||
}); |
|||
|
|||
it('should navigate to 404 page if user is not found', (done) => { |
|||
usersService.setup(x => x.getUser('my-user')) |
|||
.returns(() => Observable.of(null!)); |
|||
const router = new RouterMockup(); |
|||
|
|||
const guard = new ResolveUserGuard(usersService.object, <any>router); |
|||
|
|||
guard.resolve(<any>route, <any>{}) |
|||
.subscribe(result => { |
|||
expect(result).toBeFalsy(); |
|||
expect(router.lastNavigation).toEqual(['/404']); |
|||
|
|||
done(); |
|||
}); |
|||
}); |
|||
|
|||
it('should navigate to 404 page if user loading fails', (done) => { |
|||
usersService.setup(x => x.getUser('my-user')) |
|||
.returns(() => Observable.throw(null!)); |
|||
const router = new RouterMockup(); |
|||
|
|||
const guard = new ResolveUserGuard(usersService.object, <any>router); |
|||
|
|||
guard.resolve(<any>route, <any>{}) |
|||
.subscribe(result => { |
|||
expect(result).toBeFalsy(); |
|||
expect(router.lastNavigation).toEqual(['/404']); |
|||
|
|||
done(); |
|||
}); |
|||
}); |
|||
|
|||
it('should return user if loading succeeded', (done) => { |
|||
const user: any = {}; |
|||
|
|||
usersService.setup(x => x.getUser('my-user')) |
|||
.returns(() => Observable.of(user)); |
|||
const router = new RouterMockup(); |
|||
|
|||
const guard = new ResolveUserGuard(usersService.object, <any>router); |
|||
|
|||
guard.resolve(<any>route, <any>{}) |
|||
.subscribe(result => { |
|||
expect(result).toBe(user); |
|||
|
|||
done(); |
|||
}); |
|||
}); |
|||
}); |
|||
*/ |
|||
@ -1,24 +0,0 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { Injectable } from '@angular/core'; |
|||
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router'; |
|||
import { Observable } from 'rxjs'; |
|||
|
|||
import { UsersState } from './../state/users.state'; |
|||
|
|||
@Injectable() |
|||
export class UnsetUserGuard implements CanActivate { |
|||
constructor( |
|||
private readonly usersState: UsersState |
|||
) { |
|||
} |
|||
|
|||
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> { |
|||
return this.usersState.selectUser(null).map(u => u === null); |
|||
} |
|||
} |
|||
@ -1,44 +0,0 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { Injectable } from '@angular/core'; |
|||
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router'; |
|||
import { Observable } from 'rxjs'; |
|||
|
|||
import { allParams } from 'framework'; |
|||
|
|||
import { UsersState } from './../state/users.state'; |
|||
|
|||
@Injectable() |
|||
export class UserMustExistGuard implements CanActivate { |
|||
constructor( |
|||
private readonly usersState: UsersState, |
|||
private readonly router: Router |
|||
) { |
|||
} |
|||
|
|||
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> { |
|||
const params = allParams(route); |
|||
|
|||
const userId = params['userId']; |
|||
|
|||
if (!userId) { |
|||
throw 'Route must contain user id.'; |
|||
} |
|||
|
|||
const result = |
|||
this.usersState.selectUser(userId) |
|||
.do(dto => { |
|||
if (!dto) { |
|||
this.router.navigate(['/404']); |
|||
} |
|||
}) |
|||
.map(u => u !== null); |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
@ -1,36 +1,51 @@ |
|||
<form [formGroup]="createForm" (ngSubmit)="createSchema()"> |
|||
<div *ngIf="createFormError"> |
|||
<div class="form-alert form-alert-error" [innerHTML]="createFormError"></div> |
|||
</div> |
|||
|
|||
<div class="form-group"> |
|||
<label for="schemaName">Name</label> |
|||
|
|||
<sqx-control-errors for="name" submitOnly="true" [submitted]="createFormSubmitted"></sqx-control-errors> |
|||
<div class="modal-dialog"> |
|||
<div class="modal-content"> |
|||
<form [formGroup]="createForm" (ngSubmit)="createSchema()"> |
|||
<div class="modal-header"> |
|||
<h4 class="modal-title" *ngIf="import">Clone Schema</h4> |
|||
<h4 class="modal-title" *ngIf="!import">Create Schema</h4> |
|||
|
|||
<input type="text" class="form-control" id="schemaName" formControlName="name" autocomplete="off" sqxLowerCaseInput sqxFocusOnInit /> |
|||
|
|||
<small class="form-text text-muted"> |
|||
The schema name becomes part of the api url,<br /> e.g {{apiUrl.buildUrl("api/content/")}}{{ctx.appName}}/<b>{{schemaName | async}}</b>/. |
|||
</small> |
|||
<small class="form-text text-muted"> |
|||
It must contain lower case letters (a-z), numbers and dashes only, and cannot be longer than 40 characters. The name cannot be changed later. |
|||
</small> |
|||
</div> |
|||
|
|||
<div class="form-group clearfix"> |
|||
<button type="reset" class="float-left btn btn-secondary" (click)="cancel()">Cancel</button> |
|||
<button type="submit" class="float-right btn btn-success">Create</button> |
|||
</div> |
|||
<button type="button" class="close" data-dismiss="modal" aria-label="Close" (click)="complete()"> |
|||
<span aria-hidden="true">×</span> |
|||
</button> |
|||
</div> |
|||
|
|||
<div> |
|||
<button class="btn btn-sm btn-link" (click)="toggleImport()" [class.hidden]="showImport"> |
|||
Import schema |
|||
</button> |
|||
<button class="btn btn-sm btn-link" (click)="toggleImport()" [class.hidden]="!showImport"> |
|||
Hide |
|||
</button> |
|||
<div class="modal-body"> |
|||
<div *ngIf="createFormError"> |
|||
<div class="form-alert form-alert-error" [innerHTML]="createFormError"></div> |
|||
</div> |
|||
|
|||
<div class="form-group"> |
|||
<label for="schemaName">Name</label> |
|||
|
|||
<sqx-control-errors for="name" submitOnly="true" [submitted]="createFormSubmitted"></sqx-control-errors> |
|||
|
|||
<input type="text" class="form-control" id="schemaName" formControlName="name" autocomplete="off" sqxLowerCaseInput sqxFocusOnInit /> |
|||
|
|||
<small class="form-text text-muted"> |
|||
The schema name becomes part of the api url,<br /> e.g {{apiUrl.buildUrl("api/content/")}}{{ctx.appName}}/<b>{{schemaName | async}}</b>/. |
|||
</small> |
|||
<small class="form-text text-muted"> |
|||
It must contain lower case letters (a-z), numbers and dashes only, and cannot be longer than 40 characters. The name cannot be changed later. |
|||
</small> |
|||
</div> |
|||
|
|||
<sqx-json-editor *ngIf="showImport" formControlName="import"></sqx-json-editor> |
|||
<div class="form-group clearfix"> |
|||
<button type="reset" class="float-left btn btn-secondary" (click)="complete()">Cancel</button> |
|||
<button type="submit" class="float-right btn btn-success">Create</button> |
|||
</div> |
|||
|
|||
<div> |
|||
<button class="btn btn-sm btn-link" (click)="toggleImport()" [class.hidden]="showImport"> |
|||
Import schema |
|||
</button> |
|||
<button class="btn btn-sm btn-link" (click)="toggleImport()" [class.hidden]="!showImport"> |
|||
Hide |
|||
</button> |
|||
|
|||
<sqx-json-editor *ngIf="showImport" formControlName="import"></sqx-json-editor> |
|||
</div> |
|||
</div> |
|||
</form> |
|||
</div> |
|||
</form> |
|||
</div> |
|||
@ -0,0 +1,21 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { Component, ViewChild, ViewContainerRef } from '@angular/core'; |
|||
|
|||
@Component({ |
|||
selector: 'sqx-root-view', |
|||
template: ` |
|||
<div #element></div> |
|||
|
|||
<ng-content></ng-content> |
|||
` |
|||
}) |
|||
export class RootViewComponent { |
|||
@ViewChild('element') |
|||
public viewContainer: ViewContainerRef; |
|||
} |
|||
@ -1,27 +0,0 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { RootViewDirective } from './../'; |
|||
|
|||
/* tslint:disable:no-unused-expression */ |
|||
|
|||
describe('RootViewDirective', () => { |
|||
it('should call init of service in ctor', () => { |
|||
let viewRef = {}; |
|||
let viewRefPassed: any = null; |
|||
|
|||
const service = { |
|||
init: (ref: any) => { |
|||
viewRefPassed = ref; |
|||
} |
|||
}; |
|||
|
|||
new RootViewDirective(<any>viewRef, <any>service); |
|||
|
|||
expect(viewRef).toBe(viewRefPassed); |
|||
}); |
|||
}); |
|||
@ -1,19 +0,0 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { Directive, ViewContainerRef } from '@angular/core'; |
|||
|
|||
import { RootViewService } from './../services/root-view.service'; |
|||
|
|||
@Directive({ |
|||
selector: '[sqxRootView]' |
|||
}) |
|||
export class RootViewDirective { |
|||
constructor(public viewContainer: ViewContainerRef, rootViewService: RootViewService) { |
|||
rootViewService.init(viewContainer); |
|||
} |
|||
} |
|||
@ -1,43 +0,0 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { RootViewService } from './../'; |
|||
|
|||
describe('RootViewService', () => { |
|||
const rootViewService = new RootViewService(); |
|||
|
|||
it('should call view when clearing element', () => { |
|||
let isClearCalled = false; |
|||
|
|||
const viewRef = { |
|||
clear: () => { |
|||
isClearCalled = true; |
|||
} |
|||
}; |
|||
|
|||
rootViewService.init(<any>viewRef); |
|||
rootViewService.clear(); |
|||
|
|||
expect(isClearCalled).toBeTruthy(); |
|||
}); |
|||
|
|||
it('should call view when creating element', () => { |
|||
const view = {}; |
|||
|
|||
const viewRef = { |
|||
createEmbeddedView: () => { |
|||
return view; |
|||
} |
|||
}; |
|||
|
|||
rootViewService.init(<any>viewRef); |
|||
|
|||
const result = rootViewService.createEmbeddedView(<any>{}); |
|||
|
|||
expect(result).toBe(view); |
|||
}); |
|||
}); |
|||
@ -1,25 +0,0 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { EmbeddedViewRef, Injectable, TemplateRef, ViewContainerRef } from '@angular/core'; |
|||
|
|||
@Injectable() |
|||
export class RootViewService { |
|||
private rootView: ViewContainerRef; |
|||
|
|||
public init(view: ViewContainerRef) { |
|||
this.rootView = view; |
|||
} |
|||
|
|||
public createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, index?: number): EmbeddedViewRef<C> { |
|||
return this.rootView.createEmbeddedView(templateRef, context, index); |
|||
} |
|||
|
|||
public clear() { |
|||
this.rootView.clear(); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue