diff --git a/src/Squidex/Controllers/Api/Assets/AssetContentController.cs b/src/Squidex/Controllers/Api/Assets/AssetContentController.cs index e38d0ebe3..dd6ed5197 100644 --- a/src/Squidex/Controllers/Api/Assets/AssetContentController.cs +++ b/src/Squidex/Controllers/Api/Assets/AssetContentController.cs @@ -90,3 +90,5 @@ namespace Squidex.Controllers.Api.Assets } } } + +#pragma warning restore 1573 \ No newline at end of file diff --git a/src/Squidex/Controllers/Api/Assets/AssetController.cs b/src/Squidex/Controllers/Api/Assets/AssetController.cs index e19fe9716..048d8fb09 100644 --- a/src/Squidex/Controllers/Api/Assets/AssetController.cs +++ b/src/Squidex/Controllers/Api/Assets/AssetController.cs @@ -177,8 +177,8 @@ namespace Squidex.Controllers.Api.Assets /// 404 => Asset or app not found. /// [HttpDelete] - [Route("apps/{app}/schemas/{name}/")] - public async Task DeleteSchema(string app, Guid id) + [Route("apps/{app}/assets/{id}/")] + public async Task DeleteAsset(string app, Guid id) { await CommandBus.PublishAsync(new DeleteAsset { AssetId = id }); diff --git a/src/Squidex/app/features/assets/pages/asset.component.html b/src/Squidex/app/features/assets/pages/asset.component.html index 2d1993eb2..81a0d22bc 100644 --- a/src/Squidex/app/features/assets/pages/asset.component.html +++ b/src/Squidex/app/features/assets/pages/asset.component.html @@ -3,10 +3,12 @@
-
{{fileType}}
+ + {{fileType}} +
- +
@@ -18,9 +20,13 @@ - + + + + {{fileType}} + {{userName(asset.lastModifiedBy, true) | async}} diff --git a/src/Squidex/app/features/assets/pages/asset.component.scss b/src/Squidex/app/features/assets/pages/asset.component.scss index 28ac5f688..0fc1adfec 100644 --- a/src/Squidex/app/features/assets/pages/asset.component.scss +++ b/src/Squidex/app/features/assets/pages/asset.component.scss @@ -3,8 +3,51 @@ $card-size: 240px; -$color-type-background: #000; -$color-type-foreground: #fff; +@mixin overlay-container { + position: relative; +} + +@mixin overlay { + & { + @include transition(opacity.4s ease); + @include absolute(0, 0, 0, 0); + @include opacity(0); + color: $color-dark-foreground; + } + + &-background { + @include absolute(0, 0, 0, 0); + @include opacity(.7); + background: $color-dark-black; + } +} + +@mixin asset-type { + padding: .1rem .3rem; + text-transform: uppercase; + font-size: .7rem; + font-weight: normal; + cursor: none; + color: $color-dark-foreground; +} + +@mixin asset-link { + & { + font-size: 1.1rem; + font-weight: normal; + cursor: pointer; + color: darken($color-dark-foreground, 10%); + } + + &:hover { + color: $color-dark-foreground; + } + + &:focus, + &:hover { + text-decoration: none; + } +} :host { padding-bottom: 1rem; @@ -12,31 +55,21 @@ $color-type-foreground: #fff; .drop-overlay { & { - @include transition(opacity.4s ease); - @include absolute(0, 0, 0, 0); - @include opacity(0); + @include overlay; pointer-events: none; } &-text { - @include absolute(0, 0, 0, 0); + @include absolute(40%, 0, 0, 0); text-align: center; - line-height: 14rem; - font-size: 1.2rem; + font-size: 1.3rem; font-weight: lighter; - color: $color-type-foreground; - } - - &-background { - @include absolute(0, 0, 0, 0); - @include opacity(.7); - background: $color-type-background; } } .card { & { - position: relative; + @include overlay-container; height: $card-size; } @@ -69,7 +102,10 @@ $color-type-foreground: #fff; } &-preview { - position: relative; + & { + @include overlay-container; + height: 155px; + } &:hover { .file-overlay { @@ -82,23 +118,6 @@ $color-type-foreground: #fff; } } - &-icon { - &-container { - background: $color-border; - border: 0; - height: 155px; - line-height: 155px; - text-align: center; - } - } - - &-name { - @include truncate; - font-size: 1rem; - font-weight: normal; - line-height: 2rem; - } - &-user { @include absolute(auto, auto, 1.7rem, .5rem); } @@ -108,63 +127,47 @@ $color-type-foreground: #fff; } &-delete { - & { - @include absolute(.5rem, 1rem, auto, auto); - font-size: 1.1rem; - font-weight: normal; - cursor: pointer; - color: $color-accent-dark; - } - - &:focus, - &:hover { - text-decoration: none; - } + @include asset-link; + @include absolute(.5rem, 1rem, auto, auto); } &-download { - & { - @include absolute(.5rem, 2.5rem, auto, auto); - font-size: 1.1rem; - font-weight: normal; - cursor: pointer; - color: $color-accent-dark; - } - - &:focus, - &:hover { - text-decoration: none; - } + @include asset-link; + @include absolute(.5rem, 2.5rem, auto, auto); } &-type { @include transition(opacity.4s ease); - @include absolute(.5rem, auto, auto, .5rem); - @include border-radius(2px); - @include opacity(.8); - background: $color-type-background; - border: 0; - padding: .1rem .3rem; - text-transform: uppercase; - font-size: .7rem; + @include absolute(.7rem, auto, auto, .5rem); + @include asset-type; + @include border-radius(3px); + background: $color-dark-black; + } + + &-name { + @include truncate; + font-size: 1rem; font-weight: normal; - color: $color-type-foreground; + line-height: 2rem; + } + + &-icon-container { + background: $color-border; + border: 0; + line-height: 155px; + text-align: center; } &-overlay { & { - @include transition(opacity.4s ease); - @include absolute(0, 0, 0, 0); - @include opacity(0); - font-size: .9rem; + @include overlay; + font-size: .8rem; font-weight: normal; - color: $color-accent-dark; } - &-background { - @include absolute(0, 0, 0, 0); - @include opacity(.7); - background: $color-type-background; + &-type { + @include absolute(.7rem, auto, auto, .5rem); + @include asset-type; } } } \ No newline at end of file diff --git a/src/Squidex/app/features/assets/pages/asset.component.ts b/src/Squidex/app/features/assets/pages/asset.component.ts index a8501a11f..f5cd05c29 100644 --- a/src/Squidex/app/features/assets/pages/asset.component.ts +++ b/src/Squidex/app/features/assets/pages/asset.component.ts @@ -20,7 +20,8 @@ import { fadeAnimation, MathHelper, NotificationService, - UsersProviderService + UsersProviderService, + Version } from 'shared'; @Component({ @@ -32,7 +33,9 @@ import { ] }) export class AssetComponent extends AppComponentBase implements OnInit { - private assetVersion = MathHelper.guid(); + private assetUrlVersion = MathHelper.guid(); + private retries = 0; + private version: Version; @Input() public initFile: File; @@ -41,7 +44,10 @@ export class AssetComponent extends AppComponentBase implements OnInit { public asset: AssetDto; @Output() - public deleting = new EventEmitter(); + public loaded = new EventEmitter(); + + @Output() + public deleting = new EventEmitter(); @Output() public failed = new EventEmitter(); @@ -49,11 +55,11 @@ export class AssetComponent extends AppComponentBase implements OnInit { public progress = 0; public get previewUrl(): string { - return this.apiUrl.buildUrl(`api/assets/${this.asset.id}/?width=230&height=155&mode=Crop&q=${this.assetVersion}`); + return this.apiUrl.buildUrl(`api/assets/${this.asset.id}/?width=230&height=155&mode=Crop&q=${this.assetUrlVersion}`); } public get downloadUrl(): string { - return this.apiUrl.buildUrl(`api/assets/${this.asset.id}/?q=${this.assetVersion}`); + return this.apiUrl.buildUrl(`api/assets/${this.asset.id}/?q=${this.assetUrlVersion}`); } public get fileType(): string { @@ -102,7 +108,7 @@ export class AssetComponent extends AppComponentBase implements OnInit { const me = `subject:${this.authService.user!.id}`; const asset = new AssetDto( - this.asset.id, + result.id, me, me, DateTime.now(), DateTime.now(), @@ -115,9 +121,12 @@ export class AssetComponent extends AppComponentBase implements OnInit { result.version); this.asset = asset; - this.assetVersion = MathHelper.guid(); + this.assetUrlVersion = MathHelper.guid(); + this.version = result.version; this.progress = 0; - }, 2000); + + this.loaded.emit(asset); + }, 500); } else { this.progress = result; } @@ -126,13 +135,15 @@ export class AssetComponent extends AppComponentBase implements OnInit { this.notifyError(error); }); + } else { + this.version = this.asset.version; } } public updateFile(files: FileList) { if (files.length === 1) { this.appName() - .switchMap(app => this.assetsService.replaceFile(app, this.asset.id, files[0])) + .switchMap(app => this.assetsService.replaceFile(app, this.asset.id, files[0], this.version)) .subscribe(result => { if (result instanceof AssetReplacedDto) { setTimeout(() => { @@ -149,10 +160,12 @@ export class AssetComponent extends AppComponentBase implements OnInit { result.pixelWidth, result.pixelHeight, result.version); + this.asset = asset; - this.assetVersion = MathHelper.guid(); + this.assetUrlVersion = MathHelper.guid(); this.progress = 0; - }, 2000); + this.retries = 0; + }, 500); } else { this.progress = result; } @@ -163,6 +176,16 @@ export class AssetComponent extends AppComponentBase implements OnInit { }); } } + + public retryLoadingImage() { + this.retries++; + + if (this.retries <= 10) { + setTimeout(() => { + this.assetUrlVersion = MathHelper.guid(); + }, this.retries * 1000); + } + } } function fileSize(b: number) { diff --git a/src/Squidex/app/features/assets/pages/assets-page.component.html b/src/Squidex/app/features/assets/pages/assets-page.component.html index 5444550c3..f1832f302 100644 --- a/src/Squidex/app/features/assets/pages/assets-page.component.html +++ b/src/Squidex/app/features/assets/pages/assets-page.component.html @@ -36,8 +36,13 @@
- - + + + +
diff --git a/src/Squidex/app/features/assets/pages/assets-page.component.ts b/src/Squidex/app/features/assets/pages/assets-page.component.ts index e2b580a06..8ca08ccfb 100644 --- a/src/Squidex/app/features/assets/pages/assets-page.component.ts +++ b/src/Squidex/app/features/assets/pages/assets-page.component.ts @@ -66,6 +66,28 @@ export class AssetsPageComponent extends AppComponentBase implements OnInit { }); } + public onAssetDeleting(asset: AssetDto) { + this.appName() + .switchMap(app => this.assetsService.deleteAsset(app, asset.id, asset.version)) + .subscribe(dtos => { + this.assetsItems = this.assetsItems.filter(x => x.id !== asset.id); + this.assetsPager = this.assetsPager.decrementCount(); + }, error => { + this.notifyError(error); + }); + } + + public onAssetLoaded(file: File, asset: AssetDto) { + this.newFiles = this.newFiles.remove(file); + + this.assetsItems = this.assetsItems.pushFront(asset); + this.assetsPager = this.assetsPager.incrementCount(); + } + + public onAssetFailed(file: File) { + this.newFiles = this.newFiles.remove(file); + } + public goNext() { this.assetsPager = this.assetsPager.goNext(); @@ -78,10 +100,6 @@ export class AssetsPageComponent extends AppComponentBase implements OnInit { this.load(); } - public removeFile(file: File) { - this.newFiles = this.newFiles.remove(file); - } - public addFiles(files: FileList) { for (let i = 0; i < files.length; i++) { this.newFiles = this.newFiles.pushFront(files[i]); diff --git a/src/Squidex/app/features/schemas/pages/schema/field.component.scss b/src/Squidex/app/features/schemas/pages/schema/field.component.scss index 48f8f2991..f762a1d67 100644 --- a/src/Squidex/app/features/schemas/pages/schema/field.component.scss +++ b/src/Squidex/app/features/schemas/pages/schema/field.component.scss @@ -36,7 +36,7 @@ $field-header: #e7ebef; &.active { background: $color-theme-blue; border-color: $color-theme-blue; - color: $color-accent-dark; + color: $color-dark-foreground; } } diff --git a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.html b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.html index ccc722830..77110ebeb 100644 --- a/src/Squidex/app/features/schemas/pages/schema/schema-page.component.html +++ b/src/Squidex/app/features/schemas/pages/schema/schema-page.component.html @@ -114,12 +114,7 @@
diff --git a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.html b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.html index 277d78f83..eb4f640ae 100644 --- a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.html +++ b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.html @@ -62,10 +62,7 @@
diff --git a/src/Squidex/app/framework/angular/autocomplete.component.html b/src/Squidex/app/framework/angular/autocomplete.component.html index 774dbb184..81dbeb283 100644 --- a/src/Squidex/app/framework/angular/autocomplete.component.html +++ b/src/Squidex/app/framework/angular/autocomplete.component.html @@ -1,5 +1,5 @@ - { + public replaceFile(appName: string, id: string, file: File, version?: Version): Observable { return new Observable(subscriber => { const url = this.apiUrl.buildUrl(`api/apps/${appName}/assets/${id}/content`); @@ -179,6 +179,10 @@ export class AssetsService { 'Authorization': `${this.authService.user.user.token_type} ${this.authService.user.user.access_token}` }); + if (version && version.value.length > 0) { + headers.append('If-Match', version.value); + } + content.append('file', file); this.http.withUploadProgressListener(progress => subscriber.next(progress.percentage)) @@ -203,4 +207,11 @@ export class AssetsService { }); }); } + + public deleteAsset(appName: string, id: string, version: Version): Observable { + const url = this.apiUrl.buildUrl(`api/apps/${appName}/assets/${id}`); + + return this.authService.authDelete(url, version) + .catchError('Failed to delete asset. Please reload.'); + } } \ No newline at end of file diff --git a/src/Squidex/app/shell/pages/home/home-page.component.scss b/src/Squidex/app/shell/pages/home/home-page.component.scss index e50190345..56f206fcd 100644 --- a/src/Squidex/app/shell/pages/home/home-page.component.scss +++ b/src/Squidex/app/shell/pages/home/home-page.component.scss @@ -50,7 +50,7 @@ $color-google-dark: #af2c1a; &-button { & { @include border-radius(1.5rem); - color: $color-accent-dark; + color: $color-dark-foreground; cursor: pointer; margin-top: 4rem; height: 3rem; diff --git a/src/Squidex/app/shell/pages/internal/apps-menu.component.html b/src/Squidex/app/shell/pages/internal/apps-menu.component.html index 7fd6c1dad..65a53d6f1 100644 --- a/src/Squidex/app/shell/pages/internal/apps-menu.component.html +++ b/src/Squidex/app/shell/pages/internal/apps-menu.component.html @@ -36,9 +36,7 @@ diff --git a/src/Squidex/app/shell/pages/internal/apps-menu.component.scss b/src/Squidex/app/shell/pages/internal/apps-menu.component.scss index ec59b86ca..c12761718 100644 --- a/src/Squidex/app/shell/pages/internal/apps-menu.component.scss +++ b/src/Squidex/app/shell/pages/internal/apps-menu.component.scss @@ -9,7 +9,7 @@ @include opacity(.95); @include no-selection; @include border-radius; - color: $color-accent-dark; + color: $color-dark-foreground; cursor: pointer; border: 0; background: $color-theme-blue-dark; diff --git a/src/Squidex/app/shell/pages/internal/apps-menu.component.ts b/src/Squidex/app/shell/pages/internal/apps-menu.component.ts index c4a43d53a..111da30ed 100644 --- a/src/Squidex/app/shell/pages/internal/apps-menu.component.ts +++ b/src/Squidex/app/shell/pages/internal/apps-menu.component.ts @@ -56,14 +56,6 @@ export class AppsMenuComponent implements OnInit, OnDestroy { this.appsStore.selectedApp.subscribe(selectedApp => this.appName = selectedApp ? selectedApp.name : FALLBACK_NAME); } - public onAppCreationCancelled() { - this.modalDialog.hide(); - } - - public onAppCreationCompleted(app: AppDto) { - this.modalDialog.hide(); - } - public createApp() { this.modalMenu.hide(); this.modalDialog.show(); diff --git a/src/Squidex/app/shell/pages/internal/internal-area.component.scss b/src/Squidex/app/shell/pages/internal/internal-area.component.scss index 24c06aa80..f9c3f8ce8 100644 --- a/src/Squidex/app/shell/pages/internal/internal-area.component.scss +++ b/src/Squidex/app/shell/pages/internal/internal-area.component.scss @@ -33,7 +33,7 @@ margin-top: .625rem; font-size: .8rem; font-weight: normal; - color: $color-accent-dark; + color: $color-dark-foreground; cursor: pointer; } diff --git a/src/Squidex/app/theme/_bootstrap.scss b/src/Squidex/app/theme/_bootstrap.scss index 6f97e0b5e..42ccba586 100644 --- a/src/Squidex/app/theme/_bootstrap.scss +++ b/src/Squidex/app/theme/_bootstrap.scss @@ -61,7 +61,7 @@ body { &.dropdown-item { &:active { - color: $color-accent-dark; + color: $color-dark-foreground; } } } @@ -208,11 +208,11 @@ body { @include box-shadow(0, 0, 10px, .5); background: $color-theme-blue; border-color: $color-theme-blue; - color: $color-accent-dark; + color: $color-dark-foreground; } &:hover { - color: $color-accent-dark; + color: $color-dark-foreground; } } diff --git a/src/Squidex/app/theme/_forms.scss b/src/Squidex/app/theme/_forms.scss index a946b35b7..6133c3a77 100644 --- a/src/Squidex/app/theme/_forms.scss +++ b/src/Squidex/app/theme/_forms.scss @@ -32,7 +32,7 @@ & { @include absolute(auto, auto, .4rem, 0); @include border-radius(2px); - color: $color-accent-dark; + color: $color-dark-foreground; cursor: none; display: inline-block; font-size: .9rem; @@ -68,7 +68,7 @@ select { .form-error { @include border-radius(4px); @include truncate; - color: $color-accent-dark; + color: $color-dark-foreground; margin-top: .25rem; margin-bottom: .5rem; padding: .5rem; @@ -106,10 +106,10 @@ select { .form-control-dark { & { @include transition(background-color .3s ease); - @include placeholder-color(darken($color-accent-dark, 30%)); + @include placeholder-color(darken($color-dark-foreground, 30%)); background: $color-dark2-control; border: 1px solid $color-dark2-control; - color: darken($color-accent-dark, 20%); + color: darken($color-dark-foreground, 20%); } &:focus { diff --git a/src/Squidex/app/theme/_lists.scss b/src/Squidex/app/theme/_lists.scss index 2cb1a81d5..75e66c018 100644 --- a/src/Squidex/app/theme/_lists.scss +++ b/src/Squidex/app/theme/_lists.scss @@ -62,7 +62,7 @@ &.active { background: $color-theme-blue; border-color: $color-theme-blue; - color: $color-accent-dark; + color: $color-dark-foreground; } } } diff --git a/src/Squidex/app/theme/_panels.scss b/src/Squidex/app/theme/_panels.scss index 5383b170f..65cd9f34e 100644 --- a/src/Squidex/app/theme/_panels.scss +++ b/src/Squidex/app/theme/_panels.scss @@ -111,7 +111,7 @@ } &.active { - color: $color-accent-dark; + color: $color-dark-foreground; border: 0; background: $color-theme-blue; } diff --git a/src/Squidex/app/theme/_vars.scss b/src/Squidex/app/theme/_vars.scss index 20effb18d..f4f1e443b 100644 --- a/src/Squidex/app/theme/_vars.scss +++ b/src/Squidex/app/theme/_vars.scss @@ -50,7 +50,8 @@ $color-table-header: #a0a0a0; $color-modal-header-background: #2e3842; $color-modal-header-foreground: #6a7681; -$color-accent-dark: #fff; +$color-dark-black: #000; +$color-dark-foreground: #fff; $size-navbar-height: 3.25rem; $size-sidebar-width: 7rem;