Browse Source

Temp

pull/1/head
Sebastian 9 years ago
parent
commit
8181f9c857
  1. 17
      src/Squidex.Core/Apps/PermissionLevel.cs
  2. 22
      src/Squidex.Events/Apps/AppContributorAssigned.cs
  3. 15
      src/Squidex.Infrastructure/CQRS/Commands/ISubjectCommand.cs
  4. 19
      src/Squidex.Read/Apps/IAppContributorEntity.cs
  5. 5
      src/Squidex.Read/Apps/IAppEntity.cs
  6. 2
      src/Squidex.Read/Apps/Repositories/IAppRepository.cs
  7. 3
      src/Squidex.Read/Apps/Services/IAppProvider.cs
  8. 4
      src/Squidex.Read/Apps/Services/Implementations/CachingAppProvider.cs
  9. 25
      src/Squidex.Store.MongoDb/Apps/MongoAppContributorEntity.cs
  10. 16
      src/Squidex.Store.MongoDb/Apps/MongoAppEntity.cs
  11. 23
      src/Squidex.Store.MongoDb/Apps/MongoAppRepository.cs
  12. 5
      src/Squidex.Write/Apps/AppDomainObject.cs
  13. 4
      src/Squidex.Write/Apps/Commands/CreateApp.cs
  14. 42
      src/Squidex/.vscode/launch.json
  15. 16
      src/Squidex/.vscode/tasks.json
  16. 8
      src/Squidex/Configurations/Domain/WriteModule.cs
  17. 3
      src/Squidex/Modules/Api/Apps/AppController.cs
  18. 2
      src/Squidex/Modules/ControllerBase.cs
  19. 8
      src/Squidex/Pipeline/AppFeature.cs
  20. 12
      src/Squidex/Pipeline/AppFilterAttribute.cs
  21. 2
      src/Squidex/Pipeline/CommandHandlers/EnrichWithAppIdHandler.cs
  22. 4
      src/Squidex/Pipeline/CommandHandlers/EnrichWithSchemaAggregateIdHandler.cs
  23. 46
      src/Squidex/Pipeline/CommandHandlers/EnrichWithSubjectHandler.cs
  24. 4
      src/Squidex/Pipeline/IAppFeature.cs
  25. 8
      src/Squidex/app/app.component.html
  26. 2
      src/Squidex/app/app.routes.ts
  27. 2
      src/Squidex/app/components/apps/apps-page.component.html
  28. 10
      src/Squidex/app/components/layout/apps-menu.component.html
  29. 2
      src/Squidex/app/components/layout/apps-menu.component.scss
  30. 38
      src/Squidex/app/components/layout/apps-menu.component.ts
  31. 2
      src/Squidex/app/framework/angular/modal-view.directive.ts
  32. 2
      src/Squidex/app/framework/utils/modal-view.spec.ts
  33. 4
      src/Squidex/app/framework/utils/modal-view.ts
  34. 14
      src/Squidex/app/shared/services/apps-store.service.spec.ts
  35. 2
      src/Squidex/app/shared/services/apps-store.service.ts
  36. 1
      src/Squidex/app/theme/_layout.scss
  37. 3
      src/Squidex/app/theme/_vars.scss
  38. BIN
      src/Squidex/wwwroot/images/loader.gif
  39. 32
      src/Squidex/wwwroot/index.html

17
src/Squidex.Core/Apps/PermissionLevel.cs

@ -0,0 +1,17 @@
// ==========================================================================
// PermissionLevel.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
namespace Squidex.Core.Apps
{
public enum PermissionLevel
{
Owner,
Developer,
Editor
}
}

22
src/Squidex.Events/Apps/AppContributorAssigned.cs

@ -0,0 +1,22 @@
// ==========================================================================
// AppContributorAssigned.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using Squidex.Core.Apps;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
namespace Squidex.Events.Apps
{
[TypeName("AppContributorAssigned")]
public class AppContributorAssigned : IEvent
{
public string SubjectId { get; set; }
public PermissionLevel Permission { get; set; }
}
}

15
src/Squidex.Infrastructure/CQRS/Commands/ISubjectCommand.cs

@ -0,0 +1,15 @@
// ==========================================================================
// ISubjectCommand.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
namespace Squidex.Infrastructure.CQRS.Commands
{
public interface ISubjectCommand : ICommand
{
string SubjectId { get; set; }
}
}

