Browse Source

Restructuring

pull/1/head
Sebastian 9 years ago
parent
commit
81e33bcdd7
  1. 4
      src/Squidex/Modules/Api/Apps/AppController.cs
  2. 10
      src/Squidex/Pipeline/CommandHandlers/EnrichWithSubjectHandler.cs
  3. 9
      src/Squidex/app-config/webpack.common.js
  4. 20
      src/Squidex/app/app.component.html
  5. 10
      src/Squidex/app/app.component.spec.ts
  6. 5
      src/Squidex/app/app.component.ts
  7. 4
      src/Squidex/app/app.module.ts
  8. 32
      src/Squidex/app/app.routes.ts
  9. 1
      src/Squidex/app/components/auth/logout-page.component.ts
  10. 3
      src/Squidex/app/components/index.ts
  11. 1
      src/Squidex/app/components/internal/app/app-area.component.html
  12. 14
      src/Squidex/app/components/internal/app/app-area.component.ts
  13. 0
      src/Squidex/app/components/internal/app/dashboard/dashboard-page.component.html
  14. 14
      src/Squidex/app/components/internal/app/dashboard/dashboard-page.component.ts
  15. 4
      src/Squidex/app/components/internal/apps/apps-page.component.html
  16. 4
      src/Squidex/app/components/internal/apps/apps-page.component.scss
  17. 2
      src/Squidex/app/components/internal/apps/apps-page.component.ts
  18. 12
      src/Squidex/app/components/internal/declarations.ts
  19. 2
      src/Squidex/app/components/internal/index.ts
  20. 17
      src/Squidex/app/components/internal/internal-area.component.html
  21. 2
      src/Squidex/app/components/internal/internal-area.component.scss
  22. 35
      src/Squidex/app/components/internal/internal-area.component.ts
  23. 32
      src/Squidex/app/components/internal/internal.module.ts
  24. 8
      src/Squidex/app/components/layout/app-form.component.html
  25. 59
      src/Squidex/app/components/layout/app-form.component.ts
  26. 12
      src/Squidex/app/components/layout/apps-menu-list.component.html
  27. 19
      src/Squidex/app/components/layout/apps-menu-list.component.scss
  28. 21
      src/Squidex/app/components/layout/apps-menu-list.component.ts
  29. 15
      src/Squidex/app/components/layout/apps-menu.component.html
  30. 4
      src/Squidex/app/components/layout/apps-menu.component.scss
  31. 11
      src/Squidex/app/components/layout/apps-menu.component.ts
  32. 2
      src/Squidex/app/components/layout/declarations.ts
  33. 5
      src/Squidex/app/components/layout/layout.module.ts
  34. 2
      src/Squidex/app/components/public/declarations.ts
  35. 10
      src/Squidex/app/components/public/index.ts
  36. 0
      src/Squidex/app/components/public/not-found-page.component.html
  37. 0
      src/Squidex/app/components/public/not-found-page.component.ts
  38. 10
      src/Squidex/app/components/public/public.module.ts
  39. 11
      src/Squidex/app/shared/services/apps.service.ts
  40. 8
      src/Squidex/app/shared/services/auth.service.ts
  41. 10
      src/Squidex/app/theme/_bootstrap.scss
  42. 6
      src/Squidex/tsconfig.json
  43. 7
      src/Squidex/wwwroot/index.html

4
src/Squidex/Modules/Api/Apps/AppController.cs

@ -9,12 +9,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Squidex.Infrastructure.CQRS.Commands; using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Reflection;
using Squidex.Infrastructure.Security;
using Squidex.Modules.Api.Apps.Models; using Squidex.Modules.Api.Apps.Models;
using Squidex.Pipeline; using Squidex.Pipeline;
using Squidex.Read.Apps.Repositories; using Squidex.Read.Apps.Repositories;
@ -38,7 +38,7 @@ namespace Squidex.Modules.Api.Apps
[Route("apps/")] [Route("apps/")]
public async Task<List<ListAppDto>> Query() public async Task<List<ListAppDto>> Query()
{ {
var schemas = await appRepository.QueryAllAsync(HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value); var schemas = await appRepository.QueryAllAsync(HttpContext.User.OpenIdSubject());
return schemas.Select(s => SimpleMapper.Map(s, new ListAppDto())).ToList(); return schemas.Select(s => SimpleMapper.Map(s, new ListAppDto())).ToList();
} }

