diff --git a/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetFoldersController.cs b/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetFoldersController.cs
index 7a18acd7c..22839c2ac 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetFoldersController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetFoldersController.cs
@@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
+using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -13,6 +14,7 @@ using Squidex.Areas.Api.Controllers.Assets.Models;
using Squidex.Domain.Apps.Entities.Assets;
using Squidex.Domain.Apps.Entities.Assets.Commands;
using Squidex.Infrastructure;
+using Squidex.Infrastructure.Collections;
using Squidex.Infrastructure.Commands;
using Squidex.Infrastructure.Tasks;
using Squidex.Shared;
@@ -39,6 +41,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
///
/// The name of the app.
/// The optional parent folder id.
+ /// The scope of the query.
///
/// 200 => Asset folders returned.
/// 404 => App not found.
@@ -51,11 +54,11 @@ namespace Squidex.Areas.Api.Controllers.Assets
[ProducesResponseType(typeof(AssetFoldersDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppAssetsRead)]
[ApiCosts(1)]
- public async Task GetAssetFolders(string app, [FromQuery] DomainId parentId)
+ public async Task GetAssetFolders(string app, [FromQuery] DomainId parentId, [FromQuery] AssetFolderScope scope = AssetFolderScope.PathAndItems)
{
var (folders, path) = await AsyncHelper.WhenAll(
- assetQuery.QueryAssetFoldersAsync(Context, parentId, HttpContext.RequestAborted),
- assetQuery.FindAssetFolderAsync(Context.App.Id, parentId, HttpContext.RequestAborted));
+ GetAssetFoldersAsync(parentId, scope),
+ GetAssetPathAsync(parentId, scope));
var response = Deferred.Response(() =>
{
@@ -170,5 +173,25 @@ namespace Squidex.Areas.Api.Controllers.Assets
return AssetFolderDto.FromAssetFolder(context.Result(), Resources);
}
+
+ private Task> GetAssetPathAsync(DomainId parentId, AssetFolderScope scope)
+ {
+ if (scope == AssetFolderScope.Items)
+ {
+ return Task.FromResult>(ImmutableList.Empty());
+ }
+
+ return assetQuery.FindAssetFolderAsync(Context.App.Id, parentId, HttpContext.RequestAborted);
+ }
+
+ private Task> GetAssetFoldersAsync(DomainId parentId, AssetFolderScope scope)
+ {
+ if (scope == AssetFolderScope.Path)
+ {
+ return Task.FromResult(ResultList.CreateFrom(0));
+ }
+
+ return assetQuery.QueryAssetFoldersAsync(Context, parentId, HttpContext.RequestAborted);
+ }
}
}
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetFolderScope.cs b/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetFolderScope.cs
new file mode 100644
index 000000000..a99f152b3
--- /dev/null
+++ b/backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetFolderScope.cs
@@ -0,0 +1,16 @@
+// ==========================================================================
+// Squidex Headless CMS
+// ==========================================================================
+// Copyright (c) Squidex UG (haftungsbeschraenkt)
+// All rights reserved. Licensed under the MIT license.
+// ==========================================================================
+
+namespace Squidex.Areas.Api.Controllers.Assets.Models
+{
+ public enum AssetFolderScope
+ {
+ PathAndItems,
+ Path,
+ Items
+ }
+}
diff --git a/frontend/app/shared/components/assets/asset-dialog.component.ts b/frontend/app/shared/components/assets/asset-dialog.component.ts
index 9e1d4745d..64532d3b3 100644
--- a/frontend/app/shared/components/assets/asset-dialog.component.ts
+++ b/frontend/app/shared/components/assets/asset-dialog.component.ts
@@ -89,7 +89,7 @@ export class AssetDialogComponent implements OnChanges {
this.annotateForm.setEnabled(this.isEditable);
this.path =
- this.assetsService.getAssetFolders(this.appsState.appName, this.asset.parentId).pipe(
+ this.assetsService.getAssetFolders(this.appsState.appName, this.asset.parentId, 'Path').pipe(
map(folders => [ROOT_ITEM, ...folders.path]));
}
diff --git a/frontend/app/shared/components/assets/asset-folder-dropdown-item.component.ts b/frontend/app/shared/components/assets/asset-folder-dropdown-item.component.ts
index 673793156..487060b92 100644
--- a/frontend/app/shared/components/assets/asset-folder-dropdown-item.component.ts
+++ b/frontend/app/shared/components/assets/asset-folder-dropdown-item.component.ts
@@ -61,7 +61,7 @@ export class AssetFolderDropdownItemComponent {
this.node.isLoading = true;
- this.assetsService.getAssetFolders(this.appName, this.node.item.id)
+ this.assetsService.getAssetFolders(this.appName, this.node.item.id, 'Items')
.subscribe({
next: dto => {
if (dto.items.length > 0) {
diff --git a/frontend/app/shared/components/assets/asset-folder-dropdown.component.ts b/frontend/app/shared/components/assets/asset-folder-dropdown.component.ts
index dd58ebcf9..3d46f752b 100644
--- a/frontend/app/shared/components/assets/asset-folder-dropdown.component.ts
+++ b/frontend/app/shared/components/assets/asset-folder-dropdown.component.ts
@@ -59,7 +59,7 @@ export class AssetFolderDropdownComponent extends StatefulControlComponent {
let parent = this.root;
diff --git a/frontend/app/shared/services/assets.service.spec.ts b/frontend/app/shared/services/assets.service.spec.ts
index 2f80e3661..e05ec2f9a 100644
--- a/frontend/app/shared/services/assets.service.spec.ts
+++ b/frontend/app/shared/services/assets.service.spec.ts
@@ -91,11 +91,11 @@ describe('AssetsService', () => {
inject([AssetsService, HttpTestingController], (assetsService: AssetsService, httpMock: HttpTestingController) => {
let assets: AssetFoldersDto;
- assetsService.getAssetFolders('my-app', 'parent1').subscribe(result => {
+ assetsService.getAssetFolders('my-app', 'parent1', 'Path').subscribe(result => {
assets = result;
});
- const req = httpMock.expectOne('http://service/p/api/apps/my-app/assets/folders?parentId=parent1');
+ const req = httpMock.expectOne('http://service/p/api/apps/my-app/assets/folders?parentId=parent1&scope=Path');
expect(req.request.method).toEqual('GET');
expect(req.request.headers.get('If-Match')).toBeNull();
diff --git a/frontend/app/shared/services/assets.service.ts b/frontend/app/shared/services/assets.service.ts
index 9e71200dd..835ec6817 100644
--- a/frontend/app/shared/services/assets.service.ts
+++ b/frontend/app/shared/services/assets.service.ts
@@ -135,6 +135,7 @@ export class AssetFolderDto {
type Tags = readonly string[];
+type AssetFolderScope = 'PathAndItems' | 'Path' | 'Items';
type AssetMetadata = { [key: string]: any };
export type AnnotateAssetDto =
@@ -247,8 +248,8 @@ export class AssetsService {
}
}
- public getAssetFolders(appName: string, parentId: string): Observable {
- const url = this.apiUrl.buildUrl(`api/apps/${appName}/assets/folders?parentId=${parentId}`);
+ public getAssetFolders(appName: string, parentId: string, scope: AssetFolderScope): Observable {
+ const url = this.apiUrl.buildUrl(`api/apps/${appName}/assets/folders?parentId=${parentId}&scope=${scope}`);
return this.http.get<{ total: number; items: any[]; folders: any[]; path: any[] } & Resource>(url).pipe(
map(({ total, items, path, _links }) => {