From 81e33bcdd79f8455d6575c2d8900d27dcab543d1 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 4 Nov 2016 07:32:41 +0100 Subject: [PATCH] Restructuring --- src/Squidex/Modules/Api/Apps/AppController.cs | 4 +- .../EnrichWithSubjectHandler.cs | 10 ++-- src/Squidex/app-config/webpack.common.js | 9 ++- src/Squidex/app/app.component.html | 20 +------ src/Squidex/app/app.component.spec.ts | 10 +--- src/Squidex/app/app.component.ts | 5 +- src/Squidex/app/app.module.ts | 4 +- src/Squidex/app/app.routes.ts | 32 +++++++--- .../components/auth/logout-page.component.ts | 1 - src/Squidex/app/components/index.ts | 5 +- .../internal/app/app-area.component.html | 1 + .../internal/app/app-area.component.ts | 14 +++++ .../dashboard/dashboard-page.component.html | 0 .../app/dashboard/dashboard-page.component.ts | 14 +++++ .../apps/apps-page.component.html | 4 +- .../apps/apps-page.component.scss | 4 +- .../apps/apps-page.component.ts | 2 +- .../app/components/internal/declarations.ts | 12 ++++ .../components/{apps => internal}/index.ts | 2 +- .../internal/internal-area.component.html | 17 ++++++ .../internal/internal-area.component.scss} | 2 +- .../internal/internal-area.component.ts | 35 +++++++++++ .../components/internal/internal.module.ts | 32 ++++++++++ .../components/layout/app-form.component.html | 8 ++- .../components/layout/app-form.component.ts | 59 ++++++++++--------- .../layout/apps-menu-list.component.html | 12 ++++ .../layout/apps-menu-list.component.scss | 19 ++++++ .../layout/apps-menu-list.component.ts | 21 +++++++ .../layout/apps-menu.component.html | 15 +---- .../layout/apps-menu.component.scss | 4 +- .../components/layout/apps-menu.component.ts | 11 +++- .../app/components/layout/declarations.ts | 2 +- .../app/components/layout/layout.module.ts | 5 +- .../{apps => public}/declarations.ts | 2 +- src/Squidex/app/components/public/index.ts | 10 ++++ .../not-found-page.component.html | 0 .../not-found-page.component.ts | 0 .../public.module.ts} | 10 ++-- .../app/shared/services/apps.service.ts | 11 +++- .../app/shared/services/auth.service.ts | 8 +-- src/Squidex/app/theme/_bootstrap.scss | 10 ++++ src/Squidex/tsconfig.json | 6 +- src/Squidex/wwwroot/index.html | 7 ++- 43 files changed, 338 insertions(+), 121 deletions(-) create mode 100644 src/Squidex/app/components/internal/app/app-area.component.html create mode 100644 src/Squidex/app/components/internal/app/app-area.component.ts create mode 100644 src/Squidex/app/components/internal/app/dashboard/dashboard-page.component.html create mode 100644 src/Squidex/app/components/internal/app/dashboard/dashboard-page.component.ts rename src/Squidex/app/components/{ => internal}/apps/apps-page.component.html (85%) rename src/Squidex/app/components/{ => internal}/apps/apps-page.component.scss (68%) rename src/Squidex/app/components/{ => internal}/apps/apps-page.component.ts (94%) create mode 100644 src/Squidex/app/components/internal/declarations.ts rename src/Squidex/app/components/{apps => internal}/index.ts (80%) create mode 100644 src/Squidex/app/components/internal/internal-area.component.html rename src/Squidex/app/{app.component.scss => components/internal/internal-area.component.scss} (88%) create mode 100644 src/Squidex/app/components/internal/internal-area.component.ts create mode 100644 src/Squidex/app/components/internal/internal.module.ts create mode 100644 src/Squidex/app/components/layout/apps-menu-list.component.html create mode 100644 src/Squidex/app/components/layout/apps-menu-list.component.scss create mode 100644 src/Squidex/app/components/layout/apps-menu-list.component.ts rename src/Squidex/app/components/{apps => public}/declarations.ts (70%) create mode 100644 src/Squidex/app/components/public/index.ts rename src/Squidex/app/components/{layout => public}/not-found-page.component.html (100%) rename src/Squidex/app/components/{layout => public}/not-found-page.component.ts (100%) rename src/Squidex/app/components/{apps/apps.module.ts => public/public.module.ts} (63%) diff --git a/src/Squidex/Modules/Api/Apps/AppController.cs b/src/Squidex/Modules/Api/Apps/AppController.cs index db4591c2f..314c2b72c 100644 --- a/src/Squidex/Modules/Api/Apps/AppController.cs +++ b/src/Squidex/Modules/Api/Apps/AppController.cs @@ -9,12 +9,12 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Squidex.Infrastructure.CQRS.Commands; using Squidex.Infrastructure.Reflection; +using Squidex.Infrastructure.Security; using Squidex.Modules.Api.Apps.Models; using Squidex.Pipeline; using Squidex.Read.Apps.Repositories; @@ -38,7 +38,7 @@ namespace Squidex.Modules.Api.Apps [Route("apps/")] public async Task> 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(); } diff --git a/src/Squidex/Pipeline/CommandHandlers/EnrichWithSubjectHandler.cs b/src/Squidex/Pipeline/CommandHandlers/EnrichWithSubjectHandler.cs index c216c5e55..1cca95e58 100644 --- a/src/Squidex/Pipeline/CommandHandlers/EnrichWithSubjectHandler.cs +++ b/src/Squidex/Pipeline/CommandHandlers/EnrichWithSubjectHandler.cs @@ -7,10 +7,10 @@ // ========================================================================== using System.Security; -using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Squidex.Infrastructure.CQRS.Commands; +using Squidex.Infrastructure.Security; // ReSharper disable InvertIf namespace Squidex.Pipeline.CommandHandlers @@ -30,14 +30,14 @@ namespace Squidex.Pipeline.CommandHandlers 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); diff --git a/src/Squidex/app-config/webpack.common.js b/src/Squidex/app-config/webpack.common.js index 61cea21b1..8058ae0ae 100644 --- a/src/Squidex/app-config/webpack.common.js +++ b/src/Squidex/app-config/webpack.common.js @@ -35,6 +35,11 @@ module.exports = { root: [ helpers.root('app'), helpers.root('app-libs') + ], + moduleDirectories: [ + "*", + "app/*", + "app/theme/*" ] }, @@ -77,7 +82,9 @@ module.exports = { } ] }, - + sassLoader: { + includePaths: [helpers.root('app', 'theme')] + }, plugins: [ /** * Plugin: CommonsChunkPlugin diff --git a/src/Squidex/app/app.component.html b/src/Squidex/app/app.component.html index 91baaee15..8012c5ac6 100644 --- a/src/Squidex/app/app.component.html +++ b/src/Squidex/app/app.component.html @@ -1,20 +1,6 @@ - - -
- -
+
+ +
Loading awesomeness
diff --git a/src/Squidex/app/app.component.spec.ts b/src/Squidex/app/app.component.spec.ts index 0cc8bde5a..d6fc9c607 100644 --- a/src/Squidex/app/app.component.spec.ts +++ b/src/Squidex/app/app.component.spec.ts @@ -3,10 +3,6 @@ import { TestBed } from '@angular/core/testing'; import { RouterModule, provideRoutes } from '@angular/router'; import { RouterTestingModule } from '@angular/router/testing'; -import { SqxLayoutModule } from './components/layout'; - -import { AppsStoreService } from './shared'; - import { AppComponent } from './app.component'; describe('App', () => { @@ -17,12 +13,10 @@ describe('App', () => { ], imports: [ RouterModule, - RouterTestingModule, - SqxLayoutModule + RouterTestingModule ], providers: [ - provideRoutes([]), - { provide: AppsStoreService, useValue: new AppsStoreService(null, null) } + provideRoutes([]) ] }); }); diff --git a/src/Squidex/app/app.component.ts b/src/Squidex/app/app.component.ts index 92f567eaf..41e92bfa4 100644 --- a/src/Squidex/app/app.component.ts +++ b/src/Squidex/app/app.component.ts @@ -9,7 +9,8 @@ import * as Ng2 from '@angular/core'; @Ng2.Component({ selector: 'sqx-app', - styles, template }) -export class AppComponent { } \ No newline at end of file +export class AppComponent { + public isLoaded = false; +} \ No newline at end of file diff --git a/src/Squidex/app/app.module.ts b/src/Squidex/app/app.module.ts index 8a5387725..25ff393b6 100644 --- a/src/Squidex/app/app.module.ts +++ b/src/Squidex/app/app.module.ts @@ -30,7 +30,8 @@ import { import { SqxAppModule, SqxLayoutModule, - SqxLoginModule + SqxLoginModule, + SqxPublicModule } from './components'; import { SqxFrameworkModule } from './framework'; @@ -46,6 +47,7 @@ const baseUrl = window.location.protocol + '//' + window.location.host + '/'; SqxLayoutModule, SqxLoginModule, SqxFrameworkModule, + SqxPublicModule, routing ], declarations: [ diff --git a/src/Squidex/app/app.routes.ts b/src/Squidex/app/app.routes.ts index 59906bd07..dcc4bf44a 100644 --- a/src/Squidex/app/app.routes.ts +++ b/src/Squidex/app/app.routes.ts @@ -10,6 +10,9 @@ import * as Ng2Router from '@angular/router'; import { AppsPageComponent, + AppAreaComponent, + DashboardComponent, + InternalAreaComponent, LoginPageComponent, LogoutPageComponent, NotFoundPageComponent @@ -22,13 +25,28 @@ import { export const routes: Ng2Router.Routes = [ { path: '', - redirectTo: 'apps', - pathMatch: 'full' + redirectTo: 'app', pathMatch: 'full' }, { - path: 'apps', - component: AppsPageComponent, - canActivate: [AuthGuard] + path: 'app', + component: InternalAreaComponent, + canActivate: [AuthGuard], + children: [ + { + path: '', + component: AppsPageComponent + }, + { + path: ':appName', + component: AppAreaComponent, + children: [ + { + path: '', + component: DashboardComponent + } + ] + } + ] }, { path: 'login', @@ -38,10 +56,6 @@ export const routes: Ng2Router.Routes = [ path: 'logout', component: LogoutPageComponent }, - { - path: '404', - component: NotFoundPageComponent - }, { path: '**', component: NotFoundPageComponent diff --git a/src/Squidex/app/components/auth/logout-page.component.ts b/src/Squidex/app/components/auth/logout-page.component.ts index b93b01dbf..4bb40a079 100644 --- a/src/Squidex/app/components/auth/logout-page.component.ts +++ b/src/Squidex/app/components/auth/logout-page.component.ts @@ -15,7 +15,6 @@ import { AuthService } from './../../shared'; template }) export class LogoutPageComponent implements Ng2.OnInit { - constructor( private readonly authService: AuthService, private readonly router: Ng2Router.Router diff --git a/src/Squidex/app/components/index.ts b/src/Squidex/app/components/index.ts index b17807a2d..d18b8affe 100644 --- a/src/Squidex/app/components/index.ts +++ b/src/Squidex/app/components/index.ts @@ -5,6 +5,7 @@ * Copyright (c) Sebastian Stehle. All rights reserved */ -export * from './apps'; export * from './auth'; -export * from './layout'; \ No newline at end of file +export * from './internal'; +export * from './layout'; +export * from './public'; \ No newline at end of file diff --git a/src/Squidex/app/components/internal/app/app-area.component.html b/src/Squidex/app/components/internal/app/app-area.component.html new file mode 100644 index 000000000..90c6b6463 --- /dev/null +++ b/src/Squidex/app/components/internal/app/app-area.component.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Squidex/app/components/internal/app/app-area.component.ts b/src/Squidex/app/components/internal/app/app-area.component.ts new file mode 100644 index 000000000..47d3dfe51 --- /dev/null +++ b/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 { } \ No newline at end of file diff --git a/src/Squidex/app/components/internal/app/dashboard/dashboard-page.component.html b/src/Squidex/app/components/internal/app/dashboard/dashboard-page.component.html new file mode 100644 index 000000000..e69de29bb diff --git a/src/Squidex/app/components/internal/app/dashboard/dashboard-page.component.ts b/src/Squidex/app/components/internal/app/dashboard/dashboard-page.component.ts new file mode 100644 index 000000000..8e9c1860f --- /dev/null +++ b/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 { } \ No newline at end of file diff --git a/src/Squidex/app/components/apps/apps-page.component.html b/src/Squidex/app/components/internal/apps/apps-page.component.html similarity index 85% rename from src/Squidex/app/components/apps/apps-page.component.html rename to src/Squidex/app/components/internal/apps/apps-page.component.html index e0974506e..775fabb59 100644 --- a/src/Squidex/app/components/apps/apps-page.component.html +++ b/src/Squidex/app/components/internal/apps/apps-page.component.html @@ -19,8 +19,8 @@
diff --git a/src/Squidex/app/components/apps/apps-page.component.scss b/src/Squidex/app/components/internal/apps/apps-page.component.scss similarity index 68% rename from src/Squidex/app/components/apps/apps-page.component.scss rename to src/Squidex/app/components/internal/apps/apps-page.component.scss index 3b5bb8840..9e6c5e57d 100644 --- a/src/Squidex/app/components/apps/apps-page.component.scss +++ b/src/Squidex/app/components/internal/apps/apps-page.component.scss @@ -1,5 +1,5 @@ -@import '../../theme/_vars.scss'; -@import '../../theme/_mixins.scss'; +@import '../../../theme/_vars.scss'; +@import '../../../theme/_mixins.scss'; content { padding: 20px; diff --git a/src/Squidex/app/components/apps/apps-page.component.ts b/src/Squidex/app/components/internal/apps/apps-page.component.ts similarity index 94% rename from src/Squidex/app/components/apps/apps-page.component.ts rename to src/Squidex/app/components/internal/apps/apps-page.component.ts index 41d26567a..b22996e4b 100644 --- a/src/Squidex/app/components/apps/apps-page.component.ts +++ b/src/Squidex/app/components/internal/apps/apps-page.component.ts @@ -11,7 +11,7 @@ import { fadeAnimation, ModalView, TitleService -} from './../../framework'; +} from './../../../framework'; @Ng2.Component({ selector: 'sqx-apps-page', diff --git a/src/Squidex/app/components/internal/declarations.ts b/src/Squidex/app/components/internal/declarations.ts new file mode 100644 index 000000000..09cfddf93 --- /dev/null +++ b/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'; \ No newline at end of file diff --git a/src/Squidex/app/components/apps/index.ts b/src/Squidex/app/components/internal/index.ts similarity index 80% rename from src/Squidex/app/components/apps/index.ts rename to src/Squidex/app/components/internal/index.ts index 8b961c614..2b7d13e58 100644 --- a/src/Squidex/app/components/apps/index.ts +++ b/src/Squidex/app/components/internal/index.ts @@ -7,4 +7,4 @@ export * from './declarations'; -export * from './apps.module'; \ No newline at end of file +export * from './internal.module'; \ No newline at end of file diff --git a/src/Squidex/app/components/internal/internal-area.component.html b/src/Squidex/app/components/internal/internal-area.component.html new file mode 100644 index 000000000..5eb05dbd5 --- /dev/null +++ b/src/Squidex/app/components/internal/internal-area.component.html @@ -0,0 +1,17 @@ + + +
+ +
diff --git a/src/Squidex/app/app.component.scss b/src/Squidex/app/components/internal/internal-area.component.scss similarity index 88% rename from src/Squidex/app/app.component.scss rename to src/Squidex/app/components/internal/internal-area.component.scss index c38a19956..49eefdd70 100644 --- a/src/Squidex/app/app.component.scss +++ b/src/Squidex/app/components/internal/internal-area.component.scss @@ -1,4 +1,4 @@ -@import 'theme/mixins.scss'; +@import '../../theme/mixins.scss'; .navbar { @include box-shadow(0, 4px, 4px, 0.2px); diff --git a/src/Squidex/app/components/internal/internal-area.component.ts b/src/Squidex/app/components/internal/internal-area.component.ts new file mode 100644 index 000000000..6c5d0577a --- /dev/null +++ b/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'); + } +} \ No newline at end of file diff --git a/src/Squidex/app/components/internal/internal.module.ts b/src/Squidex/app/components/internal/internal.module.ts new file mode 100644 index 000000000..42e873b5f --- /dev/null +++ b/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 { } \ No newline at end of file diff --git a/src/Squidex/app/components/layout/app-form.component.html b/src/Squidex/app/components/layout/app-form.component.html index 53c42f3cc..f9ff4f198 100644 --- a/src/Squidex/app/components/layout/app-form.component.html +++ b/src/Squidex/app/components/layout/app-form.component.html @@ -1,4 +1,10 @@
+
+
+ {{creationError | async}} +
+
+
@@ -26,6 +32,6 @@
- +
\ No newline at end of file diff --git a/src/Squidex/app/components/layout/app-form.component.ts b/src/Squidex/app/components/layout/app-form.component.ts index 41e90f31e..90b7ead46 100644 --- a/src/Squidex/app/components/layout/app-form.component.ts +++ b/src/Squidex/app/components/layout/app-form.component.ts @@ -8,7 +8,7 @@ import * as Ng2 from '@angular/core'; import * as Ng2Forms from '@angular/forms'; -import { Observable } from 'rxjs'; +import { BehaviorSubject } from 'rxjs'; import { fadeAnimation } from './../../framework'; @@ -24,32 +24,18 @@ const FALLBACK_NAME = 'my-app'; fadeAnimation() ] }) -export class AppFormComponent implements Ng2.OnInit { - public createForm: Ng2Forms.FormGroup; - - public appName: Observable; - +export class AppFormComponent { @Ng2.Input() public showClose = false; @Ng2.Output() - public onCreated = new Ng2.EventEmitter(); + public created = new Ng2.EventEmitter(); @Ng2.Output() - public onCancelled = new Ng2.EventEmitter(); - - public creating = new Ng2.EventEmitter(); - - public creationError = new Ng2.EventEmitter(); - - constructor( - private readonly appsStore: AppsStoreService, - private readonly formBuilder: Ng2Forms.FormBuilder - ) { - } + public cancelled = new Ng2.EventEmitter(); - public ngOnInit() { - this.createForm = this.formBuilder.group({ + public createForm = + this.formBuilder.group({ name: ['', [ 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(false); + + public creationError = + new BehaviorSubject(''); + + constructor( + private readonly appsStore: AppsStoreService, + private readonly formBuilder: Ng2Forms.FormBuilder + ) { } public submit() { + this.createForm.markAsDirty(); + if (this.createForm.valid) { this.createForm.disable(); - this.creating.emit(true); + this.creating.next(true); const dto = new AppCreateDto(this.createForm.controls['name'].value); this.appsStore.createApp(dto) - .finally(() => { - this.reset(); - }) .subscribe(() => { - this.onCreated.emit(); + this.createForm.reset(); + this.created.emit(); }, error => { - this.creationError.emit(error); + this.reset(); + this.creationError.next(error); }); } } private reset() { this.createForm.enable(); - this.creating.emit(false); + this.creating.next(false); + this.creationError.next(null); } public cancel() { - this.onCancelled.emit(); + this.reset(); + this.cancelled.emit(); } } \ No newline at end of file diff --git a/src/Squidex/app/components/layout/apps-menu-list.component.html b/src/Squidex/app/components/layout/apps-menu-list.component.html new file mode 100644 index 000000000..9a8fabe52 --- /dev/null +++ b/src/Squidex/app/components/layout/apps-menu-list.component.html @@ -0,0 +1,12 @@ + + All Apps + {{apps.length || 0}} + + + + +
+ {{app.name}} + + +
\ No newline at end of file diff --git a/src/Squidex/app/components/layout/apps-menu-list.component.scss b/src/Squidex/app/components/layout/apps-menu-list.component.scss new file mode 100644 index 000000000..1b5c6be1d --- /dev/null +++ b/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; + } +} \ No newline at end of file diff --git a/src/Squidex/app/components/layout/apps-menu-list.component.ts b/src/Squidex/app/components/layout/apps-menu-list.component.ts new file mode 100644 index 000000000..bd4172f4e --- /dev/null +++ b/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[]; +} \ No newline at end of file diff --git a/src/Squidex/app/components/layout/apps-menu.component.html b/src/Squidex/app/components/layout/apps-menu.component.html index dd8252ea8..e91df8ccb 100644 --- a/src/Squidex/app/components/layout/apps-menu.component.html +++ b/src/Squidex/app/components/layout/apps-menu.component.html @@ -3,16 +3,7 @@ {{app | async}} diff --git a/src/Squidex/app/components/layout/apps-menu.component.scss b/src/Squidex/app/components/layout/apps-menu.component.scss index 4f2b6b051..6f601d97d 100644 --- a/src/Squidex/app/components/layout/apps-menu.component.scss +++ b/src/Squidex/app/components/layout/apps-menu.component.scss @@ -1,5 +1,5 @@ -@import '../../theme/_vars.scss'; -@import '../../theme/_mixins.scss'; +@import '_vars.scss'; +@import '_mixins.scss'; .navbar-dark .navbar-nav .nav-link { color: white; diff --git a/src/Squidex/app/components/layout/apps-menu.component.ts b/src/Squidex/app/components/layout/apps-menu.component.ts index a68b09aa3..b7c6c39d0 100644 --- a/src/Squidex/app/components/layout/apps-menu.component.ts +++ b/src/Squidex/app/components/layout/apps-menu.component.ts @@ -8,9 +8,9 @@ import * as Ng2 from '@angular/core'; 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'; @@ -30,10 +30,15 @@ export class AppsMenuComponent { this.appsStore.apps.map(a => a || []); 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( private readonly appsStore: AppsStoreService, + private readonly router: Ng2Router.Router, private readonly route: Ng2Router.ActivatedRoute ) { } diff --git a/src/Squidex/app/components/layout/declarations.ts b/src/Squidex/app/components/layout/declarations.ts index 64df1c132..591fc5ebc 100644 --- a/src/Squidex/app/components/layout/declarations.ts +++ b/src/Squidex/app/components/layout/declarations.ts @@ -7,5 +7,5 @@ export * from './app-form.component'; export * from './apps-menu.component'; -export * from './not-found-page.component'; +export * from './apps-menu-list.component'; export * from './search-form.component'; \ No newline at end of file diff --git a/src/Squidex/app/components/layout/layout.module.ts b/src/Squidex/app/components/layout/layout.module.ts index a5398360b..52858bec2 100644 --- a/src/Squidex/app/components/layout/layout.module.ts +++ b/src/Squidex/app/components/layout/layout.module.ts @@ -12,7 +12,7 @@ import { SqxFrameworkModule } from './../../framework'; import { AppFormComponent, AppsMenuComponent, - NotFoundPageComponent, + AppsMenuListComponent, SearchFormComponent } from './declarations'; @@ -23,12 +23,13 @@ import { declarations: [ AppFormComponent, AppsMenuComponent, - NotFoundPageComponent, + AppsMenuListComponent, SearchFormComponent, ], exports: [ AppFormComponent, AppsMenuComponent, + AppsMenuListComponent, SearchFormComponent, ] }) diff --git a/src/Squidex/app/components/apps/declarations.ts b/src/Squidex/app/components/public/declarations.ts similarity index 70% rename from src/Squidex/app/components/apps/declarations.ts rename to src/Squidex/app/components/public/declarations.ts index b8ee4800a..633f7bc67 100644 --- a/src/Squidex/app/components/apps/declarations.ts +++ b/src/Squidex/app/components/public/declarations.ts @@ -5,4 +5,4 @@ * Copyright (c) Sebastian Stehle. All rights reserved */ -export * from './apps-page.component'; \ No newline at end of file +export * from './not-found-page.component'; \ No newline at end of file diff --git a/src/Squidex/app/components/public/index.ts b/src/Squidex/app/components/public/index.ts new file mode 100644 index 000000000..8c8ba34d4 --- /dev/null +++ b/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'; \ No newline at end of file diff --git a/src/Squidex/app/components/layout/not-found-page.component.html b/src/Squidex/app/components/public/not-found-page.component.html similarity index 100% rename from src/Squidex/app/components/layout/not-found-page.component.html rename to src/Squidex/app/components/public/not-found-page.component.html diff --git a/src/Squidex/app/components/layout/not-found-page.component.ts b/src/Squidex/app/components/public/not-found-page.component.ts similarity index 100% rename from src/Squidex/app/components/layout/not-found-page.component.ts rename to src/Squidex/app/components/public/not-found-page.component.ts diff --git a/src/Squidex/app/components/apps/apps.module.ts b/src/Squidex/app/components/public/public.module.ts similarity index 63% rename from src/Squidex/app/components/apps/apps.module.ts rename to src/Squidex/app/components/public/public.module.ts index fbeeb6850..d3443c5c4 100644 --- a/src/Squidex/app/components/apps/apps.module.ts +++ b/src/Squidex/app/components/public/public.module.ts @@ -8,19 +8,17 @@ import * as Ng2 from '@angular/core'; import { SqxFrameworkModule } from './../../framework'; -import { SqxLayoutModule } from './../layout'; import { - AppsPageComponent + NotFoundPageComponent, } from './declarations'; @Ng2.NgModule({ imports: [ - SqxFrameworkModule, - SqxLayoutModule + SqxFrameworkModule ], declarations: [ - AppsPageComponent + NotFoundPageComponent ] }) -export class SqxAppModule { } \ No newline at end of file +export class SqxPublicModule { } \ No newline at end of file diff --git a/src/Squidex/app/shared/services/apps.service.ts b/src/Squidex/app/shared/services/apps.service.ts index 63d1685cd..83ec7817e 100644 --- a/src/Squidex/app/shared/services/apps.service.ts +++ b/src/Squidex/app/shared/services/apps.service.ts @@ -57,9 +57,14 @@ export class AppsService { const now = DateTime.now(); 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 => { - return new AppDto(response.id, appToCreate.name, now, now); - }); + .map(response => new AppDto(response.id, appToCreate.name, now, now)); } } \ No newline at end of file diff --git a/src/Squidex/app/shared/services/auth.service.ts b/src/Squidex/app/shared/services/auth.service.ts index e30a6089c..0d8ae93af 100644 --- a/src/Squidex/app/shared/services/auth.service.ts +++ b/src/Squidex/app/shared/services/auth.service.ts @@ -152,14 +152,14 @@ export class AuthService { } private checkResponse(response: Observable) { - return response.catch((errorResponse: Ng2Http.Response) => { - if (errorResponse.status === 401) { + return response.catch((error: Ng2Http.Response) => { + if (error.status === 401) { this.login(); - } else { + } else if (error.status === 403) { this.router.navigate(['/404']); } - return Observable.throw(response); + return Observable.throw(error); }); } diff --git a/src/Squidex/app/theme/_bootstrap.scss b/src/Squidex/app/theme/_bootstrap.scss index 8b53b3f09..9df58da98 100644 --- a/src/Squidex/app/theme/_bootstrap.scss +++ b/src/Squidex/app/theme/_bootstrap.scss @@ -5,6 +5,16 @@ 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 { border-color: $accent-error; } diff --git a/src/Squidex/tsconfig.json b/src/Squidex/tsconfig.json index 75bcea575..54700e7f8 100644 --- a/src/Squidex/tsconfig.json +++ b/src/Squidex/tsconfig.json @@ -8,6 +8,10 @@ "experimentalDecorators": true, "removeComments": false, "noImplicitAny": true, - "suppressImplicitAnyIndexErrors": true + "suppressImplicitAnyIndexErrors": true, + "baseUrl": ".", + "paths": { + "*": ["*", "app/*"] + } } } \ No newline at end of file diff --git a/src/Squidex/wwwroot/index.html b/src/Squidex/wwwroot/index.html index 8c52eba97..b7d53ffbe 100644 --- a/src/Squidex/wwwroot/index.html +++ b/src/Squidex/wwwroot/index.html @@ -11,6 +11,11 @@