10
src/Squidex/Pipeline/CommandHandlers/EnrichWithSubjectHandler.cs

@ -7,10 +7,10 @@
// ========================================================================== // ==========================================================================
using System.Security; using System.Security;
using System.Security.Claims;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Squidex.Infrastructure.CQRS.Commands; using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Infrastructure.Security;
// ReSharper disable InvertIf // ReSharper disable InvertIf
namespace Squidex.Pipeline.CommandHandlers namespace Squidex.Pipeline.CommandHandlers
@ -30,14 +30,14 @@ namespace Squidex.Pipeline.CommandHandlers
if (subjectCommand != null) if (subjectCommand != null)
{ {
var user = httpContextAccessor.HttpContext.User; var subjectId = httpContextAccessor.HttpContext.User.OpenIdSubject();
if (user?.FindFirst(ClaimTypes.NameIdentifier) == null) if (subjectId == null)
{ {
throw new SecurityException("No user available"); throw new SecurityException("No user with subject id available");
} }
subjectCommand.SubjectId = user.FindFirst(ClaimTypes.NameIdentifier).Value; subjectCommand.SubjectId = subjectId;
} }
return Task.FromResult(false); return Task.FromResult(false);

9
src/Squidex/app-config/webpack.common.js

@ -35,6 +35,11 @@ module.exports = {
root: [ root: [
helpers.root('app'), helpers.root('app'),
helpers.root('app-libs') helpers.root('app-libs')
],
moduleDirectories: [
"*",
"app/*",
"app/theme/*"
] ]
}, },
@ -77,7 +82,9 @@ module.exports = {
} }
] ]
}, },
sassLoader: {
includePaths: [helpers.root('app', 'theme')]
},
plugins: [ plugins: [
/** /**
* Plugin: CommonsChunkPlugin * Plugin: CommonsChunkPlugin

20
src/Squidex/app/app.component.html

@ -1,20 +1,6 @@
<nav class="navbar navbar-fixed-top navbar-dark bg-primary bg-faded"> <main>
<span class="navbar-brand"> <router-outlet (activate)="isLoaded = true">
<i class="icon-logo"></i> <div class="loading" *ngIf="!isLoaded">
</span>
<div class="float-xs-left apps-menu">
<sqx-apps-menu></sqx-apps-menu>
</div>
<div class="float-xs-left search-form">
<sqx-search-form></sqx-search-form>
</div>
</nav>
<main>
<router-outlet>
<div class="loading">
<img src="/images/loader.gif" /> <img src="/images/loader.gif" />
<div>Loading awesomeness</div> <div>Loading awesomeness</div>

10
src/Squidex/app/app.component.spec.ts

@ -3,10 +3,6 @@ import { TestBed } from '@angular/core/testing';
import { RouterModule, provideRoutes } from '@angular/router'; import { RouterModule, provideRoutes } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing'; import { RouterTestingModule } from '@angular/router/testing';
import { SqxLayoutModule } from './components/layout';
import { AppsStoreService } from './shared';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
describe('App', () => { describe('App', () => {
@ -17,12 +13,10 @@ describe('App', () => {
], ],
imports: [ imports: [
RouterModule, RouterModule,
RouterTestingModule, RouterTestingModule
SqxLayoutModule
], ],
providers: [ providers: [
provideRoutes([]), provideRoutes([])
{ provide: AppsStoreService, useValue: new AppsStoreService(null, null) }
] ]
}); });
}); });

5
src/Squidex/app/app.component.ts

@ -9,7 +9,8 @@ import * as Ng2 from '@angular/core';
@Ng2.Component({ @Ng2.Component({
selector: 'sqx-app', selector: 'sqx-app',
styles,
template template
}) })
export class AppComponent { } export class AppComponent {
public isLoaded = false;
}

4
src/Squidex/app/app.module.ts

@ -30,7 +30,8 @@ import {
import { import {
SqxAppModule, SqxAppModule,
SqxLayoutModule, SqxLayoutModule,
SqxLoginModule SqxLoginModule,
SqxPublicModule
} from './components'; } from './components';
import { SqxFrameworkModule } from './framework'; import { SqxFrameworkModule } from './framework';
@ -46,6 +47,7 @@ const baseUrl = window.location.protocol + '//' + window.location.host + '/';
SqxLayoutModule, SqxLayoutModule,
SqxLoginModule, SqxLoginModule,
SqxFrameworkModule, SqxFrameworkModule,
SqxPublicModule,
routing routing
], ],
declarations: [ declarations: [

32
src/Squidex/app/app.routes.ts

@ -10,6 +10,9 @@ import * as Ng2Router from '@angular/router';
import { import {
AppsPageComponent, AppsPageComponent,
AppAreaComponent,
DashboardComponent,
InternalAreaComponent,
LoginPageComponent, LoginPageComponent,
LogoutPageComponent, LogoutPageComponent,
NotFoundPageComponent NotFoundPageComponent
@ -22,13 +25,28 @@ import {
export const routes: Ng2Router.Routes = [ export const routes: Ng2Router.Routes = [
{ {
path: '', path: '',
redirectTo: 'apps', redirectTo: 'app', pathMatch: 'full'
pathMatch: 'full'
}, },
{ {
path: 'apps', path: 'app',
component: AppsPageComponent, component: InternalAreaComponent,
canActivate: [AuthGuard] canActivate: [AuthGuard],
children: [
{
path: '',
component: AppsPageComponent
},
{
path: ':appName',
component: AppAreaComponent,
children: [
{
path: '',
component: DashboardComponent
}
]
}
]
}, },
{ {
path: 'login', path: 'login',
@ -38,10 +56,6 @@ export const routes: Ng2Router.Routes = [
path: 'logout', path: 'logout',
component: LogoutPageComponent component: LogoutPageComponent
}, },
{
path: '404',
component: NotFoundPageComponent
},
{ {
path: '**', path: '**',
component: NotFoundPageComponent component: NotFoundPageComponent

1
src/Squidex/app/components/auth/logout-page.component.ts

@ -15,7 +15,6 @@ import { AuthService } from './../../shared';
template template
}) })
export class LogoutPageComponent implements Ng2.OnInit { export class LogoutPageComponent implements Ng2.OnInit {
constructor( constructor(
private readonly authService: AuthService, private readonly authService: AuthService,
private readonly router: Ng2Router.Router private readonly router: Ng2Router.Router

3
src/Squidex/app/components/index.ts

@ -5,6 +5,7 @@
* Copyright (c) Sebastian Stehle. All rights reserved * Copyright (c) Sebastian Stehle. All rights reserved
*/ */
export * from './apps';
export * from './auth'; export * from './auth';
export * from './internal';
export * from './layout'; export * from './layout';
export * from './public';

1
src/Squidex/app/components/internal/app/app-area.component.html

@ -0,0 +1 @@
<router-outlet></router-outlet>

14
src/Squidex/app/components/internal/app/app-area.component.ts

@ -0,0 +1,14 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import * as Ng2 from '@angular/core';
@Ng2.Component({
selector: 'sqx-app-area',
template
})
export class AppAreaComponent { }

0
src/Squidex/app/components/internal/app/dashboard/dashboard-page.component.html

14
src/Squidex/app/components/internal/app/dashboard/dashboard-page.component.ts

@ -0,0 +1,14 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import * as Ng2 from '@angular/core';
@Ng2.Component({
selector: 'sqx-dashboard-page',
template
})
export class DashboardComponent { }

4
src/Squidex/app/components/apps/apps-page.component.html → src/Squidex/app/components/internal/apps/apps-page.component.html

@ -19,8 +19,8 @@
<div class="modal-body"> <div class="modal-body">
<sqx-app-form <sqx-app-form
(onCreated)="modalDialog.hide()" (created)="modalDialog.hide()"
(onCancelled)="modalDialog.hide()"></sqx-app-form> (cancelled)="modalDialog.hide()"></sqx-app-form>
</div> </div>
</div> </div>
</div> </div>

4
src/Squidex/app/components/apps/apps-page.component.scss → src/Squidex/app/components/internal/apps/apps-page.component.scss

@ -1,5 +1,5 @@
@import '../../theme/_vars.scss'; @import '../../../theme/_vars.scss';
@import '../../theme/_mixins.scss'; @import '../../../theme/_mixins.scss';
content { content {
padding: 20px; padding: 20px;

2
src/Squidex/app/components/apps/apps-page.component.ts → src/Squidex/app/components/internal/apps/apps-page.component.ts

@ -11,7 +11,7 @@ import {
fadeAnimation, fadeAnimation,
ModalView, ModalView,
TitleService TitleService
} from './../../framework'; } from './../../../framework';
@Ng2.Component({ @Ng2.Component({
selector: 'sqx-apps-page', selector: 'sqx-apps-page',

12
src/Squidex/app/components/internal/declarations.ts

@ -0,0 +1,12 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
export * from './apps/apps-page.component';
export * from './app/app-area.component';
export * from './app/dashboard/dashboard-page.component';
export * from './internal-area.component';

2
src/Squidex/app/components/apps/index.ts → src/Squidex/app/components/internal/index.ts

@ -7,4 +7,4 @@
export * from './declarations'; export * from './declarations';
export * from './apps.module'; export * from './internal.module';

17
src/Squidex/app/components/internal/internal-area.component.html

@ -0,0 +1,17 @@
<nav class="navbar navbar-fixed-top navbar-dark bg-primary bg-faded">
<span class="navbar-brand">
<i class="icon-logo"></i>
</span>
<div class="float-xs-left apps-menu">
<sqx-apps-menu></sqx-apps-menu>
</div>
<div class="float-xs-left search-form">
<sqx-search-form></sqx-search-form>
</div>
</nav>
<main>
<router-outlet></router-outlet>
</main>

2
src/Squidex/app/app.component.scss → src/Squidex/app/components/internal/internal-area.component.scss

@ -1,4 +1,4 @@
@import 'theme/mixins.scss'; @import '../../theme/mixins.scss';
.navbar { .navbar {
@include box-shadow(0, 4px, 4px, 0.2px); @include box-shadow(0, 4px, 4px, 0.2px);

35
src/Squidex/app/components/internal/internal-area.component.ts

@ -0,0 +1,35 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import * as Ng2 from '@angular/core';
import {
fadeAnimation,
ModalView,
TitleService
} from './../../framework';
@Ng2.Component({
selector: 'sqx-internal-area',
styles,
template,
animations: [
fadeAnimation()
]
})
export class InternalAreaComponent implements Ng2.OnInit {
public modalDialog = new ModalView();
constructor(
private readonly title: TitleService
) {
}
public ngOnInit() {
this.title.setTitle('Apps');
}
}

32
src/Squidex/app/components/internal/internal.module.ts

@ -0,0 +1,32 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import * as Ng2 from '@angular/core';
import { SqxFrameworkModule } from './../../framework';
import { SqxLayoutModule } from './../layout';
import {
AppAreaComponent,
AppsPageComponent,
DashboardComponent,
InternalAreaComponent
} from './declarations';
@Ng2.NgModule({
imports: [
SqxFrameworkModule,
SqxLayoutModule
],
declarations: [
AppAreaComponent,
AppsPageComponent,
DashboardComponent,
InternalAreaComponent
]
})
export class SqxAppModule { }

8
src/Squidex/app/components/layout/app-form.component.html

@ -1,4 +1,10 @@
<form [formGroup]="createForm" (ngSubmit)="submit()"> <form [formGroup]="createForm" (ngSubmit)="submit()">
<div *ngIf="creationError | async" [@fade]>
<div class="form-error">
{{creationError | async}}
</div>
</div>
<div class="form-group"> <div class="form-group">
<label for="app-name">Name</label> <label for="app-name">Name</label>
@ -26,6 +32,6 @@
<div class="form-group"> <div class="form-group">
<button type="reset" class="btn btn-link" (click)="cancel()">Cancel</button> <button type="reset" class="btn btn-link" (click)="cancel()">Cancel</button>
<button type="submit" class="btn btn-success">Create</button> <button type="submit" class="btn btn-success" [disabled]="createForm.invalid">Create</button>
</div> </div>
</form> </form>

59
src/Squidex/app/components/layout/app-form.component.ts

@ -8,7 +8,7 @@
import * as Ng2 from '@angular/core'; import * as Ng2 from '@angular/core';
import * as Ng2Forms from '@angular/forms'; import * as Ng2Forms from '@angular/forms';
import { Observable } from 'rxjs'; import { BehaviorSubject } from 'rxjs';
import { fadeAnimation } from './../../framework'; import { fadeAnimation } from './../../framework';
@ -24,32 +24,18 @@ const FALLBACK_NAME = 'my-app';
fadeAnimation() fadeAnimation()
] ]
}) })
export class AppFormComponent implements Ng2.OnInit { export class AppFormComponent {
public createForm: Ng2Forms.FormGroup;
public appName: Observable<string>;
@Ng2.Input() @Ng2.Input()
public showClose = false; public showClose = false;
@Ng2.Output() @Ng2.Output()
public onCreated = new Ng2.EventEmitter(); public created = new Ng2.EventEmitter();
@Ng2.Output() @Ng2.Output()
public onCancelled = new Ng2.EventEmitter(); public cancelled = new Ng2.EventEmitter();
public creating = new Ng2.EventEmitter<boolean>();
public creationError = new Ng2.EventEmitter<any>();
constructor(
private readonly appsStore: AppsStoreService,
private readonly formBuilder: Ng2Forms.FormBuilder
) {
}
public ngOnInit() { public createForm =
this.createForm = this.formBuilder.group({ this.formBuilder.group({
name: ['', name: ['',
[ [
Ng2Forms.Validators.required, Ng2Forms.Validators.required,
@ -58,34 +44,49 @@ export class AppFormComponent implements Ng2.OnInit {
]] ]]
}); });
this.appName = this.createForm.controls['name'].valueChanges.map(name => name || FALLBACK_NAME).publishBehavior(FALLBACK_NAME).refCount(); public appName =
this.createForm.controls['name'].valueChanges.map(name => name || FALLBACK_NAME).publishBehavior(FALLBACK_NAME).refCount();
public creating =
new BehaviorSubject<boolean>(false);
public creationError =
new BehaviorSubject<string>('');
constructor(
private readonly appsStore: AppsStoreService,
private readonly formBuilder: Ng2Forms.FormBuilder
) {
} }
public submit() { public submit() {
this.createForm.markAsDirty();
if (this.createForm.valid) { if (this.createForm.valid) {
this.createForm.disable(); this.createForm.disable();
this.creating.emit(true); this.creating.next(true);
const dto = new AppCreateDto(this.createForm.controls['name'].value); const dto = new AppCreateDto(this.createForm.controls['name'].value);
this.appsStore.createApp(dto) this.appsStore.createApp(dto)
.finally(() => {
this.reset();
})
.subscribe(() => { .subscribe(() => {
this.onCreated.emit(); this.createForm.reset();
this.created.emit();
}, error => { }, error => {
this.creationError.emit(error); this.reset();
this.creationError.next(error);
}); });
} }
} }
private reset() { private reset() {
this.createForm.enable(); this.createForm.enable();
this.creating.emit(false); this.creating.next(false);
this.creationError.next(null);
} }
public cancel() { public cancel() {
this.onCancelled.emit(); this.reset();
this.cancelled.emit();
} }
} }

12
src/Squidex/app/components/layout/apps-menu-list.component.html

@ -0,0 +1,12 @@
<a class="dropdown-item all-apps" routerLink="/apps">
<span class="all-apps-text">All Apps</span>
<span class="all-apps-pill tag tag-pill tag-default">{{apps.length || 0}}</span>
</a>
<div class="dropdown-divider"></div>
<div *ngIf="apps && apps.length > 0">
<a class="dropdown-item" *ngFor="let app of apps" [routerLink]="['/app', app.name]">{{app.name}}</a>
<div class="dropdown-divider"></div>
</div>

19
src/Squidex/app/components/layout/apps-menu-list.component.scss

@ -0,0 +1,19 @@
@import '_vars.scss';
@import '_mixins.scss';
.all-apps {
& {
position: relative;
}
&-text {
font-weight: bold;
}
&-pill {
@include absolute(6px, 10px, auto, auto);
color: $accent-blue;
border: none;
background: $accent-blue-lighter;
}
}

21
src/Squidex/app/components/layout/apps-menu-list.component.ts

@ -0,0 +1,21 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import * as Ng2 from '@angular/core';
import { AppDto } from 'shared';
@Ng2.Component({
selector: 'sqx-apps-menu-list',
styles,
template
})
export class AppsMenuListComponent {
@Ng2.Input()
public apps: AppDto[];
}

15
src/Squidex/app/components/layout/apps-menu.component.html

@ -3,16 +3,7 @@
<span class="nav-link dropdown-toggle" id="app-name" (click)="modalMenu.toggle()">{{app | async}}</span> <span class="nav-link dropdown-toggle" id="app-name" (click)="modalMenu.toggle()">{{app | async}}</span>
<div class="dropdown-menu" [(sqxModalView)]="modalMenu" [@fade]="(modalMenu.isOpen | async)"> <div class="dropdown-menu" [(sqxModalView)]="modalMenu" [@fade]="(modalMenu.isOpen | async)">
<a class="dropdown-item all-apps" routerLink="/apps"> <sqx-apps-menu-list [apps]="apps | async"></sqx-apps-menu-list>
<span class="all-apps-text">All Apps</span>
<span class="all-apps-pill tag tag-pill tag-default">{{(apps | async).length}}</span>
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" *ngFor="let app of (apps | async)">{{app.name}}</a>
<div class="dropdown-divider"></div>
<div class="drodown-button"> <div class="drodown-button">
<button class="btn btn-block btn-success" id="app-create" (click)="createApp()"><i class="icon-plus"></i> Create New App</button> <button class="btn btn-block btn-success" id="app-create" (click)="createApp()"><i class="icon-plus"></i> Create New App</button>
@ -34,8 +25,8 @@
<div class="modal-body"> <div class="modal-body">
<sqx-app-form <sqx-app-form
(onCreated)="modalDialog.hide()" (created)="modalDialog.hide()"
(onCancelled)="modalDialog.hide()"></sqx-app-form> (cancelled)="modalDialog.hide()"></sqx-app-form>
</div> </div>
</div> </div>
</div> </div>

4
src/Squidex/app/components/layout/apps-menu.component.scss

@ -1,5 +1,5 @@
@import '../../theme/_vars.scss'; @import '_vars.scss';
@import '../../theme/_mixins.scss'; @import '_mixins.scss';
.navbar-dark .navbar-nav .nav-link { .navbar-dark .navbar-nav .nav-link {
color: white; color: white;

11
src/Squidex/app/components/layout/apps-menu.component.ts

@ -8,9 +8,9 @@
import * as Ng2 from '@angular/core'; import * as Ng2 from '@angular/core';
import * as Ng2Router from '@angular/router'; import * as Ng2Router from '@angular/router';
import { AppsStoreService } from './../../shared'; import { AppsStoreService } from 'shared';
import { fadeAnimation, ModalView } from './../../framework'; import { fadeAnimation, ModalView } from 'framework';
const FALLBACK_NAME = 'Apps Overview'; const FALLBACK_NAME = 'Apps Overview';
@ -30,10 +30,15 @@ export class AppsMenuComponent {
this.appsStore.apps.map(a => a || []); this.appsStore.apps.map(a => a || []);
public app = public app =
this.route.params.map((p: any) => p.app || FALLBACK_NAME); this.router.events.switchMap(() => {
return this.router.routerState.root.params.map(p => {
return p['my_named'] || FALLBACK_NAME;
} );
});
constructor( constructor(
private readonly appsStore: AppsStoreService, private readonly appsStore: AppsStoreService,
private readonly router: Ng2Router.Router,
private readonly route: Ng2Router.ActivatedRoute private readonly route: Ng2Router.ActivatedRoute
) { ) {
} }

2
src/Squidex/app/components/layout/declarations.ts

@ -7,5 +7,5 @@
export * from './app-form.component'; export * from './app-form.component';
export * from './apps-menu.component'; export * from './apps-menu.component';
export * from './not-found-page.component'; export * from './apps-menu-list.component';
export * from './search-form.component'; export * from './search-form.component';

5
src/Squidex/app/components/layout/layout.module.ts

@ -12,7 +12,7 @@ import { SqxFrameworkModule } from './../../framework';
import { import {
AppFormComponent, AppFormComponent,
AppsMenuComponent, AppsMenuComponent,
NotFoundPageComponent, AppsMenuListComponent,
SearchFormComponent SearchFormComponent
} from './declarations'; } from './declarations';
@ -23,12 +23,13 @@ import {
declarations: [ declarations: [
AppFormComponent, AppFormComponent,
AppsMenuComponent, AppsMenuComponent,
NotFoundPageComponent, AppsMenuListComponent,
SearchFormComponent, SearchFormComponent,
], ],
exports: [ exports: [
AppFormComponent, AppFormComponent,
AppsMenuComponent, AppsMenuComponent,
AppsMenuListComponent,
SearchFormComponent, SearchFormComponent,
] ]
}) })

2
src/Squidex/app/components/apps/declarations.ts → src/Squidex/app/components/public/declarations.ts

@ -5,4 +5,4 @@
* Copyright (c) Sebastian Stehle. All rights reserved * Copyright (c) Sebastian Stehle. All rights reserved
*/ */
export * from './apps-page.component'; export * from './not-found-page.component';

10
src/Squidex/app/components/public/index.ts

@ -0,0 +1,10 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
export * from './declarations';
export * from './public.module';

0
src/Squidex/app/components/layout/not-found-page.component.html → src/Squidex/app/components/public/not-found-page.component.html

0
src/Squidex/app/components/layout/not-found-page.component.ts → src/Squidex/app/components/public/not-found-page.component.ts

10
src/Squidex/app/components/apps/apps.module.ts → src/Squidex/app/components/public/public.module.ts

@ -8,19 +8,17 @@
import * as Ng2 from '@angular/core'; import * as Ng2 from '@angular/core';
import { SqxFrameworkModule } from './../../framework'; import { SqxFrameworkModule } from './../../framework';
import { SqxLayoutModule } from './../layout';
import { import {
AppsPageComponent NotFoundPageComponent,
} from './declarations'; } from './declarations';
@Ng2.NgModule({ @Ng2.NgModule({
imports: [ imports: [
SqxFrameworkModule, SqxFrameworkModule
SqxLayoutModule
], ],
declarations: [ declarations: [
AppsPageComponent NotFoundPageComponent
] ]
}) })
export class SqxAppModule { } export class SqxPublicModule { }

11
src/Squidex/app/shared/services/apps.service.ts

@ -57,9 +57,14 @@ export class AppsService {
const now = DateTime.now(); const now = DateTime.now();
return this.authService.authPost(this.apiUrl.buildUrl('api/apps'), appToCreate) return this.authService.authPost(this.apiUrl.buildUrl('api/apps'), appToCreate)
.catch(response => {
if (response.status === 400) {
return Observable.throw('An app with the same name already exists.');
} else {
return Observable.throw('A new app could not be created.');
}
})
.map(response => response.json()) .map(response => response.json())
.map(response => { .map(response => new AppDto(response.id, appToCreate.name, now, now));
return new AppDto(response.id, appToCreate.name, now, now);
});
} }
} }

8
src/Squidex/app/shared/services/auth.service.ts

@ -152,14 +152,14 @@ export class AuthService {
} }
private checkResponse(response: Observable<Ng2Http.Response>) { private checkResponse(response: Observable<Ng2Http.Response>) {
return response.catch((errorResponse: Ng2Http.Response) => { return response.catch((error: Ng2Http.Response) => {
if (errorResponse.status === 401) { if (error.status === 401) {
this.login(); this.login();
} else { } else if (error.status === 403) {
this.router.navigate(['/404']); this.router.navigate(['/404']);
} }
return Observable.throw(response); return Observable.throw(error);
}); });
} }

10
src/Squidex/app/theme/_bootstrap.scss

@ -5,6 +5,16 @@
font-size: 0.8rem; font-size: 0.8rem;
} }
.form-error {
@include border-radius(3px);
@include truncate();
color: white;
margin-top: 4px;
margin-bottom: 10px;
padding: 6px;
background: $accent-error;
}
.ng-invalid.ng-dirty { .ng-invalid.ng-dirty {
border-color: $accent-error; border-color: $accent-error;
} }

6
src/Squidex/tsconfig.json

@ -8,6 +8,10 @@
"experimentalDecorators": true, "experimentalDecorators": true,
"removeComments": false, "removeComments": false,
"noImplicitAny": true, "noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true "suppressImplicitAnyIndexErrors": true,
"baseUrl": ".",
"paths": {
"*": ["*", "app/*"]
}
} }
} }

7
src/Squidex/wwwroot/index.html

@ -11,6 +11,11 @@
<style> <style>
body { body {
background: #F4F8F9; background: #F4F8F9;
line-height: 1.5;
}
img {
vertical-align: middle;
} }
.loading { .loading {
@ -18,7 +23,7 @@
} }
.loading img { .loading img {
width: 160px; height: 60px;
} }
.loading div { .loading div {

Loading…
Cancel
Save