Browse Source

API refined

pull/65/head
Sebastian Stehle 10 years ago
parent
commit
8930a20170
  1. 13
      src/Squidex/Controllers/Api/Assets/AssetController.cs
  2. 43
      src/Squidex/Controllers/Api/Assets/Models/AssetCreatedDto.cs
  3. 25
      src/Squidex/Controllers/Api/Assets/Models/AssetDto.cs
  4. 63
      src/Squidex/Controllers/Api/Assets/Models/AssetReplacedDto.cs
  5. 2
      src/Squidex/Controllers/Api/Schemas/SchemaFieldsController.cs
  6. 35
      src/Squidex/app/features/assets/pages/asset.component.ts
  7. 36
      src/Squidex/app/shared/services/assets.service.ts

13
src/Squidex/Controllers/Api/Assets/AssetController.cs

@ -90,7 +90,7 @@ namespace Squidex.Controllers.Api.Assets
} }
/// <summary> /// <summary>
/// Creates and uploads a new asset. /// Upload a new asset.
/// </summary> /// </summary>
/// <param name="app">The app where the asset is a part of.</param> /// <param name="app">The app where the asset is a part of.</param>
/// <param name="file">The file to upload.</param> /// <param name="file">The file to upload.</param>
@ -101,7 +101,7 @@ namespace Squidex.Controllers.Api.Assets
/// </returns> /// </returns>
[HttpPost] [HttpPost]
[Route("apps/{app}/assets/")] [Route("apps/{app}/assets/")]
[ProducesResponseType(typeof(AssetDto), 201)] [ProducesResponseType(typeof(AssetCreatedDto), 201)]
[ProducesResponseType(typeof(ErrorDto), 400)] [ProducesResponseType(typeof(ErrorDto), 400)]
public async Task<IActionResult> PostAsset(string app, List<IFormFile> file) public async Task<IActionResult> PostAsset(string app, List<IFormFile> file)
{ {
@ -111,13 +111,13 @@ namespace Squidex.Controllers.Api.Assets
var context = await CommandBus.PublishAsync(command); var context = await CommandBus.PublishAsync(command);
var result = context.Result<EntityCreatedResult<Guid>>(); var result = context.Result<EntityCreatedResult<Guid>>();
var response = AssetDto.Create(command, result); var response = AssetCreatedDto.Create(command, result);
return StatusCode(201, response); return StatusCode(201, response);
} }
/// <summary> /// <summary>
/// Replaces the content of the asset with a newer version. /// Replace asset content.
/// </summary> /// </summary>
/// <param name="app">The app where the asset is a part of.</param> /// <param name="app">The app where the asset is a part of.</param>
/// <param name="id">The id of the asset.</param> /// <param name="id">The id of the asset.</param>
@ -129,7 +129,7 @@ namespace Squidex.Controllers.Api.Assets
/// </returns> /// </returns>
[HttpPut] [HttpPut]
[Route("apps/{app}/assets/{id}/content")] [Route("apps/{app}/assets/{id}/content")]
[ProducesResponseType(typeof(AssetDto), 201)] [ProducesResponseType(typeof(AssetReplacedDto), 201)]
[ProducesResponseType(typeof(ErrorDto), 400)] [ProducesResponseType(typeof(ErrorDto), 400)]
public async Task<IActionResult> PutAssetContent(string app, Guid id, List<IFormFile> file) public async Task<IActionResult> PutAssetContent(string app, Guid id, List<IFormFile> file)
{ {
@ -139,7 +139,7 @@ namespace Squidex.Controllers.Api.Assets
var context = await CommandBus.PublishAsync(command); var context = await CommandBus.PublishAsync(command);
var result = context.Result<EntitySavedResult>(); var result = context.Result<EntitySavedResult>();
var response = AssetUpdatedDto.Create(command, result); var response = AssetReplacedDto.Create(command, result);
return StatusCode(201, response); return StatusCode(201, response);
} }
@ -152,6 +152,7 @@ namespace Squidex.Controllers.Api.Assets
/// <param name="request">The asset object that needs to updated.</param> /// <param name="request">The asset object that needs to updated.</param>
/// <returns> /// <returns>
/// 204 => Asset updated. /// 204 => Asset updated.
/// 400 => Asset name not valid.
/// 404 => Asset or app not found. /// 404 => Asset or app not found.
/// </returns> /// </returns>
[HttpPut] [HttpPut]