19
src/Squidex.Read/Apps/IAppContributorEntity.cs

@ -0,0 +1,19 @@
// ==========================================================================
// IAppContributorEntity.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using Squidex.Core.Apps;
namespace Squidex.Read.Apps
{
public interface IAppContributorEntity
{
string SubjectId { get; }
PermissionLevel Permission { get; }
}
}

5
src/Squidex.Read/Apps/IAppEntity.cs

@ -5,10 +5,15 @@
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
namespace Squidex.Read.Apps
{
public interface IAppEntity : IEntity
{
string Name { get; }
IEnumerable<IAppContributorEntity> Contributors { get; }
}
}

2
src/Squidex.Read/Apps/Repositories/IAppRepository.cs

@ -13,7 +13,7 @@ namespace Squidex.Read.Apps.Repositories
{
public interface IAppRepository
{
Task<IReadOnlyList<IAppEntity>> QueryAllAsync();
Task<IReadOnlyList<IAppEntity>> QueryAllAsync(string currentSubjectId);
Task<IAppEntity> FindAppByNameAsync(string name);
}

3
src/Squidex.Read/Apps/Services/IAppProvider.cs

@ -6,13 +6,12 @@
// All rights reserved.
// ==========================================================================
using System;
using System.Threading.Tasks;
namespace Squidex.Read.Apps.Services
{
public interface IAppProvider
{
Task<Guid?> FindAppIdByNameAsync(string name);
Task<IAppEntity> FindAppByNameAsync(string name);
}
}

4
src/Squidex.Read/Apps/Services/Implementations/CachingAppProvider.cs

@ -35,7 +35,7 @@ namespace Squidex.Read.Apps.Services.Implementations
this.appRepository = appRepository;
}
public async Task<Guid?> FindAppIdByNameAsync(string name)
public async Task<IAppEntity> FindAppByNameAsync(string name)
{
Guard.NotNullOrEmpty(name, nameof(name));
@ -51,7 +51,7 @@ namespace Squidex.Read.Apps.Services.Implementations
Cache.Set(cacheKey, cacheItem, new MemoryCacheEntryOptions { SlidingExpiration = CacheDuration });
}
return cacheItem.Entity?.Id;
return cacheItem.Entity;
}
private static string BulidCacheKey(string name)

25
src/Squidex.Store.MongoDb/Apps/MongoAppContributorEntity.cs

@ -0,0 +1,25 @@
// ==========================================================================
// MongoAppContributorEntity.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using MongoDB.Bson.Serialization.Attributes;
using Squidex.Core.Apps;
using Squidex.Read.Apps;
namespace Squidex.Store.MongoDb.Apps
{
public sealed class MongoAppContributorEntity : IAppContributorEntity
{
[BsonRequired]
[BsonElement]
public string SubjectId { get; set; }
[BsonRequired]
[BsonElement]
public PermissionLevel Permission { get; set; }
}
}

16
src/Squidex.Store.MongoDb/Apps/MongoAppEntity.cs

@ -6,6 +6,8 @@
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using MongoDB.Bson.Serialization.Attributes;
using Squidex.Read.Apps;
using Squidex.Store.MongoDb.Utils;
@ -17,5 +19,19 @@ namespace Squidex.Store.MongoDb.Apps
[BsonRequired]
[BsonElement]
public string Name { get; set; }
[BsonRequired]
[BsonElement]
public List<MongoAppContributorEntity> Contributors { get; set; }
IEnumerable<IAppContributorEntity> IAppEntity.Contributors
{
get { return Contributors; }
}
public MongoAppEntity()
{
Contributors = new List<MongoAppContributorEntity>();
}
}
}

23
src/Squidex.Store.MongoDb/Apps/MongoAppRepository.cs

