I am wanting to see if there is a nice way or a built in way to extend V15 Content/Document Workspace view before the list of properties in each tab, by displaying some kind of alert/message/warning to the user.
I would love to know if its possible to achieve this with the current extensions or WebComponent slots that may be available for me to insert this message?
If not my current hack and thought is for my Workspace Context that is loaded in alongside the document/content workspace context, is to try and find the element <umb-content-workspace-view-edit-tab> in the DOM of the page and then insert my element before it.
Not ideal as obviously fragile and prone to breaking if the DOM was to change in Umbraco.
Open to any thoughts or ideas on how to solve this problem?
You are probably further along than me when it comes to understanding the new Umbraco backoffice. But isn’t it possible to take an existing workspace and extend in it? Something like export default class MyWorkspace extends UmbDocumentWorkspace? And then make your workspace the active workspace for documents?
OK I have hacked something by using some DOM traversal and it works, but I am not sure if I like it.
Hoping someone from the core swings by and might be able to chip in with some thoughts.
Warning: There be dragons ahead
dom.nodes.ts
export class DomNodeUtils {
static findInShadowRoot(node: ShadowRoot | Document | null, selector: string): HTMLElement | null {
if(!node)
{
return null;
}
// Check if the current node contains the element we are looking for
const targetElement = node.querySelector(selector) as HTMLElement;
if(targetElement){
console.log('found targetElement', targetElement);
return targetElement;
}
// Recursively search through all the shadow roots of the children
const elements = node.querySelectorAll('*');
for(const element of elements){
if(element.shadowRoot){
const tryFindElement = this.findInShadowRoot(element.shadowRoot, selector);
if(tryFindElement){
console.log('found tryFindElement', tryFindElement);
return tryFindElement;
}
}
}
return null;
}
}
contentlock.workspace.context.ts
constructor(host: UmbControllerHost) {
super(host, CONTENTLOCK_WORKSPACE_CONTEXT.toString());
this.provideContext(CONTENTLOCK_WORKSPACE_CONTEXT, this);
// truncated...
// Add an event listener into the window for the navigation success router event
// Why? - well the findInShadowRoot() util method won't find the DOM elements until all the items been loaded in from router slots
window.addEventListener('navigationsuccess', this._navigationSuccessHandler);
}
private _navigationSuccessHandler() {
// Check to see if we have our NODE in the DOM
// As it fires as we change from tab to tab in the document workspace
// And dont want to duplicate the notice over and over
const tryFindNotice = DomNodeUtils.findInShadowRoot(document, '#locked-by-notice');
if(!tryFindNotice){
const tryFindInsertBefore = DomNodeUtils.findInShadowRoot(document, 'umb-content-workspace-view-edit-tab');
if(tryFindInsertBefore){
tryFindInsertBefore.insertAdjacentHTML('beforebegin', `<div id="locked-by-notice" style="margin-bottom: var(--uui-size-4); padding: var(--uui-size-5); background: var(--uui-color-current);">This node is locked by Emma</div>`)
}
}
}
...
Result
It works, but I kinda feel dirty that I needed to do this. Is there a better/nicer way to achieve what I am trying to do?
OK well that logic is flawed when using the navigationsuccess event, as there is no way for me to know the difference between navigating to a brand new content node vs the tabs on the content node changing and the URL/route changing.
Just because we have the Shadow-DOM to encapsulate Components, it does not mean that the DOM cant be manipulated. Its a little harder, but it is possible.
Surely not something I would recommend, as it could break, also in minors. Cause going this way you are going off road and unless we freeze the code base we cannot be sure not to break it.
So doing so then just please be aware, and if I see any topic regarding this on the tracker then you owe me a cup of coffee.
To do this the proper way my suggestion would be to reconsider how you show this information. Could you inject this on the Workspace level, something Static/floating on top? Add a thin yellow colored border on the whole workspace and then a tiny message in the bottom left corner?