-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Description
Which Umbraco version are you using?
16.0.0
Bug summary
I am upgrading from Umbraco 15.0 and have learnt readOnlyState is no longer a thing and discovered readOnlyGuard but from reading docs it states the following
readOnlyGuard (This will be removed in the future. Use propertyWriteGuard instead)
So after porting my code to use propertyWriteGuard I have noticed the node name is still editable and no longer displays the label of readonly.
Specifics
Screenshot
Steps to reproduce
My code for my workspace context as follows, but its pretty much the same as the one in the documentation
https://docs.umbraco.com/umbraco-cms/customizing/property-level-ui-permissions#write-a-general-rule
Code Sample
import { UmbContextBase } from '@umbraco-cms/backoffice/class-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
import { type UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UMB_DOCUMENT_WORKSPACE_CONTEXT, UmbDocumentWorkspaceContext } from '@umbraco-cms/backoffice/document';
import { observeMultiple, UmbBooleanState, UmbStringState } from '@umbraco-cms/backoffice/observable-api';
import { UmbEntityUnique } from '@umbraco-cms/backoffice/entity';
import ContentLockSignalrContext, { CONTENTLOCK_SIGNALR_CONTEXT } from '../globalContexts/contentlock.signalr.context';
import { UMB_CURRENT_USER_CONTEXT } from '@umbraco-cms/backoffice/current-user';
import { UMB_CONFIRM_MODAL, umbOpenModal } from '@umbraco-cms/backoffice/modal';
import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api';
export class ContentLockWorkspaceContext extends UmbContextBase {
#docWorkspaceCtx?: UmbDocumentWorkspaceContext;
#unique: UmbEntityUnique | undefined;
#isLocked = new UmbBooleanState(false);
isLocked = this.#isLocked.asObservable();
#isLockedBySelf = new UmbBooleanState(false);
isLockedBySelf = this.#isLockedBySelf.asObservable();
#lockedByName = new UmbStringState('');
lockedByName = this.#lockedByName.asObservable();
#signalRContext?: ContentLockSignalrContext;
#currentUserKey?: string;
#localize = new UmbLocalizationController(this);
constructor(host: UmbControllerHost) {
super(host, CONTENTLOCK_WORKSPACE_CONTEXT.toString());
this.consumeContext(CONTENTLOCK_SIGNALR_CONTEXT, (signalRContext) => {
this.#signalRContext = signalRContext;
});
this.consumeContext(UMB_CURRENT_USER_CONTEXT, (currentUserCtx) => {
this.observe(currentUserCtx?.unique, (currentUserKey) => {
this.#currentUserKey = currentUserKey;
this.checkContentLockState();
});
});
this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (docWorkspaceCtx) => {
this.#docWorkspaceCtx = docWorkspaceCtx;
this.#docWorkspaceCtx?.observe(this.#docWorkspaceCtx?.unique, (unique) => {
this.#unique = unique;
this.checkContentLockState();
});
});
}
public async checkContentLockState() {
if(!this.#unique) return;
if(!this.#currentUserKey) return;
if (this.#signalRContext) {
let previousState = { isLocked: false, isLockedBySelf: false };
// Observe the 3 states from the SignalR context
// isLocked: boolean - Is the item locked by anyone
// isLockedBySelf: boolean - Is the item locked by the current user
// lockInfo: object - Contains the lock info, including who locked it
this.observe(observeMultiple([
this.#signalRContext.isNodeLocked(this.#unique.toString()),
this.#signalRContext.isNodeLockedByMe(this.#unique.toString(), this.#currentUserKey),
this.#signalRContext.getLock(this.#unique.toString())
]), async ([isLocked, isLockedBySelf, lockInfo]) => {
// Set the observables
this.setIsLocked(isLocked);
this.setIsLockedBySelf(isLockedBySelf);
if (lockInfo) {
this.setLockedByName(lockInfo.checkedOutBy);
}
if(isLocked && isLockedBySelf === false){
// Page is locked by someone else - set the propertyWriteGuard
this.#docWorkspaceCtx?.propertyWriteGuard.addRule({
unique: `ContentLock-${this.#unique!.toString()}`,
permitted: false,
message: `This page is locked by ${lockInfo?.checkedOutBy}`
});
}
else {
// Page is not locked or its locked by self - remove the readonly (propertyWriteGuard)
this.#docWorkspaceCtx?.propertyWriteGuard.removeRule(`ContentLock-${this.#unique!.toString()}`);
}
// If previously the page was locked by someone else, we can alert the user its now unlocked
if (previousState.isLocked && !previousState.isLockedBySelf && !isLocked && !isLockedBySelf) {
umbOpenModal(this, UMB_CONFIRM_MODAL,
{
data: {
headline: this.#localize.term('contentUnlockedModal_modalHeader'),
content: this.#localize.term('contentUnlockedModal_modalContent'),
color: "positive",
confirmLabel: this.#localize.term('contentUnlockedModal_reload'),
}
}
)
.then(async () => {
// This will reload the entire page, so the user can see the latest version of the content
// Might be nice if we can just ask a context to reload the node or something?
// There is reload on Workspace context
await this.#docWorkspaceCtx?.reload();
})
.catch(() => {
// Do nothing if the user cancels the modal or presses escape etc
});
}
// Update the previous state
previousState = { isLocked, isLockedBySelf };
});
}
}
public getIsLocked() {
return this.#isLocked.getValue();
}
public setIsLocked(isLocked: boolean) {
this.#isLocked.setValue(isLocked);
}
public getIsLockedBySelf() {
return this.#isLockedBySelf.getValue();
}
public setIsLockedBySelf(isLockedBySelf: boolean) {
this.#isLockedBySelf.setValue(isLockedBySelf);
}
public getLockedByName() {
return this.#lockedByName.getValue();
}
public setLockedByName(lockedBy: string) {
this.#lockedByName.setValue(lockedBy);
}
}
// Declare a api export, so Extension Registry can initialize this class:
export const api = ContentLockWorkspaceContext;
// Declare a Context Token that other elements can use to request the WorkspaceContextCounter:
export const CONTENTLOCK_WORKSPACE_CONTEXT = new UmbContextToken<ContentLockWorkspaceContext>('UmbWorkspaceContext', 'contentlock.workspacecontext');Expected result / actual result
For the node name to not be editable and for the label towards the end of the input field to have the read only text like it did with readOnlyGuard/readOnlyState