Browse Source

CORS fixes and inline editing for assets.

pull/337/head
Sebastian Stehle 8 years ago
parent
commit
e38c70ecb3
  1. 3
      src/Squidex/Areas/Api/Controllers/Assets/Models/UpdateAssetDto.cs
  2. 3
      src/Squidex/Config/Web/WebExtensions.cs
  3. 10
      src/Squidex/app/features/content/shared/assets-editor.component.html
  4. 56
      src/Squidex/app/features/content/shared/assets-editor.component.ts
  5. 4
      src/Squidex/app/shared/components/asset.component.html
  6. 22
      src/Squidex/app/shared/components/asset.component.ts
  7. 8
      src/Squidex/app/shared/components/assets-list.component.ts
  8. 2
      src/Squidex/app/theme/_forms.scss

3
src/Squidex/Areas/Api/Controllers/Assets/Models/UpdateAssetDto.cs

@ -7,7 +7,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Squidex.Domain.Apps.Entities.Assets.Commands;
namespace Squidex.Areas.Api.Controllers.Assets.Models
@ -17,13 +16,11 @@ namespace Squidex.Areas.Api.Controllers.Assets.Models
/// <summary>
/// The new name of the asset.
/// </summary>
[Required]
public string FileName { get; set; }
/// <summary>
/// The new asset tags.
/// </summary>
[Required]
public HashSet<string> Tags { get; set; }
public AssetCommand ToCommand(Guid id)

3
src/Squidex/Config/Web/WebExtensions.cs

@ -101,8 +101,7 @@ namespace Squidex.Config.Web
app.UseCors(builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
.AllowAnyHeader());
}
public static void UseMyForwardingRules(this IApplicationBuilder app)

10
src/Squidex/app/features/content/shared/assets-editor.component.html

@ -25,8 +25,8 @@
<sqx-asset *ngFor="let file of newAssets" [initFile]="file"
(failed)="removeLoadingAsset(file)" (loaded)="addAsset(file, $event)">
</sqx-asset>
<sqx-asset *ngFor="let asset of oldAssets" [asset]="asset" removeMode="true" isDisabled="true"
(removing)="removeLoadedAsset($event)">
<sqx-asset *ngFor="let asset of oldAssets; trackBy: trackByAsset" [asset]="asset" removeMode="true"
(updated)="notifyOthers($event)" (removing)="removeLoadedAsset($event)">
</sqx-asset>
</div>
</ng-container>
@ -40,9 +40,9 @@
<div
[sqxSortModel]="oldAssets.values"
(sqxSorted)="sortAssets($event)">
<div *ngFor="let asset of oldAssets">
<sqx-asset [asset]="asset" removeMode="true" isDisabled="true"
[isListView]="true" (removing)="removeLoadedAsset($event)">
<div *ngFor="let asset of oldAssets; trackBy: trackByAsset">
<sqx-asset [asset]="asset" removeMode="true" [isListView]="true"
(updated)="notifyOthers($event)" (removing)="removeLoadedAsset($event)">
</sqx-asset>
</div>
</div>

56
src/Squidex/app/features/content/shared/assets-editor.component.ts

