Skip to content

Commit 985975f

Browse files
authored
Merge pull request #2010 from umbraco/14/bugfix/calculate-user-start-nodes
Bugfix: Render calculated user start nodes in User Workspace
2 parents 9077e80 + 5397c7b commit 985975f

File tree

13 files changed

+771
-628
lines changed

13 files changed

+771
-628
lines changed

src/external/backend-api/src/models.ts

Lines changed: 608 additions & 593 deletions
Large diffs are not rendered by default.

src/external/backend-api/src/services.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8566,6 +8566,29 @@ providerName
85668566
});
85678567
}
85688568

8569+
/**
8570+
* @returns unknown OK
8571+
* @throws ApiError
8572+
*/
8573+
public static getUserByIdCalculateStartNodes(data: UserData['payloads']['GetUserByIdCalculateStartNodes']): CancelablePromise<UserData['responses']['GetUserByIdCalculateStartNodes']> {
8574+
const {
8575+
8576+
id
8577+
} = data;
8578+
return __request(OpenAPI, {
8579+
method: 'GET',
8580+
url: '/umbraco/management/api/v1/user/{id}/calculate-start-nodes',
8581+
path: {
8582+
id
8583+
},
8584+
errors: {
8585+
401: `The resource is protected and requires an authentication token`,
8586+
403: `The authenticated user do not have access to this resource`,
8587+
404: `Not Found`,
8588+
},
8589+
});
8590+
}
8591+
85698592
/**
85708593
* @returns string OK
85718594
* @throws ApiError

src/mocks/data/user/user.db.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class UmbUserMockDB extends UmbEntityMockDbBase<UmbMockUserModel> {
7676
hasAccessToSensitiveData: true,
7777
avatarUrls: [],
7878
hasAccessToAllLanguages: true,
79-
languageIsoCode: firstUser.languageIsoCode,
79+
languageIsoCode: firstUser.languageIsoCode || null,
8080
languages: [],
8181
documentStartNodeIds: firstUser.documentStartNodeIds,
8282
mediaStartNodeIds: firstUser.mediaStartNodeIds,

src/packages/core/repository/detail/detail-data-source.interface.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ import type { UmbDataSourceResponse } from '../data-source-response.interface.js
22
import type { UmbReadDetailDataSource } from './read/index.js';
33
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
44

5-
export interface UmbDetailDataSourceConstructor<DetailType = any> {
6-
new (host: UmbControllerHost): UmbDetailDataSource<DetailType>;
5+
export interface UmbDetailDataSourceConstructor<
6+
DetailType = any,
7+
UmbDetailDataSourceType extends UmbDetailDataSource<DetailType> = UmbDetailDataSource<DetailType>,
8+
> {
9+
new (host: UmbControllerHost): UmbDetailDataSourceType;
710
}
811

912
export interface UmbDetailDataSource<DetailType> extends UmbReadDetailDataSource<DetailType> {

src/packages/core/repository/detail/detail-repository-base.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,17 @@ import type { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
88
import type { UmbDetailStore } from '@umbraco-cms/backoffice/store';
99
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
1010

11-
export abstract class UmbDetailRepositoryBase<DetailModelType extends { unique: string; entityType: string }>
11+
export abstract class UmbDetailRepositoryBase<
12+
DetailModelType extends { unique: string; entityType: string },
13+
UmbDetailDataSourceType extends UmbDetailDataSource<DetailModelType> = UmbDetailDataSource<DetailModelType>,
14+
>
1215
extends UmbRepositoryBase
1316
implements UmbDetailRepository<DetailModelType>, UmbApi
1417
{
1518
#init: Promise<unknown>;
1619

1720
#detailStore?: UmbDetailStore<DetailModelType>;
18-
#detailSource: UmbDetailDataSource<DetailModelType>;
21+
protected detailDataSource: UmbDetailDataSourceType;
1922
#notificationContext?: UmbNotificationContext;
2023

2124
constructor(
@@ -25,7 +28,7 @@ export abstract class UmbDetailRepositoryBase<DetailModelType extends { unique:
2528
) {
2629
super(host);
2730

28-
this.#detailSource = new detailSource(host);
31+
this.detailDataSource = new detailSource(host) as UmbDetailDataSourceType;
2932

3033
this.#init = Promise.all([
3134
this.consumeContext(detailStoreContextAlias, (instance) => {
@@ -45,7 +48,7 @@ export abstract class UmbDetailRepositoryBase<DetailModelType extends { unique:
4548
* @memberof UmbDetailRepositoryBase
4649
*/
4750
async createScaffold(preset?: Partial<DetailModelType>) {
48-
return this.#detailSource.createScaffold(preset);
51+
return this.detailDataSource.createScaffold(preset);
4952
}
5053