@ -7,8 +7,8 @@
// ==========================================================================
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver;
using Squidex.Events.Apps;
using Squidex.Infrastructure.CQRS;
@ -38,10 +38,10 @@ namespace Squidex.Store.MongoDb.Apps
return collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.Name));
}
public async Task<IReadOnlyList<IAppEntity>> QueryAllAsync()
public async Task<IReadOnlyList<IAppEntity>> QueryAllAsync(string currentSubjectId)
{
var entities =
await Collection.Find(new BsonDocument()).ToListAsync();
await Collection.Find(s => s.Contributors.Any(c => c.SubjectId == currentSubjectId)).ToListAsync();
return entities;
}
@ -59,6 +59,23 @@ namespace Squidex.Store.MongoDb.Apps
return Collection.CreateAsync(headers, a => SimpleMapper.Map(@event, a));
}
public Task On(AppContributorAssigned @event, EnvelopeHeaders headers)
{
return Collection.CreateAsync(headers, a =>
{
var contributor = a.Contributors.Find(x => x.SubjectId == @event.SubjectId);
if (contributor == null)
{
contributor = new MongoAppContributorEntity { SubjectId = @event.SubjectId };
a.Contributors.Add(contributor);
}
contributor.Permission = @event.Permission;
});
}
public Task On(Envelope<IEvent> @event)
{
return this.DispatchActionAsync(@event.Payload, @event.Headers);

5
src/Squidex.Write/Apps/AppDomainObject.cs

@ -7,11 +7,13 @@
// ==========================================================================
using System;
using Squidex.Core.Apps;
using Squidex.Events.Apps;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Dispatching;
using Squidex.Infrastructure.Reflection;
using Squidex.Write.Apps.Commands;
namespace Squidex.Write.Apps
@ -45,7 +47,8 @@ namespace Squidex.Write.Apps
VerifyNotCreated();
RaiseEvent(new AppCreated { Name = command.Name });
RaiseEvent(SimpleMapper.Map(command, new AppCreated()));
RaiseEvent(SimpleMapper.Map(command, new AppContributorAssigned { Permission = PermissionLevel.Owner }));
}
private void VerifyNotCreated()

4
src/Squidex.Write/Apps/Commands/CreateApp.cs

@ -12,10 +12,12 @@ using Squidex.Infrastructure.CQRS.Commands;
namespace Squidex.Write.Apps.Commands
{
public sealed class CreateApp : AggregateCommand, IValidatable
public sealed class CreateApp : AggregateCommand, ISubjectCommand, IValidatable
{
public string Name { get; set; }
public string SubjectId { get; set; }
public void Validate(IList<ValidationError> errors)
{
if (!Name.IsSlug())

42
src/Squidex/.vscode/launch.json

@ -0,0 +1,42 @@
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceRoot}\\bin\\Debug\\netcoreapp1.0\\Squidex.dll",
"args": [],
"cwd": "${workspaceRoot}",
"stopAtEntry": false,
"internalConsoleOptions": "openOnSessionStart",
"launchBrowser": {
"enabled": true,
"args": "${auto-detect-url}",
"windows": {
"command": "cmd.exe",
"args": "/C start ${auto-detect-url}"
},
"osx": {
"command": "open"
},
"linux": {
"command": "xdg-open"
}
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceRoot}/Views"
}
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command.pickProcess}"
}
]
}

16
src/Squidex/.vscode/tasks.json

@ -0,0 +1,16 @@
{
"version": "0.1.0",
"command": "dotnet",
"isShellCommand": true,
"args": [],
"tasks": [
{
"taskName": "build",
"args": [
"${workspaceRoot}\\project.json"
],
"isBuildCommand": true,
"problemMatcher": "$msCompile"
}
]
}

8
src/Squidex/Configurations/Web/WriteModule.cs → src/Squidex/Configurations/Domain/WriteModule.cs

@ -12,13 +12,13 @@ using Squidex.Pipeline.CommandHandlers;
using Squidex.Write.Apps;
using Squidex.Write.Schemas;
namespace Squidex.Configurations.Web
namespace Squidex.Configurations.Domain
{
public class WriteModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<EnrichWithAggregateIdHandler>()
builder.RegisterType<EnrichWithSchemaAggregateIdHandler>()
.As<ICommandHandler>()
.SingleInstance();
@ -26,6 +26,10 @@ namespace Squidex.Configurations.Web
.As<ICommandHandler>()
.SingleInstance();
builder.RegisterType<EnrichWithSubjectHandler>()
.As<ICommandHandler>()
.SingleInstance();
builder.RegisterType<AppCommandHandler>()
.As<ICommandHandler>()
.SingleInstance();

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

@ -9,6 +9,7 @@
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;
@ -37,7 +38,7 @@ namespace Squidex.Modules.Api.Apps
[Route("apps/")]
public async Task<List<ListAppDto>> Query()
{
var schemas = await appRepository.QueryAllAsync();
var schemas = await appRepository.QueryAllAsync(HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value);
return schemas.Select(s => SimpleMapper.Map(s, new ListAppDto())).ToList();
}

2
src/Squidex/Modules/ControllerBase.cs

@ -33,7 +33,7 @@ namespace Squidex.Modules
throw new InvalidOperationException("Not in a app context");
}
return appFeature.AppId;
return appFeature.App.Id;
}
}
}