@ -7,8 +7,9 @@
// tslint:disable:prefer-for-of
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, forwardRef } from '@angular/core';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, forwardRef, OnDestroy, OnInit } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Subscription } from 'rxjs';
import {
AppsState,
@ -17,6 +18,7 @@ import {
DialogModel,
ImmutableArray,
LocalStoreService,
MessageBus,
Types
} from '@app/shared';
@ -24,6 +26,14 @@ export const SQX_ASSETS_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => AssetsEditorComponent), multi: true
};
class AssetUpdated {
constructor(
public readonly asset: AssetDto,
public readonly source: any
) {
}
}
@Component({
selector: 'sqx-assets-editor',
styleUrls: ['./assets-editor.component.scss'],
@ -31,9 +41,10 @@ export const SQX_ASSETS_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
providers: [SQX_ASSETS_EDITOR_CONTROL_VALUE_ACCESSOR],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AssetsEditorComponent implements ControlValueAccessor {
export class AssetsEditorComponent implements ControlValueAccessor, OnInit, OnDestroy {
private callChange = (v: any) => { /* NOOP */ };
private callTouched = () => { /* NOOP */ };
private subscription: Subscription;
public assetsDialog = new DialogModel();
@ -47,7 +58,8 @@ export class AssetsEditorComponent implements ControlValueAccessor {
private readonly appsState: AppsState,
private readonly assetsService: AssetsService,
private readonly changeDetector: ChangeDetectorRef,
private readonly localStore: LocalStoreService
private readonly localStore: LocalStoreService,
private readonly messageBus: MessageBus
) {
this.isListView = this.localStore.get('assetView') === 'List';
}
@ -73,6 +85,24 @@ export class AssetsEditorComponent implements ControlValueAccessor {
}
}
public notifyOthers(asset: AssetDto) {
this.messageBus.emit(new AssetUpdated(asset, this));
}
public ngOnDestroy() {
this.subscription.unsubscribe();
}
public ngOnInit() {
this.subscription =
this.messageBus.of(AssetUpdated)
.subscribe(event => {
if (event.source !== this) {
this.setAssets(this.oldAssets.replaceBy('id', event.asset));
}
});
}
public setAssets(asset: ImmutableArray<AssetDto>) {
this.oldAssets = asset;
@ -120,6 +150,14 @@ export class AssetsEditorComponent implements ControlValueAccessor {
}
}
public sortAssets(assets: AssetDto[]) {
if (assets) {
this.oldAssets = ImmutableArray.of(assets);
this.updateValue();
}
}
public removeLoadedAsset(asset: AssetDto) {
if (asset) {
this.oldAssets = this.oldAssets.remove(asset);
@ -138,14 +176,6 @@ export class AssetsEditorComponent implements ControlValueAccessor {
this.isListView = isListView;
}
public sortAssets(assets: AssetDto[]) {
if (assets) {
this.oldAssets = ImmutableArray.of(assets);
this.updateValue();
}
}
private updateValue() {
let ids: string[] | null = this.oldAssets.values.map(x => x.id);
@ -158,4 +188,8 @@ export class AssetsEditorComponent implements ControlValueAccessor {
this.changeDetector.markForCheck();
}
public trackByAsset(index: number, asset: AssetDto) {
return asset.id;
}
}

4
src/Squidex/app/shared/components/asset.component.html

@ -63,7 +63,7 @@
<form [formGroup]="renameForm.form" (ngSubmit)="renameAsset()">
<sqx-control-errors for="name" [submitted]="renameForm.submitted | async"></sqx-control-errors>
<input type="text" class="form-control form-underlined editable" id="assetName" formControlName="name" autocomplete="off" sqxFocusOnInit (blur)="renameCancel()" />
<input type="text" class="form-control form-underlined editable" id="assetName" formControlName="name" autocomplete="off" spellcheck="false" sqxFocusOnInit (blur)="renameCancel()" />
</form>
</div>
</div>
@ -104,7 +104,7 @@
<form [formGroup]="renameForm.form" (ngSubmit)="renameAsset()">
<sqx-control-errors for="name" [submitted]="renameForm.submitted | async"></sqx-control-errors>
<input type="text" class="form-control editable form-underlined" id="assetName" formControlName="name" autocomplete="off" sqxFocusOnInit (blur)="renameCancel()" />
<input type="text" class="form-control editable form-underlined" id="assetName" formControlName="name" autocomplete="off" spellcheck="false" sqxFocusOnInit (blur)="renameCancel()" />
</form>
</div>
</div>

22
src/Squidex/app/shared/components/asset.component.ts

@ -5,7 +5,7 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostBinding, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostBinding, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges } from '@angular/core';
import { FormBuilder, FormControl } from '@angular/forms';
import { Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
@ -34,7 +34,7 @@ import {
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AssetComponent implements OnDestroy, OnInit {
export class AssetComponent implements OnChanges, OnDestroy, OnInit {
private tagSubscription: Subscription;
@Input()
@ -98,6 +98,10 @@ export class AssetComponent implements OnDestroy, OnInit {
) {
}
public ngOnDestroy() {
this.tagSubscription.unsubscribe();
}
public ngOnInit() {
const initFile = this.initFile;
@ -116,12 +120,6 @@ export class AssetComponent implements OnDestroy, OnInit {
this.emitFailed(error);
});
} else {
this.updateAsset(this.asset, false);
}
if (this.isDisabled) {
this.tagInput.disable();
}
this.tagSubscription =
@ -133,8 +131,10 @@ export class AssetComponent implements OnDestroy, OnInit {
});
}
public ngOnDestroy() {
this.tagSubscription.unsubscribe();
public ngOnChanges(changes: SimpleChanges) {
if (changes['asset'] && this.asset) {
this.tagInput.setValue(this.asset.tags, { emitEvent: false });
}
}
public updateFile(files: FileList) {
@ -220,7 +220,7 @@ export class AssetComponent implements OnDestroy, OnInit {
this.asset = asset;
this.progress = 0;
this.tagInput.setValue(asset.tags);
this.tagInput.setValue(asset.tags, { emitEvent: false });
if (emitEvent) {
this.emitUpdated(asset);

8
src/Squidex/app/shared/components/assets-list.component.ts

@ -66,10 +66,6 @@ export class AssetsListComponent {
this.state.update(asset);
}
public trackByAsset(index: number, asset: AssetDto) {
return asset.id;
}
public select(asset: AssetDto) {
this.selected.emit(asset);
}
@ -87,5 +83,9 @@ export class AssetsListComponent {
this.newFiles = this.newFiles.pushFront(files[i]);
}
}
public trackByAsset(index: number, asset: AssetDto) {
return asset.id;
}
}

2
src/Squidex/app/theme/_forms.scss

@ -185,7 +185,7 @@ input {
@include border-radius(0);
padding-left: 0;
padding-right: 0;
border-color: transparent;
border: 0;
border-bottom: 1px solid $color-input-border;
}

Loading…
Cancel
Save