5154
/**
@@ -58,7 +61,7 @@ export abstract class UmbDetailRepositoryBase<DetailModelType extends { unique:
5861
if (!unique) throw new Error('Unique is missing');
5962
await this.#init;
6063

61-
const { data, error } = await this.#detailSource.read(unique);
64+
const { data, error } = await this.detailDataSource.read(unique);
6265

6366
if (data) {
6467
this.#detailStore!.append(data);
@@ -78,7 +81,7 @@ export abstract class UmbDetailRepositoryBase<DetailModelType extends { unique:
7881
if (!model) throw new Error('Data is missing');
7982
await this.#init;
8083

81-
const { data: createdData, error } = await this.#detailSource.create(model, parentUnique);
84+
const { data: createdData, error } = await this.detailDataSource.create(model, parentUnique);
8285

8386
if (createdData) {
8487
this.#detailStore?.append(createdData);
@@ -102,7 +105,7 @@ export abstract class UmbDetailRepositoryBase<DetailModelType extends { unique:
102105
if (!model.unique) throw new Error('Unique is missing');
103106
await this.#init;
104107

105-
const { data: updatedData, error } = await this.#detailSource.update(model);
108+
const { data: updatedData, error } = await this.detailDataSource.update(model);
106109

107110
if (updatedData) {
108111
this.#detailStore!.updateItem(model.unique, updatedData);
@@ -125,7 +128,7 @@ export abstract class UmbDetailRepositoryBase<DetailModelType extends { unique:
125128
if (!unique) throw new Error('Unique is missing');
126129
await this.#init;
127130

128-
const { error } = await this.#detailSource.delete(unique);
131+
const { error } = await this.detailDataSource.delete(unique);
129132

130133
if (!error) {
131134
this.#detailStore!.removeItem(unique);
@@ -152,7 +155,7 @@ export abstract class UmbDetailRepositoryBase<DetailModelType extends { unique:
152155

153156
override destroy(): void {
154157
this.#detailStore = undefined;
155-
(this.#detailSource as any) = undefined;
158+
(this.detailDataSource as any) = undefined;
156159
super.destroy();
157160
}
158161
}

src/packages/user/user/components/user-document-start-node/user-document-start-node.element.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,18 @@ import { UmbDocumentItemRepository } from '@umbraco-cms/backoffice/document';
55

66
@customElement('umb-user-document-start-node')
77
export class UmbUserDocumentStartNodeElement extends UmbLitElement {
8+
#uniques: Array<string> = [];
89
@property({ type: Array, attribute: false })
9-
uniques: Array<string> = [];
10+
public get uniques(): Array<string> {
11+
return this.#uniques;
12+
}
13+
public set uniques(value: Array<string>) {
14+
this.#uniques = value;
15+
16+
if (this.#uniques.length > 0) {
17+
this.#observeItems();
18+
}
19+
}
1020

1121
@property({ type: Boolean })
1222
readonly = false;
@@ -16,10 +26,12 @@ export class UmbUserDocumentStartNodeElement extends UmbLitElement {
1626

1727
#itemRepository = new UmbDocumentItemRepository(this);
1828

19-
protected override async firstUpdated(): Promise<void> {
20-
if (this.uniques.length === 0) return;
21-
const { data } = await this.#itemRepository.requestItems(this.uniques);
22-
this._displayValue = data || [];
29+
async #observeItems() {
30+
const { asObservable } = await this.#itemRepository.requestItems(this.#uniques);
31+
32+
this.observe(asObservable(), (data) => {
33+
this._displayValue = data || [];
34+
});
2335
}
2436

2537
override render() {

src/packages/user/user/components/user-media-start-node/user-media-start-node.element.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,18 @@ import { UmbMediaItemRepository } from '@umbraco-cms/backoffice/media';
55

66
@customElement('umb-user-media-start-node')
77
export class UmbUserMediaStartNodeElement extends UmbLitElement {
8+
#uniques: Array<string> = [];
89
@property({ type: Array, attribute: false })
9-
uniques: Array<string> = [];
10+
public get uniques(): Array<string> {
11+
return this.#uniques;
12+
}
13+
public set uniques(value: Array<string>) {
14+
this.#uniques = value;
15+
16+
if (this.#uniques.length > 0) {
17+
this.#observeItems();
18+
}
19+
}
1020

1121
@property({ type: Boolean })
1222
readonly = false;
@@ -16,10 +26,12 @@ export class UmbUserMediaStartNodeElement extends UmbLitElement {
1626

1727
#itemRepository = new UmbMediaItemRepository(this);
1828

19-
protected override async firstUpdated(): Promise<void> {
20-
if (this.uniques.length === 0) return;
21-
const { data } = await this.#itemRepository.requestItems(this.uniques);
22-
this._displayValue = data || [];
29+
async #observeItems() {
30+
const { asObservable } = await this.#itemRepository.requestItems(this.#uniques);
31+
32+
this.observe(asObservable(), (data) => {
33+
this._displayValue = data || [];
34+
});
2335
}
2436

2537
override render() {
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import type { UmbUserDetailModel, UmbUserStartNodesModel } from '../../types.js';
2+
import type { UmbDataSourceResponse, UmbDetailDataSource } from '@umbraco-cms/backoffice/repository';
3+
4+
export interface UmbUserDetailDataSource extends UmbDetailDataSource<UmbUserDetailModel> {
5+
calculateStartNodes(unique: string): Promise<UmbDataSourceResponse<UmbUserStartNodesModel>>;
6+
}
Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,33 @@
11
import type { UmbUserDetailModel } from '../../types.js';
2+
import type { UmbUserDetailDataSource } from './types.js';
23
import { UmbUserServerDataSource } from './user-detail.server.data-source.js';
34
import { UMB_USER_DETAIL_STORE_CONTEXT } from './user-detail.store.js';
45
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
56
import { UmbDetailRepositoryBase } from '@umbraco-cms/backoffice/repository';
67

7-
export class UmbUserDetailRepository extends UmbDetailRepositoryBase<UmbUserDetailModel> {
8+
export class UmbUserDetailRepository extends UmbDetailRepositoryBase<UmbUserDetailModel, UmbUserDetailDataSource> {
89
constructor(host: UmbControllerHost) {
910
super(host, UmbUserServerDataSource, UMB_USER_DETAIL_STORE_CONTEXT);
1011
}
1112

13+
/**
14+
* Creates a new User detail
15+
* @param {UmbUserDetailModel} model
16+
* @return {*}
17+
* @memberof UmbUserDetailRepository
18+
*/
1219
override async create(model: UmbUserDetailModel) {
1320
return super.create(model, null);
1421
}
22+
23+
/**
24+
* Requests the detail for the given unique
25+
* @return {*}
26+
* @memberof UmbUserDetailRepository
27+
*/
28+
requestCalculateStartNodes(unique: string) {
29+
return this.detailDataSource.calculateStartNodes(unique);
30+
}
1531
}
1632