8
src/Squidex/Pipeline/AppFeature.cs

@ -6,17 +6,17 @@
// All rights reserved.
// ==========================================================================
using System;
using Squidex.Read.Apps;
namespace Squidex.Pipeline
{
public sealed class AppFeature : IAppFeature
{
public Guid AppId { get; }
public IAppEntity App { get; }
public AppFeature(Guid appId)
public AppFeature(IAppEntity app)
{
AppId = appId;
App = app;
}
}
}

12
src/Squidex/Pipeline/AppFilterAttribute.cs

@ -6,6 +6,8 @@
// All rights reserved.
// ==========================================================================
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
@ -28,21 +30,23 @@ namespace Squidex.Pipeline
if (!string.IsNullOrWhiteSpace(appName))
{
var appId = await appProvider.FindAppIdByNameAsync(appName);
var app = await appProvider.FindAppByNameAsync(appName);
if (!appId.HasValue)
if (app == null)
{
context.Result = new NotFoundResult();
return;
}
if (!context.HttpContext.User.HasClaim("app", appName))
var subject = context.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (subject == null || app.Contributors.Any(x => x.SubjectId == subject))
{
context.Result = new NotFoundResult();
return;
}
context.HttpContext.Features.Set<IAppFeature>(new AppFeature(appId.Value));
context.HttpContext.Features.Set<IAppFeature>(new AppFeature(app));
}
await next();

2
src/Squidex/Pipeline/CommandHandlers/EnrichWithAppIdHandler.cs

@ -38,7 +38,7 @@ namespace Squidex.Pipeline.CommandHandlers
throw new InvalidOperationException("Cannot resolve app");
}
appCommand.AppId = appFeature.AppId;
appCommand.AppId = appFeature.App.Id;
}
return Task.FromResult(false);

4
src/Squidex/Pipeline/CommandHandlers/EnrichWithAggregateIdHandler.cs → src/Squidex/Pipeline/CommandHandlers/EnrichWithSchemaAggregateIdHandler.cs

