* observation as promise util * all success observer * next step todos * await everything loaded * contentTypeLoaded observable * tidying up * Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * remove comment --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -7,6 +7,7 @@ export * from './default-memoization.function.js';
|
||||
export * from './filter-frozen-array.function.js';
|
||||
export * from './json-string-comparison.function.js';
|
||||
export * from './merge-observables.function.js';
|
||||
export * from './observation-as-promise.function.js';
|
||||
export * from './observe-multiple.function.js';
|
||||
export * from './partial-update-frozen-array.function.js';
|
||||
export * from './push-at-to-unique-array.function.js';
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
|
||||
/**
|
||||
* @function observationAsPromise
|
||||
* @param {Observable<unknown>} observable - an Array of Observables to use for this combined observation.
|
||||
* @param {Promise<condition>} condition - a method which should return true or false, if rejected or returning undefined the observation will result in a rejected Promise.
|
||||
* @description - Observes an Observable and returns a Promise that resolves when the condition returns true. If the condition returns undefined or rejects, the Promise will reject with the current value.
|
||||
* @returns {Promise<unknown>} - Returns a Promise which resolves when the condition returns true or rejects when the condition returns undefined or is rejecting it self.
|
||||
*/
|
||||
export function observationAsPromise<T>(
|
||||
observable: Observable<T>,
|
||||
condition: (value: T) => Promise<boolean | undefined>,
|
||||
): Promise<T> {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
let initialCallback = true;
|
||||
let wantedToClose = false;
|
||||
const subscription = observable.subscribe(async (value) => {
|
||||
const shouldClose = await condition(value).catch(() => {
|
||||
if (initialCallback) {
|
||||
wantedToClose = true;
|
||||
} else {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
reject(value);
|
||||
});
|
||||
if (shouldClose === true) {
|
||||
if (initialCallback) {
|
||||
wantedToClose = true;
|
||||
} else {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
resolve(value);
|
||||
}
|
||||
});
|
||||
initialCallback = false;
|
||||
if (wantedToClose) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -19,12 +19,15 @@ import {
|
||||
appendToFrozenArray,
|
||||
filterFrozenArray,
|
||||
createObservablePart,
|
||||
observationAsPromise,
|
||||
mergeObservables,
|
||||
} from '@umbraco-cms/backoffice/observable-api';
|
||||
import { incrementString } from '@umbraco-cms/backoffice/utils';
|
||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||
import { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api';
|
||||
import { umbExtensionsRegistry, type ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs';
|
||||
import { UmbError } from '@umbraco-cms/backoffice/resources';
|
||||
|
||||
type UmbPropertyTypeUnique = UmbPropertyTypeModel['unique'];
|
||||
|
||||
@@ -112,6 +115,13 @@ export class UmbContentTypeStructureManager<
|
||||
readonly contentTypeUniques = this.#contentTypes.asObservablePart((x) => x.map((y) => y.unique));
|
||||
readonly contentTypeAliases = this.#contentTypes.asObservablePart((x) => x.map((y) => y.alias));
|
||||
|
||||
readonly contentTypeLoaded = mergeObservables(
|
||||
[this.contentTypeCompositions, this.contentTypeUniques],
|
||||
([comps, uniques]) => {
|
||||
return comps.every((x) => uniques.includes(x.contentType.unique));
|
||||
},
|
||||
);
|
||||
|
||||
readonly variesByCulture = createObservablePart(this.ownerContentType, (x) => x?.variesByCulture);
|
||||
readonly variesBySegment = createObservablePart(this.ownerContentType, (x) => x?.variesBySegment);
|
||||
|
||||
@@ -191,9 +201,26 @@ export class UmbContentTypeStructureManager<
|
||||
);
|
||||
}
|
||||
this.#repoManager!.setUniques([unique]);
|
||||
const result = await this.observe(this.#repoManager!.entryByUnique(unique)).asPromise();
|
||||
const observable = this.#repoManager!.entryByUnique(unique);
|
||||
const result = await this.observe(observable).asPromise();
|
||||
if (!result) {
|
||||
this.#initRejection?.(`Content Type structure manager could not load: ${unique}`);
|
||||
return {
|
||||
error: new UmbError(`Content Type structure manager could not load: ${unique}`),
|
||||
asObservable: () => observable,
|
||||
};
|
||||
}
|
||||
|
||||
// Awaits that everything is loaded:
|
||||
await observationAsPromise(this.contentTypeLoaded, async (loaded) => {
|
||||
return loaded === true;
|
||||
}).catch(() => {
|
||||
const msg = `Content Type structure manager could not load: ${unique}. Not all Content Types loaded successfully.`;
|
||||
this.#initRejection?.(msg);
|
||||
return Promise.reject(new UmbError(msg));
|
||||
});
|
||||
|
||||
this.#initResolver?.(result);
|
||||
await this.#init;
|
||||
return { data: result, asObservable: () => this.ownerContentType };
|
||||
}
|
||||
|
||||
|
||||
@@ -151,14 +151,14 @@ export class UmbRepositoryDetailsManager<DetailType extends { unique: string }>
|
||||
*/
|
||||
addEntry(data: DetailType): void {
|
||||
const unique = data.unique;
|
||||
this.#entries.appendOne(data);
|
||||
this.#uniques.appendOne(unique);
|
||||
this.#statuses.appendOne({
|
||||
state: {
|
||||
type: 'success',
|
||||
},
|
||||
unique,
|
||||
});
|
||||
this.#entries.appendOne(data);
|
||||
this.#uniques.appendOne(unique);
|
||||
// Notice in this case we do not have a observable from the repo, but it should maybe be fine that we just listen for ACTION EVENTS.
|
||||
}
|
||||
|
||||
|
||||
@@ -415,7 +415,7 @@ export class UmbDocumentWorkspaceContext
|
||||
this.readOnlyGuard?.addRule({
|
||||
unique: identifier,
|
||||
message,
|
||||
/* This guard is a bit backwards. The rule is permitted to be read-only.
|
||||
/* This guard is a bit backwards. The rule is permitted to be read-only.
|
||||
If the user does not have permission, we set it to true = permitted to be read-only. */
|
||||
permitted: true,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user