diff --git a/src/Squidex.Read.MongoDb/Assets/MongoAssetRepository.cs b/src/Squidex.Read.MongoDb/Assets/MongoAssetRepository.cs index 0eb212f9d..2c5c40dad 100644 --- a/src/Squidex.Read.MongoDb/Assets/MongoAssetRepository.cs +++ b/src/Squidex.Read.MongoDb/Assets/MongoAssetRepository.cs @@ -42,9 +42,9 @@ namespace Squidex.Read.MongoDb.Assets return await Collection.Find(x => x.Id == assetId).CountAsync() == 1; } - public async Task> QueryAsync(Guid appId, HashSet mimeTypes = null, string query = null, int take = 10, int skip = 0) + public async Task> QueryAsync(Guid appId, HashSet mimeTypes = null, HashSet ids = null, string query = null, int take = 10, int skip = 0) { - var filter = CreateFilter(appId, mimeTypes, query); + var filter = CreateFilter(appId, mimeTypes, ids, query); var assets = await Collection.Find(filter).Skip(skip).Limit(take).SortByDescending(x => x.LastModified).ToListAsync(); @@ -52,9 +52,9 @@ namespace Squidex.Read.MongoDb.Assets return assets.OfType().ToList(); } - public async Task CountAsync(Guid appId, HashSet mimeTypes = null, string query = null) + public async Task CountAsync(Guid appId, HashSet mimeTypes = null, HashSet ids = null, string query = null) { - var filter = CreateFilter(appId, mimeTypes, query); + var filter = CreateFilter(appId, mimeTypes, ids, query); var count = await Collection.Find(filter).CountAsync(); @@ -70,13 +70,18 @@ namespace Squidex.Read.MongoDb.Assets return entity; } - private static FilterDefinition CreateFilter(Guid appId, ICollection mimeTypes, string query) + private static FilterDefinition CreateFilter(Guid appId, ICollection mimeTypes, ICollection ids, string query) { var filters = new List> { Filter.Eq(x => x.AppId, appId) }; + if (ids != null && ids.Count > 0) + { + filters.Add(Filter.In(x => x.Id, ids)); + } + if (mimeTypes != null && mimeTypes.Count > 0) { filters.Add(Filter.In(x => x.MimeType, mimeTypes)); diff --git a/src/Squidex.Read/Assets/Repositories/IAssetRepository.cs b/src/Squidex.Read/Assets/Repositories/IAssetRepository.cs index f01676bc2..03de0f13a 100644 --- a/src/Squidex.Read/Assets/Repositories/IAssetRepository.cs +++ b/src/Squidex.Read/Assets/Repositories/IAssetRepository.cs @@ -14,9 +14,9 @@ namespace Squidex.Read.Assets.Repositories { public interface IAssetRepository { - Task> QueryAsync(Guid appId, HashSet mimeTypes = null, string query = null, int take = 10, int skip = 0); + Task> QueryAsync(Guid appId, HashSet mimeTypes = null, HashSet ids = null, string query = null, int take = 10, int skip = 0); - Task CountAsync(Guid appId, HashSet mimeTypes = null, string query = null); + Task CountAsync(Guid appId, HashSet mimeTypes = null, HashSet ids = null, string query = null); Task FindAssetAsync(Guid id); } diff --git a/src/Squidex/Controllers/Api/Assets/AssetContentController.cs b/src/Squidex/Controllers/Api/Assets/AssetContentController.cs index efae49e6f..d8ac35e3e 100644 --- a/src/Squidex/Controllers/Api/Assets/AssetContentController.cs +++ b/src/Squidex/Controllers/Api/Assets/AssetContentController.cs @@ -47,7 +47,7 @@ namespace Squidex.Controllers.Api.Assets { var asset = await assetRepository.FindAssetAsync(id); - if (asset == null || asset.FileVersion < version) + if (asset == null || asset.FileVersion < version || width == 0 || height == 0) { return NotFound(); } diff --git a/src/Squidex/Controllers/Api/Assets/AssetController.cs b/src/Squidex/Controllers/Api/Assets/AssetController.cs index f998b2357..9879094c3 100644 --- a/src/Squidex/Controllers/Api/Assets/AssetController.cs +++ b/src/Squidex/Controllers/Api/Assets/AssetController.cs @@ -14,8 +14,10 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; +using Microsoft.Extensions.Primitives; using NSwag.Annotations; using Squidex.Controllers.Api.Assets.Models; +using Squidex.Controllers.Api.Schemas.Models; using Squidex.Core.Identity; using Squidex.Infrastructure; using Squidex.Infrastructure.CQRS.Commands; @@ -53,6 +55,7 @@ namespace Squidex.Controllers.Api.Assets /// Get assets. /// /// The app where the assets belong to. + /// The optional asset ids. /// The number of assets to skip. /// The number of assets to take. /// The query to limit the files by name. @@ -64,7 +67,7 @@ namespace Squidex.Controllers.Api.Assets [HttpGet] [Route("apps/{app}/assets/")] [ProducesResponseType(typeof(AssetsDto), 200)] - public async Task GetAssets(string app, [FromQuery] string query = null, [FromQuery] string mimeTypes = null, [FromQuery] int skip = 0, [FromQuery] int take = 10) + public async Task GetAssets(string app, [FromQuery] string query = null, [FromQuery] string mimeTypes = null, [FromQuery] string ids = null, [FromQuery] int skip = 0, [FromQuery] int take = 10) { var mimeTypeList = new HashSet(); @@ -76,8 +79,21 @@ namespace Squidex.Controllers.Api.Assets } } - var taskForAssets = assetRepository.QueryAsync(AppId, mimeTypeList, query, take, skip); - var taskForCount = assetRepository.CountAsync(AppId, mimeTypeList, query); + var idsList = new HashSet(); + + if (!string.IsNullOrWhiteSpace(ids)) + { + foreach (var id in ids.Split(',')) + { + if (Guid.TryParse(id, out var guid)) + { + idsList.Add(guid); + } + } + } + + var taskForAssets = assetRepository.QueryAsync(AppId, mimeTypeList, idsList, query, take, skip); + var taskForCount = assetRepository.CountAsync(AppId, mimeTypeList, idsList, query); await Task.WhenAll(taskForAssets, taskForCount); @@ -90,6 +106,34 @@ namespace Squidex.Controllers.Api.Assets return Ok(model); } + /// + /// Get a asset by id. + /// + /// The id of the asset to retrieve. + /// The name of the app to get the asset from. + /// + /// 200 => Asset found. + /// 404 => Asset or app not found. + /// + [HttpGet] + [Route("apps/{app}/assets/{id}")] + [ProducesResponseType(typeof(AssetsDto), 200)] + public async Task GetAsset(string app, Guid id) + { + var entity = await assetRepository.FindAssetAsync(id); + + if (entity == null) + { + return NotFound(); + } + + var model = SimpleMapper.Map(entity, new AssetDto()); + + Response.Headers["ETag"] = new StringValues(entity.Version.ToString()); + + return Ok(model); + } + /// /// Upload a new asset. /// diff --git a/src/Squidex/Controllers/Api/Schemas/SchemasController.cs b/src/Squidex/Controllers/Api/Schemas/SchemasController.cs index f80373f17..187fabfd1 100644 --- a/src/Squidex/Controllers/Api/Schemas/SchemasController.cs +++ b/src/Squidex/Controllers/Api/Schemas/SchemasController.cs @@ -65,7 +65,7 @@ namespace Squidex.Controllers.Api.Schemas /// Get a schema by name. /// /// The name of the schema to retrieve. - /// The name of the app to create the schema to. + /// The name of the app to get the schema from. /// /// 200 => Schema found. /// 404 => Schema or app not found. diff --git a/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts b/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts index 749f5c32d..40cdf4ba3 100644 --- a/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts +++ b/src/Squidex/app/features/administration/pages/event-consumers/event-consumers-page.component.ts @@ -15,8 +15,7 @@ import { fadeAnimation, ImmutableArray, ModalView, - NotificationService, - UsersProviderService + NotificationService } from 'shared'; @Component({ @@ -34,10 +33,10 @@ export class EventConsumersPageComponent extends ComponentBase implements OnInit public eventConsumerError = ''; public eventConsumers = ImmutableArray.empty(); - constructor(notifications: NotificationService, users: UsersProviderService, + constructor(notifications: NotificationService, private readonly eventConsumersService: EventConsumersService ) { - super(notifications, users); + super(notifications); } public ngOnInit() { diff --git a/src/Squidex/app/features/administration/pages/users/users-page.component.ts b/src/Squidex/app/features/administration/pages/users/users-page.component.ts index 75b8f7530..79877d0fc 100644 --- a/src/Squidex/app/features/administration/pages/users/users-page.component.ts +++ b/src/Squidex/app/features/administration/pages/users/users-page.component.ts @@ -15,8 +15,7 @@ import { NotificationService, Pager, UserDto, - UserManagementService, - UsersProviderService + UserManagementService } from 'shared'; @Component({ @@ -32,11 +31,11 @@ export class UsersPageComponent extends ComponentBase implements OnInit { public usersFilter = new FormControl(); public usersQuery = ''; - constructor(notifications: NotificationService, users: UsersProviderService, + constructor(notifications: NotificationService, private readonly userManagementService: UserManagementService, private readonly authService: AuthService ) { - super(notifications, users); + super(notifications); } public ngOnInit() { diff --git a/src/Squidex/app/features/assets/declarations.ts b/src/Squidex/app/features/assets/declarations.ts index 260478be7..0cc787227 100644 --- a/src/Squidex/app/features/assets/declarations.ts +++ b/src/Squidex/app/features/assets/declarations.ts @@ -5,5 +5,4 @@ * Copyright (c) Sebastian Stehle. All rights reserved */ -export * from './pages/asset.component'; export * from './pages/assets-page.component'; \ No newline at end of file diff --git a/src/Squidex/app/features/assets/module.ts b/src/Squidex/app/features/assets/module.ts index 41ee6a238..7c799333b 100644 --- a/src/Squidex/app/features/assets/module.ts +++ b/src/Squidex/app/features/assets/module.ts @@ -7,11 +7,11 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; +import { DndModule } from 'ng2-dnd'; -import { SqxFrameworkModule } from 'shared'; +import { SqxFrameworkModule, SqxSharedModule } from 'shared'; import { - AssetComponent, AssetsPageComponent } from './declarations'; @@ -25,10 +25,11 @@ const routes: Routes = [ @NgModule({ imports: [ SqxFrameworkModule, + SqxSharedModule, + DndModule, RouterModule.forChild(routes) ], declarations: [ - AssetComponent, AssetsPageComponent ] }) 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 7c87887a2..1dbe09953 100644 --- a/src/Squidex/app/features/assets/pages/assets-page.component.html +++ b/src/Squidex/app/features/assets/pages/assets-page.component.html @@ -40,7 +40,7 @@ (failed)="onAssetFailed(file)" (loaded)="onAssetLoaded(file, $event)"> - diff --git a/src/Squidex/app/features/assets/pages/assets-page.component.scss b/src/Squidex/app/features/assets/pages/assets-page.component.scss index e392eee55..e90403286 100644 --- a/src/Squidex/app/features/assets/pages/assets-page.component.scss +++ b/src/Squidex/app/features/assets/pages/assets-page.component.scss @@ -52,4 +52,8 @@ .col-3 { padding-left: 8px; padding-right: 8px; +} + +.dnd-sortable-drag { + border: 0; } \ No newline at end of file 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 8ca08ccfb..49e93b7a9 100644 --- a/src/Squidex/app/features/assets/pages/assets-page.component.ts +++ b/src/Squidex/app/features/assets/pages/assets-page.component.ts @@ -18,8 +18,7 @@ import { fadeAnimation, ImmutableArray, NotificationService, - Pager, - UsersProviderService + Pager } from 'shared'; @Component({ @@ -38,10 +37,10 @@ export class AssetsPageComponent extends AppComponentBase implements OnInit { public assetsFilter = new FormControl(); public assertQuery = ''; - constructor(apps: AppsStoreService, notifications: NotificationService, users: UsersProviderService, + constructor(apps: AppsStoreService, notifications: NotificationService, private readonly assetsService: AssetsService ) { - super(notifications, users, apps); + super(notifications, apps); } public ngOnInit() { @@ -57,7 +56,7 @@ export class AssetsPageComponent extends AppComponentBase implements OnInit { private load() { this.appName() - .switchMap(app => this.assetsService.getAssets(app, this.assetsPager.pageSize, this.assetsPager.skip, this.assertQuery, null)) + .switchMap(app => this.assetsService.getAssets(app, this.assetsPager.pageSize, this.assetsPager.skip, this.assertQuery, null, null)) .subscribe(dtos => { this.assetsItems = ImmutableArray.of(dtos.items); this.assetsPager = this.assetsPager.setCount(dtos.total); diff --git a/src/Squidex/app/features/content/pages/content/content-field.component.html b/src/Squidex/app/features/content/pages/content/content-field.component.html index e9ad8b7c7..df2ffb2b6 100644 --- a/src/Squidex/app/features/content/pages/content/content-field.component.html +++ b/src/Squidex/app/features/content/pages/content/content-field.component.html @@ -91,9 +91,9 @@ 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 7cd5ca13a..732f0fb77 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 @@ -28,7 +28,6 @@ import { NumberFieldPropertiesDto, SchemaDetailsDto, StringFieldPropertiesDto, - UsersProviderService, ValidatorsEx, Version } from 'shared'; @@ -53,14 +52,14 @@ export class ContentPageComponent extends AppComponentBase implements OnDestroy, public languages: AppLanguageDto[] = []; - constructor(apps: AppsStoreService, notifications: NotificationService, users: UsersProviderService, + constructor(apps: AppsStoreService, notifications: NotificationService, private readonly contentsService: ContentsService, private readonly location: Location, private readonly route: ActivatedRoute, private readonly router: Router, private readonly messageBus: MessageBus ) { - super(notifications, users, apps); + super(notifications, apps); } public ngOnDestroy() { diff --git a/src/Squidex/app/features/content/pages/contents/content-item.component.html b/src/Squidex/app/features/content/pages/contents/content-item.component.html index 39c7edb48..9cae38ff1 100644 --- a/src/Squidex/app/features/content/pages/contents/content-item.component.html +++ b/src/Squidex/app/features/content/pages/contents/content-item.component.html @@ -8,7 +8,7 @@ {{content.lastModified | fromNow}} - +
- {{userName(schema.lastModifiedBy, true) | async}} + {{schema.lastModifiedBy | userNameRef}}
diff --git a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts index 888c3b77c..48296e899 100644 --- a/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts +++ b/src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts @@ -22,7 +22,6 @@ import { NotificationService, SchemaDto, SchemasService, - UsersProviderService, Version } from 'shared'; @@ -47,13 +46,13 @@ export class SchemasPageComponent extends AppComponentBase implements OnDestroy, public schemasFilter = new FormControl(); public schemasFiltered = ImmutableArray.empty(); - constructor(apps: AppsStoreService, notifications: NotificationService, users: UsersProviderService, + constructor(apps: AppsStoreService, notifications: NotificationService, private readonly schemasService: SchemasService, private readonly authService: AuthService, private readonly messageBus: MessageBus, private readonly route: ActivatedRoute ) { - super(notifications, users, apps); + super(notifications, apps); } public ngOnDestroy() { diff --git a/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts b/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts index 48d0362f7..64b365589 100644 --- a/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts +++ b/src/Squidex/app/features/settings/pages/clients/clients-page.component.ts @@ -19,7 +19,6 @@ import { MessageBus, NotificationService, UpdateAppClientDto, - UsersProviderService, ValidatorsEx, Version } from 'shared'; @@ -48,12 +47,12 @@ export class ClientsPageComponent extends AppComponentBase implements OnInit { return this.addClientForm.controls['name'].value && this.addClientForm.controls['name'].value.length > 0; } - constructor(apps: AppsStoreService, notifications: NotificationService, users: UsersProviderService, + constructor(apps: AppsStoreService, notifications: NotificationService, private readonly appClientsService: AppClientsService, private readonly messageBus: MessageBus, private readonly formBuilder: FormBuilder ) { - super(notifications, users, apps); + super(notifications, apps); } public ngOnInit() { diff --git a/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.html b/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.html index 18e640339..6407a4d3a 100644 --- a/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.html +++ b/src/Squidex/app/features/settings/pages/contributors/contributors-page.component.html @@ -43,13 +43,13 @@ - + - {{userName(contributor.contributorId) | async}} + {{contributor.contributorId | userName}} - {{userEmail(contributor.contributorId) | async}} + {{contributor.contributorId | userEmail}}