@ -19,12 +19,12 @@ using Squidex.Write.Schemas;
namespace Squidex.Pipeline.CommandHandlers
{
public sealed class EnrichWithAggregateIdHandler : ICommandHandler
public sealed class EnrichWithSchemaAggregateIdHandler : ICommandHandler
{
private readonly ISchemaProvider schemaProvider;
private readonly IActionContextAccessor actionContextAccessor;
public EnrichWithAggregateIdHandler(ISchemaProvider schemaProvider, IActionContextAccessor actionContextAccessor)
public EnrichWithSchemaAggregateIdHandler(ISchemaProvider schemaProvider, IActionContextAccessor actionContextAccessor)
{
this.schemaProvider = schemaProvider;

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

@ -0,0 +1,46 @@
// ==========================================================================
// EnrichWithSubjectHandler.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Security;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Squidex.Infrastructure.CQRS.Commands;
// ReSharper disable InvertIf
namespace Squidex.Pipeline.CommandHandlers
{
public class EnrichWithSubjectHandler : ICommandHandler
{
private readonly IHttpContextAccessor httpContextAccessor;
public EnrichWithSubjectHandler(IHttpContextAccessor httpContextAccessor)
{
this.httpContextAccessor = httpContextAccessor;
}
public Task<bool> HandleAsync(CommandContext context)
{
var subjectCommand = context.Command as ISubjectCommand;
if (subjectCommand != null)
{
var user = httpContextAccessor.HttpContext.User;
if (user?.FindFirst(ClaimTypes.NameIdentifier) == null)
{
throw new SecurityException("No user available");
}
subjectCommand.SubjectId = user.FindFirst(ClaimTypes.NameIdentifier).Value;
}
return Task.FromResult(false);
}
}
}

4
src/Squidex/Pipeline/IAppFeature.cs

@ -6,12 +6,12 @@
// All rights reserved.
// ==========================================================================
using System;
using Squidex.Read.Apps;
namespace Squidex.Pipeline
{
public interface IAppFeature
{
Guid AppId { get; }
IAppEntity App { get; }
}
}

8
src/Squidex/app/app.component.html

@ -13,5 +13,11 @@
</nav>
<main>
<router-outlet></router-outlet>
<router-outlet>
<div class="loading">
<img src="/images/loader.gif" />
<div>Loading awesomeness</div>
</div>
</router-outlet>
</main>

2
src/Squidex/app/app.routes.ts

@ -48,4 +48,4 @@ export const routes: Ng2Router.Routes = [
}
];
export const routing: Ng2.ModuleWithProviders = Ng2Router.RouterModule.forRoot(routes, { useHash: false });
export const routing: Ng2.ModuleWithProviders = Ng2Router.RouterModule.forRoot(routes, { useHash: false, enableTracing: true });

2
src/Squidex/app/components/apps/apps-page.component.html

@ -6,7 +6,7 @@
</div>
</content>
<div class="modal" [(sqxModalView)]="modalDialog" [@fade]="modalDialog.isOpenChanges | async">
<div class="modal" [(sqxModalView)]="modalDialog" [@fade]="modalDialog.isOpen | async">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">

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

@ -1,16 +1,16 @@
<ul class="nav navbar-nav" *ngIf="apps">
<li class="nav-item dropdown">
<span class="nav-link dropdown-toggle" id="app-name" (click)="modalMenu.toggle()">{{app}}</span>
<span class="nav-link dropdown-toggle" id="app-name" (click)="modalMenu.toggle()">{{app | async}}</span>
<div class="dropdown-menu" [(sqxModalView)]="modalMenu">
<div class="dropdown-menu" [(sqxModalView)]="modalMenu" [@fade]="(modalMenu.isOpen | async)">
<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}}</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">{{app.name}}</a>
<a class="dropdown-item" *ngFor="let app of (apps | async)">{{app.name}}</a>
<div class="dropdown-divider"></div>
@ -21,7 +21,7 @@
</li>
</ul>
<div class="modal ng-animate" [(sqxModalView)]="modalDialog" [@fade]="(modalDialog.isOpenChanges | async)">
<div class="modal ng-animate" [(sqxModalView)]="modalDialog" [@fade]="(modalDialog.isOpen | async)">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">

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