43
src/Squidex/Controllers/Api/Assets/Models/AssetUpdatedDto.cs → src/Squidex/Controllers/Api/Assets/Models/AssetCreatedDto.cs

@ -1,21 +1,31 @@
// ========================================================================== // ==========================================================================
// AssetUpdatedDto.cs // AssetDto.cs
// Squidex Headless CMS // Squidex Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) Squidex Group // Copyright (c) Squidex Group
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using NodaTime;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Commands; using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Write.Assets.Commands; using Squidex.Write.Assets.Commands;
namespace Squidex.Controllers.Api.Assets.Models namespace Squidex.Controllers.Api.Assets.Models
{ {
public sealed class AssetUpdatedDto public sealed class AssetCreatedDto
{ {
/// <summary>
/// The id of the asset.
/// </summary>
public Guid Id { get; set; }
/// <summary>
/// The file name.
/// </summary>
[Required]
public string FileName { get; set; }
/// <summary> /// <summary>
/// The mime type. /// The mime type.
/// </summary> /// </summary>
@ -42,36 +52,23 @@ namespace Squidex.Controllers.Api.Assets.Models
/// </summary> /// </summary>
public int? PixelHeight { get; set; } public int? PixelHeight { get; set; }
/// <summary>
/// The user that has updated the asset.
/// </summary>
[Required]
public RefToken LastModifiedBy { get; set; }
/// <summary>
/// The date and time when the asset has been modified last.
/// </summary>
public Instant LastModified { get; set; }
/// <summary> /// <summary>
/// The version of the asset. /// The version of the asset.
/// </summary> /// </summary>
public long Version { get; set; } public long Version { get; set; }
public static AssetUpdatedDto Create(UpdateAsset command, EntitySavedResult result) public static AssetCreatedDto Create(CreateAsset command, EntityCreatedResult<Guid> result)
{ {
var now = SystemClock.Instance.GetCurrentInstant(); var response = new AssetCreatedDto
var response = new AssetUpdatedDto
{ {
Version = result.Version, Id = command.AssetId,
LastModified = now, FileName = command.File.FileName,
LastModifiedBy = command.Actor,
FileSize = command.File.FileSize, FileSize = command.File.FileSize,
MimeType = command.File.MimeType, MimeType = command.File.MimeType,
IsImage = command.ImageInfo != null, IsImage = command.ImageInfo != null,
PixelWidth = command.ImageInfo?.PixelWidth, PixelWidth = command.ImageInfo?.PixelWidth,
PixelHeight = command.ImageInfo?.PixelHeight PixelHeight = command.ImageInfo?.PixelHeight,
Version = result.Version
}; };
return response; return response;

25
src/Squidex/Controllers/Api/Assets/Models/AssetDto.cs

@ -10,8 +10,6 @@ using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using NodaTime; using NodaTime;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Write.Assets.Commands;
namespace Squidex.Controllers.Api.Assets.Models namespace Squidex.Controllers.Api.Assets.Models
{ {
@ -80,28 +78,5 @@ namespace Squidex.Controllers.Api.Assets.Models
/// The version of the asset. /// The version of the asset.
/// </summary> /// </summary>
public long Version { get; set; } public long Version { get; set; }
public static AssetDto Create(CreateAsset command, EntityCreatedResult<Guid> result)
{
var now = SystemClock.Instance.GetCurrentInstant();
var response = new AssetDto
{
Id = result.IdOrValue,
Version = result.Version,
Created = now,
CreatedBy = command.Actor,
LastModified = now,
LastModifiedBy = command.Actor,
FileName = command.File.FileName,
FileSize = command.File.FileSize,
MimeType = command.File.MimeType,
IsImage = command.ImageInfo != null,
PixelWidth = command.ImageInfo?.PixelWidth,
PixelHeight = command.ImageInfo?.PixelHeight
};
return response;
}
} }
} }

63
src/Squidex/Controllers/Api/Assets/Models/AssetReplacedDto.cs

@ -0,0 +1,63 @@
// ==========================================================================
// AssetUpdatedDto.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.ComponentModel.DataAnnotations;
using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Write.Assets.Commands;
namespace Squidex.Controllers.Api.Assets.Models
{
public sealed class AssetReplacedDto
{
/// <summary>
/// The mime type.
/// </summary>
[Required]
public string MimeType { get; set; }
/// <summary>
/// The size of the file in bytes.
/// </summary>
public long FileSize { get; set; }
/// <summary>
/// Determines of the created file is an image.
/// </summary>
public bool IsImage { get; set; }
/// <summary>
/// The width of the image in pixels if the asset is an image.
/// </summary>
public int? PixelWidth { get; set; }
/// <summary>
/// The height of the image in pixels if the asset is an image.
/// </summary>
public int? PixelHeight { get; set; }
/// <summary>
/// The version of the asset.
/// </summary>
public long Version { get; set; }
public static AssetReplacedDto Create(UpdateAsset command, EntitySavedResult result)
{
var response = new AssetReplacedDto
{
FileSize = command.File.FileSize,
MimeType = command.File.MimeType,
IsImage = command.ImageInfo != null,
PixelWidth = command.ImageInfo?.PixelWidth,
PixelHeight = command.ImageInfo?.PixelHeight,
Version = result.Version
};
return response;
}
}
}

2
src/Squidex/Controllers/Api/Schemas/SchemaFieldsController.cs

@ -33,7 +33,7 @@ namespace Squidex.Controllers.Api.Schemas
} }
/// <summary> /// <summary>
/// Create a new schema field. /// Add a schema field.
/// </summary> /// </summary>
/// <param name="app">The name of the app.</param> /// <param name="app">The name of the app.</param>
/// <param name="name">The name of the schema.</param> /// <param name="name">The name of the schema.</param>

35
src/Squidex/app/features/assets/pages/asset.component.ts

@ -11,9 +11,12 @@ import {
ApiUrlConfig, ApiUrlConfig,
AppComponentBase, AppComponentBase,
AppsStoreService, AppsStoreService,
AssetCreatedDto,
AssetDto, AssetDto,
AssetUpdatedDto, AssetReplacedDto,
AssetsService, AssetsService,
AuthService,
DateTime,
fadeAnimation, fadeAnimation,
MathHelper, MathHelper,
NotificationService, NotificationService,
@ -77,6 +80,7 @@ export class AssetComponent extends AppComponentBase implements OnInit {
constructor(apps: AppsStoreService, notifications: NotificationService, users: UsersProviderService, constructor(apps: AppsStoreService, notifications: NotificationService, users: UsersProviderService,
private readonly assetsService: AssetsService, private readonly assetsService: AssetsService,
private readonly authService: AuthService,
private readonly apiUrl: ApiUrlConfig private readonly apiUrl: ApiUrlConfig
) { ) {
super(notifications, users, apps); super(notifications, users, apps);
@ -89,9 +93,24 @@ export class AssetComponent extends AppComponentBase implements OnInit {
this.appName() this.appName()
.switchMap(app => this.assetsService.uploadFile(app, initFile)) .switchMap(app => this.assetsService.uploadFile(app, initFile))
.subscribe(result => { .subscribe(result => {
if (result instanceof AssetDto) { if (result instanceof AssetCreatedDto) {
setTimeout(() => { setTimeout(() => {
this.asset = result; const me = `subject:${this.authService.user!.id}`;
const asset = new AssetDto(
this.asset.id,
me, me,
DateTime.now(),
DateTime.now(),
result.fileName,
result.fileSize,
result.mimeType,
result.isImage,
result.pixelWidth,
result.pixelHeight,
result.version);
this.asset = asset;
this.assetVersion = MathHelper.guid(); this.assetVersion = MathHelper.guid();
this.progress = 0; this.progress = 0;
}, 2000); }, 2000);
@ -111,14 +130,14 @@ export class AssetComponent extends AppComponentBase implements OnInit {
this.appName() this.appName()
.switchMap(app => this.assetsService.replaceFile(app, this.asset.id, files[0])) .switchMap(app => this.assetsService.replaceFile(app, this.asset.id, files[0]))
.subscribe(result => { .subscribe(result => {
if (result instanceof AssetUpdatedDto) { if (result instanceof AssetReplacedDto) {
setTimeout(() => { setTimeout(() => {
const me = `subject:${this.authService.user!.id}`;
const asset = new AssetDto( const asset = new AssetDto(
this.asset.id, this.asset.id,
this.asset.createdBy, this.asset.createdBy, me,
result.lastModifiedBy, this.asset.created, DateTime.now(),
this.asset.created,
result.lastModified,
this.asset.fileName, this.asset.fileName,
result.fileSize, result.fileSize,
result.mimeType, result.mimeType,

36
src/Squidex/app/shared/services/assets.service.ts

@ -44,10 +44,22 @@ export class AssetDto {
} }
} }
export class AssetUpdatedDto { export class AssetCreatedDto {
constructor(
public readonly id: string,
public readonly fileName: string,
public readonly fileSize: number,
public readonly mimeType: string,
public readonly isImage: boolean,
public readonly pixelWidth: number | null,
public readonly pixelHeight: number | null,
public readonly version: Version
) {
}
}
export class AssetReplacedDto {
constructor( constructor(
public readonly lastModifiedBy: string,
public readonly lastModified: DateTime,
public readonly fileSize: number, public readonly fileSize: number,
public readonly mimeType: string, public readonly mimeType: string,
public readonly isImage: boolean, public readonly isImage: boolean,
@ -122,8 +134,8 @@ export class AssetsService {
.catchError('Failed to load assets. Please reload.'); .catchError('Failed to load assets. Please reload.');
} }
public uploadFile(appName: string, file: File): Observable<number | AssetDto> { public uploadFile(appName: string, file: File): Observable<number | AssetCreatedDto> {
return new Observable<number | AssetDto>(subscriber => { return new Observable<number | AssetCreatedDto>(subscriber => {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/assets/`); const url = this.apiUrl.buildUrl(`api/apps/${appName}/assets/`);
const content = new FormData(); const content = new FormData();
@ -137,12 +149,8 @@ export class AssetsService {
.post(url, content, { headers }) .post(url, content, { headers })
.map(response => response.json()) .map(response => response.json())
.map(response => { .map(response => {
return new AssetDto( return new AssetCreatedDto(
response.id, response.id,
response.createdBy,
response.lastModifiedBy,
DateTime.parseISO_UTC(response.created),
DateTime.parseISO_UTC(response.lastModified),
response.fileName, response.fileName,
response.fileSize, response.fileSize,
response.mimeType, response.mimeType,
@ -162,8 +170,8 @@ export class AssetsService {
}); });
} }
public replaceFile(appName: string, id: string, file: File): Observable<number | AssetUpdatedDto> { public replaceFile(appName: string, id: string, file: File): Observable<number | AssetReplacedDto> {
return new Observable<number | AssetDto>(subscriber => { return new Observable<number | AssetReplacedDto>(subscriber => {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/assets/${id}/content`); const url = this.apiUrl.buildUrl(`api/apps/${appName}/assets/${id}/content`);
const content = new FormData(); const content = new FormData();
@ -177,9 +185,7 @@ export class AssetsService {
.put(url, content, { headers }) .put(url, content, { headers })
.map(response => response.json()) .map(response => response.json())
.map(response => { .map(response => {
return new AssetUpdatedDto( return new AssetReplacedDto(
response.lastModifiedBy,
DateTime.parseISO_UTC(response.lastModified),
response.fileSize, response.fileSize,
response.mimeType, response.mimeType,
response.isImage, response.isImage,

Loading…
Cancel
Save