From 2c1a5ba22af8ba559fe0a5c519fa0d8747a9fd92 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Wed, 19 Jun 2019 20:14:20 +0200 Subject: [PATCH] Bugfixes. --- .../Apps/RoleExtensions.cs | 2 +- .../Api/Controllers/Apps/Models/AppDto.cs | 5 ++ .../Controllers/Assets/Models/AssetsDto.cs | 2 +- .../pages/content/content-page.component.ts | 2 +- .../shared/assets-editor.component.html | 4 +- .../pages/backups/backups-page.component.html | 2 +- .../pages/clients/client.component.ts | 20 +++--- .../pages/languages/language.component.ts | 16 ++--- .../pages/patterns/pattern.component.ts | 18 ++--- .../angular/forms/file-drop.directive.ts | 13 ++-- .../components/asset-dialog.component.ts | 2 +- .../components/asset-uploader.component.html | 72 ++++++++++--------- .../shared/components/asset.component.html | 12 +++- .../components/assets-list.component.html | 2 +- .../components/markdown-editor.component.html | 2 +- .../components/rich-editor.component.html | 2 +- .../app/shared/services/apps.service.ts | 2 + .../app/shared/services/assets.service.ts | 6 +- src/Squidex/app/shared/state/assets.state.ts | 10 ++- .../Apps/RoleExtensionsTests.cs | 9 +++ 20 files changed, 120 insertions(+), 83 deletions(-) diff --git a/src/Squidex.Domain.Apps.Entities/Apps/RoleExtensions.cs b/src/Squidex.Domain.Apps.Entities/Apps/RoleExtensions.cs index 0e0eddad9..f6464d5dc 100644 --- a/src/Squidex.Domain.Apps.Entities/Apps/RoleExtensions.cs +++ b/src/Squidex.Domain.Apps.Entities/Apps/RoleExtensions.cs @@ -55,7 +55,7 @@ namespace Squidex.Domain.Apps.Entities.Apps { return id; } - })); + }).Where(x => x != "common")); } } } diff --git a/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs b/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs index 1c2c28920..6d706dc30 100644 --- a/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs @@ -182,6 +182,11 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models AddPostLink("schemas/create", controller.Url(x => nameof(x.PostSchema), values)); } + if (controller.HasPermission(AllPermissions.AppAssetsCreate, Name, permissions: permissions)) + { + AddPostLink("assets/create", controller.Url(x => nameof(x.PostSchema), values)); + } + return this; } } diff --git a/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetsDto.cs b/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetsDto.cs index c0870d583..f6ceca82d 100644 --- a/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetsDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetsDto.cs @@ -59,7 +59,7 @@ namespace Squidex.Areas.Api.Controllers.Assets.Models response.AddPostLink("create", controller.Url(x => nameof(x.PostAsset), values)); } - response.AddDeleteLink("tags", controller.Url(x => nameof(x.GetTags), values)); + response.AddGetLink("tags", controller.Url(x => nameof(x.GetTags), values)); return response; } diff --git a/src/Squidex/app/features/content/pages/content/content-page.component.ts b/src/Squidex/app/features/content/pages/content/content-page.component.ts index fd4afb1a6..94c3f79c2 100644 --- a/src/Squidex/app/features/content/pages/content/content-page.component.ts +++ b/src/Squidex/app/features/content/pages/content/content-page.component.ts @@ -183,7 +183,7 @@ export class ContentPageComponent extends ResourceOwner implements CanComponentD private loadContent(data: any) { this.contentForm.loadContent(data); - this.contentForm.setEnabled(!this.content || this.content.canUpdate); + this.contentForm.setEnabled(this.content && !this.content.canUpdate); } public discardChanges() { diff --git a/src/Squidex/app/features/content/shared/assets-editor.component.html b/src/Squidex/app/features/content/shared/assets-editor.component.html index 4bf9cdadf..01e7337ca 100644 --- a/src/Squidex/app/features/content/shared/assets-editor.component.html +++ b/src/Squidex/app/features/content/shared/assets-editor.component.html @@ -1,9 +1,9 @@ -
+
-
+
Drop files or click
diff --git a/src/Squidex/app/features/settings/pages/backups/backups-page.component.html b/src/Squidex/app/features/settings/pages/backups/backups-page.component.html index 0c326e4ca..94ade6d25 100644 --- a/src/Squidex/app/features/settings/pages/backups/backups-page.component.html +++ b/src/Squidex/app/features/settings/pages/backups/backups-page.component.html @@ -52,7 +52,7 @@ Duration:
-
+
{{backup.started | sqxFromNow}}
diff --git a/src/Squidex/app/features/settings/pages/clients/client.component.ts b/src/Squidex/app/features/settings/pages/clients/client.component.ts index dcc038b66..76c7bc9d3 100644 --- a/src/Squidex/app/features/settings/pages/clients/client.component.ts +++ b/src/Squidex/app/features/settings/pages/clients/client.component.ts @@ -5,7 +5,7 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ -import { Component, Input, OnChanges } from '@angular/core'; +import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; import { FormBuilder } from '@angular/forms'; import { @@ -58,16 +58,18 @@ export class ClientComponent implements OnChanges { ) { } - public ngOnChanges() { - this.renameForm.load(this.client); + public ngOnChanges(changes: SimpleChanges) { + if (changes['client']) { + this.renameForm.load(this.client); - const app = this.appsState.appName; + const app = this.appsState.appName; - this.connectHttpText = connectHttpText(this.apiUrl, app, this.client); - this.connectCLINetText = connectCLINetText(app, this.client, this.apiUrl); - this.connectCLINixText = connectCLINixText(app, this.client, this.apiUrl); - this.connectCLIWinText = connectCLIWinText(app, this.client, this.apiUrl); - this.connectLibraryText = connectLibrary(this.apiUrl, app, this.client); + this.connectHttpText = connectHttpText(this.apiUrl, app, this.client); + this.connectCLINetText = connectCLINetText(app, this.client, this.apiUrl); + this.connectCLINixText = connectCLINixText(app, this.client, this.apiUrl); + this.connectCLIWinText = connectCLIWinText(app, this.client, this.apiUrl); + this.connectLibraryText = connectLibrary(this.apiUrl, app, this.client); + } } public revoke() { diff --git a/src/Squidex/app/features/settings/pages/languages/language.component.ts b/src/Squidex/app/features/settings/pages/languages/language.component.ts index 8956b6a2a..ecfc7a583 100644 --- a/src/Squidex/app/features/settings/pages/languages/language.component.ts +++ b/src/Squidex/app/features/settings/pages/languages/language.component.ts @@ -48,7 +48,12 @@ export class LanguageComponent implements OnChanges { } public ngOnChanges() { - this.resetForm(); + this.isEditable = this.language.canUpdate; + + this.editForm.load(this.language); + this.editForm.setEnabled(this.isEditable); + + this.otherLanguage = this.fallbackLanguagesNew.at(0); } public toggleEditing() { @@ -94,15 +99,6 @@ export class LanguageComponent implements OnChanges { this.otherLanguage = this.fallbackLanguagesNew.at(0); } - private resetForm() { - this.isEditable = this.language.canUpdate; - - this.editForm.load(this.language); - this.editForm.setEnabled(this.isEditable); - - this.otherLanguage = this.fallbackLanguagesNew.at(0); - } - public trackByLanguage(index: number, language: AppLanguageDto) { return language.iso2Code; } diff --git a/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts b/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts index a4cd887b1..43572f708 100644 --- a/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts +++ b/src/Squidex/app/features/settings/pages/patterns/pattern.component.ts @@ -5,7 +5,7 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; import { FormBuilder } from '@angular/forms'; import { @@ -19,7 +19,7 @@ import { styleUrls: ['./pattern.component.scss'], templateUrl: './pattern.component.html' }) -export class PatternComponent implements OnInit { +export class PatternComponent implements OnChanges { @Input() public pattern: PatternDto; @@ -34,12 +34,14 @@ export class PatternComponent implements OnInit { ) { } - public ngOnInit() { - this.isEditable = !this.pattern || this.pattern.canUpdate; - this.isDeletable = this.pattern && this.pattern.canDelete; + public ngOnChanges(changes: SimpleChanges) { + if (changes['pattern']) { + this.isEditable = !this.pattern || this.pattern.canUpdate; + this.isDeletable = this.pattern && this.pattern.canDelete; - this.editForm.load(this.pattern); - this.editForm.setEnabled(this.isEditable); + this.editForm.load(this.pattern); + this.editForm.setEnabled(this.isEditable); + } } public cancel() { @@ -61,7 +63,7 @@ export class PatternComponent implements OnInit { if (this.pattern) { this.patternsState.update(this.pattern, value) .subscribe(newPattern => { - this.editForm.submitCompleted({ newValue: newPattern }); + this.editForm.submitCompleted(newPattern); }, error => { this.editForm.submitFailed(error); }); diff --git a/src/Squidex/app/framework/angular/forms/file-drop.directive.ts b/src/Squidex/app/framework/angular/forms/file-drop.directive.ts index 027413c90..adf2eec5c 100644 --- a/src/Squidex/app/framework/angular/forms/file-drop.directive.ts +++ b/src/Squidex/app/framework/angular/forms/file-drop.directive.ts @@ -19,7 +19,7 @@ const ImageTypes = [ ]; @Directive({ - selector: '[sqxFileDrop]' + selector: '[sqxDropFile]' }) export class FileDropDirective { private dragCounter = 0; @@ -33,7 +33,10 @@ export class FileDropDirective { @Input() public noDrop: boolean; - @Output('sqxFileDrop') + @Input('sqxDropDisabled') + public disabled = false; + + @Output('sqxDropFile') public drop = new EventEmitter(); constructor( @@ -60,7 +63,7 @@ export class FileDropDirective { } } - if (result.length > 0) { + if (result.length > 0 && !this.disabled) { this.drop.emit(result); } @@ -127,7 +130,7 @@ export class FileDropDirective { private dragStart() { this.dragCounter++; - if (this.dragCounter === 1) { + if (this.dragCounter === 1 && !this.disabled) { this.renderer.addClass(this.element.nativeElement, 'drag'); } } @@ -135,7 +138,7 @@ export class FileDropDirective { private dragEnd(number?: number ) { this.dragCounter = number || this.dragCounter - 1; - if (this.dragCounter === 0) { + if (this.dragCounter === 0 && !this.disabled) { this.renderer.removeClass(this.element.nativeElement, 'drag'); } } diff --git a/src/Squidex/app/shared/components/asset-dialog.component.ts b/src/Squidex/app/shared/components/asset-dialog.component.ts index 463267626..564b35b52 100644 --- a/src/Squidex/app/shared/components/asset-dialog.component.ts +++ b/src/Squidex/app/shared/components/asset-dialog.component.ts @@ -55,7 +55,7 @@ export class AssetDialogComponent extends StatefulComponent implements OnInit { this.isEditable = this.asset.canUpdate; this.annotateForm.load(this.asset); - this.annotateForm.setEnabled(!this.isEditable); + this.annotateForm.setEnabled(this.isEditable); } public generateSlug() { diff --git a/src/Squidex/app/shared/components/asset-uploader.component.html b/src/Squidex/app/shared/components/asset-uploader.component.html index 01abb1b31..3f9a43764 100644 --- a/src/Squidex/app/shared/components/asset-uploader.component.html +++ b/src/Squidex/app/shared/components/asset-uploader.component.html @@ -1,44 +1,46 @@ - - + \ No newline at end of file diff --git a/src/Squidex/app/shared/components/asset.component.html b/src/Squidex/app/shared/components/asset.component.html index 2cfdedcd1..583b66749 100644 --- a/src/Squidex/app/shared/components/asset.component.html +++ b/src/Squidex/app/shared/components/asset.component.html @@ -1,5 +1,8 @@ -
+
@@ -74,7 +77,10 @@ -
+
@@ -125,7 +131,7 @@ - diff --git a/src/Squidex/app/shared/components/assets-list.component.html b/src/Squidex/app/shared/components/assets-list.component.html index 592e44e29..99d7e82ab 100644 --- a/src/Squidex/app/shared/components/assets-list.component.html +++ b/src/Squidex/app/shared/components/assets-list.component.html @@ -1,4 +1,4 @@ -
+

Drop files here to upload

or
diff --git a/src/Squidex/app/shared/components/markdown-editor.component.html b/src/Squidex/app/shared/components/markdown-editor.component.html index 322e46392..819a39c12 100644 --- a/src/Squidex/app/shared/components/markdown-editor.component.html +++ b/src/Squidex/app/shared/components/markdown-editor.component.html @@ -1,4 +1,4 @@ -
+
diff --git a/src/Squidex/app/shared/components/rich-editor.component.html b/src/Squidex/app/shared/components/rich-editor.component.html index 36cb40d19..44a1469e8 100644 --- a/src/Squidex/app/shared/components/rich-editor.component.html +++ b/src/Squidex/app/shared/components/rich-editor.component.html @@ -1,4 +1,4 @@ -
+
diff --git a/src/Squidex/app/shared/services/apps.service.ts b/src/Squidex/app/shared/services/apps.service.ts index e5a82b468..9ed139d17 100644 --- a/src/Squidex/app/shared/services/apps.service.ts +++ b/src/Squidex/app/shared/services/apps.service.ts @@ -35,6 +35,7 @@ export class AppDto { public readonly canReadRoles: boolean; public readonly canReadRules: boolean; public readonly canReadSchemas: boolean; + public readonly canUploadAssets: boolean; constructor(links: ResourceLinks, public readonly id: string, @@ -61,6 +62,7 @@ export class AppDto { this.canReadRoles = hasAnyLink(links, 'roles'); this.canReadRules = hasAnyLink(links, 'rules'); this.canReadSchemas = hasAnyLink(links, 'schemas'); + this.canUploadAssets = hasAnyLink(links, 'assets/create'); } } diff --git a/src/Squidex/app/shared/services/assets.service.ts b/src/Squidex/app/shared/services/assets.service.ts index 715047113..9e840e4cf 100644 --- a/src/Squidex/app/shared/services/assets.service.ts +++ b/src/Squidex/app/shared/services/assets.service.ts @@ -27,7 +27,11 @@ import { Versioned } from '@app/framework'; -export class AssetsDto extends ResultSet {} +export class AssetsDto extends ResultSet { + public get canCreate() { + return hasAnyLink(this._links, 'create'); + } +} export class AssetDto { public readonly _meta: Metadata = {}; diff --git a/src/Squidex/app/shared/state/assets.state.ts b/src/Squidex/app/shared/state/assets.state.ts index 4b50f56a9..09eeabc0a 100644 --- a/src/Squidex/app/shared/state/assets.state.ts +++ b/src/Squidex/app/shared/state/assets.state.ts @@ -39,6 +39,9 @@ interface Snapshot { // Indicates if the assets are loaded. isLoaded?: boolean; + + // Indicates if the user can create assets. + canCreate?: boolean; } @Injectable() @@ -64,6 +67,9 @@ export class AssetsState extends State { public isLoaded = this.project(x => !!x.isLoaded); + public canCreate = + this.project(x => !!x.canCreate); + constructor( private readonly appsState: AppsState, private readonly assetsService: AssetsService, @@ -89,7 +95,7 @@ export class AssetsState extends State { Object.keys(this.snapshot.tagsSelected)), this.assetsService.getTags(this.appName) ).pipe( - tap(([ { items, total }, tags ]) => { + tap(([ { items, total, canCreate }, tags ]) => { if (isReload) { this.dialogs.notifyInfo('Assets reloaded.'); } @@ -98,7 +104,7 @@ export class AssetsState extends State { const assets = ImmutableArray.of(items); const assetsPager = s.assetsPager.setCount(total); - return { ...s, assets, assetsPager, isLoaded: true, tags }; + return { ...s, assets, assetsPager, isLoaded: true, tags, canCreate }; }); }), shareSubscribed(this.dialogs)); diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Apps/RoleExtensionsTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Apps/RoleExtensionsTests.cs index 5cb8fb01b..cfd3c06af 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Apps/RoleExtensionsTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Apps/RoleExtensionsTests.cs @@ -67,5 +67,14 @@ namespace Squidex.Domain.Apps.Entities.Apps Assert.Equal(Permission.Any, result.First().Id); } + + [Fact] + public void Should_remove_common_permission() + { + var source = new PermissionSet("squidex.apps.my-app.common"); + var result = source.WithoutApp("my-app"); + + Assert.Empty(result); + } } }