@ -37,7 +37,7 @@
}
&-pill {
@include absolute(auto, 10px, auto, auto);
@include absolute(6px, 10px, auto, auto);
color: $accent-blue;
border: none;
background: $accent-blue-lighter;

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

@ -8,10 +8,7 @@
import * as Ng2 from '@angular/core';
import * as Ng2Router from '@angular/router';
import {
AppDto,
AppsStoreService
} from './../../shared';
import { AppsStoreService } from './../../shared';
import { fadeAnimation, ModalView } from './../../framework';
@ -25,16 +22,15 @@ const FALLBACK_NAME = 'Apps Overview';
fadeAnimation()
]
})
export class AppsMenuComponent implements Ng2.OnInit, Ng2.OnDestroy {
private appsSubscription: any | null = null;
private routeSubscription: any | null = null;
export class AppsMenuComponent {
public modalMenu = new ModalView();
public modalDialog = new ModalView();
public apps: AppDto[] | null = null;
public apps =
this.appsStore.apps.map(a => a || []);
public app = FALLBACK_NAME;
public app =
this.route.params.map((p: any) => p.app || FALLBACK_NAME);
constructor(
private readonly appsStore: AppsStoreService,
@ -42,28 +38,6 @@ export class AppsMenuComponent implements Ng2.OnInit, Ng2.OnDestroy {
) {
}
public ngOnInit() {
this.appsSubscription = this.appsStore.appsChanges.subscribe(apps => {
this.apps = apps;
});
this.routeSubscription = this.route.params.map(p => p['app']).subscribe(app => {
this.app = app || FALLBACK_NAME;
});
}
public ngOnDestroy() {
if (this.appsSubscription) {
this.appsSubscription.unsubscribe();
this.appsSubscription = null;
}
if (this.routeSubscription) {
this.routeSubscription.unsubscribe();
this.routeSubscription = null;
}
}
public createApp() {
this.modalMenu.hide();
this.modalDialog.show();

2
src/Squidex/app/framework/angular/modal-view.directive.ts

@ -45,7 +45,7 @@ export class ModalViewDirective implements Ng2.OnChanges {
}
if (this.modalView) {
this.subscription = this.modalView.isOpenChanges.subscribe(isOpen => {
this.subscription = this.modalView.isOpen.subscribe(isOpen => {
if (this.isEnabled) {
if (isOpen) {
this.renderer.setElementStyle(this.elementRef.nativeElement, 'display', 'block');

2
src/Squidex/app/framework/utils/modal-view.spec.ts

@ -55,7 +55,7 @@ describe('ModalView', () => {
function checkValue(dialog: ModalView, expected: boolean) {
let result: boolean | null = null;
dialog.isOpenChanges.subscribe(value => {
dialog.isOpen.subscribe(value => {
result = value;
}).unsubscribe();

4
src/Squidex/app/framework/utils/modal-view.ts

@ -10,7 +10,7 @@ import { BehaviorSubject, Observable } from 'rxjs';
export class ModalView {
private readonly isOpen$: BehaviorSubject<boolean>;
public get isOpenChanges(): Observable<boolean> {
public get isOpen(): Observable<boolean> {
return this.isOpen$.distinctUntilChanged();
}
@ -29,7 +29,7 @@ export class ModalView {
public toggle() {
let value = false;
this.isOpenChanges.subscribe(v => {
this.isOpen.subscribe(v => {
value = v;
}).unsubscribe();

14
src/Squidex/app/shared/services/apps-store.service.spec.ts

@ -36,11 +36,11 @@ describe('AppsStoreService', () => {
let result1: AppDto[];
let result2: AppDto[];
store.appsChanges.subscribe(x => {
store.apps.subscribe(x => {
result1 = x;
}).unsubscribe();
store.appsChanges.subscribe(x => {
store.apps.subscribe(x => {
result2 = x;
}).unsubscribe();
@ -68,13 +68,13 @@ describe('AppsStoreService', () => {
let result1: AppDto[];
let result2: AppDto[];
store.appsChanges.subscribe(x => {
store.apps.subscribe(x => {
result1 = x;
}).unsubscribe();
store.reload();
store.appsChanges.subscribe(x => {
store.apps.subscribe(x => {
result2 = x;
}).unsubscribe();
@ -102,13 +102,13 @@ describe('AppsStoreService', () => {
let result1: AppDto[];
let result2: AppDto[];
store.appsChanges.subscribe(x => {
store.apps.subscribe(x => {
result1 = x;
}).unsubscribe();
store.createApp(new AppCreateDto('new-name')).subscribe(x => { });
store.appsChanges.subscribe(x => {
store.apps.subscribe(x => {
result2 = x;
}).unsubscribe();
@ -133,7 +133,7 @@ describe('AppsStoreService', () => {
store.createApp(new AppCreateDto('new-name')).subscribe(x => { });
store.appsChanges.subscribe(x => {
store.apps.subscribe(x => {
result = x;
}).unsubscribe();

2
src/Squidex/app/shared/services/apps-store.service.ts

@ -22,7 +22,7 @@ export class AppsStoreService {
private lastApps: AppDto[] = null;
private readonly apps$ = new BehaviorSubject<AppDto[]>(null);
public get appsChanges(): Observable<AppDto[]> {
public get apps(): Observable<AppDto[]> {
return this.apps$;
}

1
src/Squidex/app/theme/_layout.scss

@ -3,6 +3,7 @@
body {
overflow: hidden;
background: $background;
}
.hidden {

3
src/Squidex/app/theme/_vars.scss

@ -1,5 +1,8 @@
$nav-text-color: #333;
$background: #F4F8F9;
$border: #EAEEEF;
$accent-blue: #438CEF;
$accent-blue-dark: #3F83DF;
$accent-blue-light: #A1C6F7;

BIN
src/Squidex/wwwroot/images/loader.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

32
src/Squidex/wwwroot/index.html

@ -2,13 +2,39 @@
<html>
<head>
<base href="/">
<title>Squidex - Headless CMS</title>
<title>Squidex Headless CMS</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
background: #F4F8F9;
}
.loading {
text-align: center; margin-top: 200px;
}
.loading img {
width: 160px;
}
.loading div {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
font-size: 30px;
font-weight: lighter;
}
</style>
</head>
<body>
<sqx-app>Loading...</sqx-app>
<sqx-app>
<div class="loading">
<img src="/images/loader.gif" />
<div>Loading awesomeness</div>
</div>
</sqx-app>
</body>
</html>
Loading…
Cancel
Save