1733
export default UmbUserDetailRepository;

src/packages/user/user/repository/detail/user-detail.server.data-source.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { UmbUserDetailModel } from '../../types.js';
1+
import type { UmbUserDetailModel, UmbUserStartNodesModel } from '../../types.js';
22
import { UMB_USER_ENTITY_TYPE } from '../../entity.js';
33
import { UmbId } from '@umbraco-cms/backoffice/id';
44
import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository';
@@ -212,4 +212,42 @@ export class UmbUserServerDataSource implements UmbDetailDataSource<UmbUserDetai
212212
}),
213213
);
214214
}
215+
216+
/**
217+
* Calculates the start nodes for the User
218+
* @param {string} unique
219+
* @return {*}
220+
* @memberof UmbUserServerDataSource
221+
*/
222+
async calculateStartNodes(unique: string) {
223+
if (!unique) throw new Error('Unique is missing');
224+
225+
const { data, error } = await tryExecuteAndNotify(
226+
this.#host,
227+
UserService.getUserByIdCalculateStartNodes({
228+
id: unique,
229+
}),
230+
);
231+
232+
if (data) {
233+
const calculatedStartNodes: UmbUserStartNodesModel = {
234+
hasDocumentRootAccess: data.hasDocumentRootAccess,
235+
documentStartNodeUniques: data.documentStartNodeIds.map((node) => {
236+
return {
237+
unique: node.id,
238+
};
239+
}),
240+
hasMediaRootAccess: data.hasMediaRootAccess,
241+
mediaStartNodeUniques: data.mediaStartNodeIds.map((node) => {
242+
return {
243+
unique: node.id,
244+
};
245+
}),
246+
};
247+
248+
return { data: calculatedStartNodes };
249+
}
250+
251+
return { error };
252+
}
215253
}

0 commit comments

Comments
 (0)