DEV Community

Kevin Jump
Kevin Jump

Posted on • Edited on

Early Adopter's guide to Umbraco v14 - Workspaces

So now, if you have been following along, we have all sort of cool things, we have a dashboard that talks to the server back end, with contexts, repositories, stores and resources, a custom section with a menu and a menu item, and well the beginnings of quite a useless time package.

Today we are going to plumb in our menu item to something, a workspace. In umbraco v14 land a workspace is essentially everything in the big main box.

Workspace is the main big box

Whats a workspace?

Anything that isn't the menu bar or the sidebar happens in a workspace. So there is a document workspace for content, a media one for media, and so on. Its not that there is 'one' big workspace for all documents, but when you open a content item, everything in the box is in the workspace.

Creating a workspace.

You can probibly guess by now a workspace is created via a manifest config.



var workspaceManifest : ManifestWorkspace = {
    type: 'workspace',
    alias: 'time.workspace',
    name: 'time workspace',
    element: ()=> import('./workspace.element'),
    meta: {
        entityType: 'time-workspace'
    }
};


Enter fullscreen mode Exit fullscreen mode

What is worth noting here is that we are going to import a "workspace elemet" this will be the lit element that renders the page.

the entity-type is not the element type that renders the page, rather it is a 'type name' of the workspace. this is the value that is used to link the workspace to the menu (or tree).

Linking the workspace to a menu item.

going back to the menu item we created in the last post. we need to tell it the 'entity-type' that the menu item opens.

for us that is the workspace entity-type.



const menuItemManifest  : ManifestMenuItem = {
    type: 'menuItem',
    alias: 'time.menu,item',
    name: 'time menu item',
    meta: {
        label: 'Time Zones',
        icon: 'icon-alarm-clock',
        entityType: 'time-workspace',
        menus: [
            'time.menu'
        ]
    }
}


Enter fullscreen mode Exit fullscreen mode

We have matched the entity-type in the workspace with the one on the menu item, when you click the menu item, the workspace loads!

Workspace element.

So we jumped the gun a little there because we just linked to an element type we haven't written yet.

the root workspace element, is the thing that will be the parent to everything we do in the workspace. its allmost like its the lit-app for the workspace.



import { UmbElementMixin } 
    from "@umbraco-cms/backoffice/element-api";
import { LitElement, html, customElement } 
    from "@umbraco-cms/backoffice/external/lit";

@customElement('time-workspace-root')
export class TimeWorkspaceElement extends
    UmbElementMixin(LitElement) {

    render() {
        return html`
            <umb-workspace-editor 
                headline="Time"
                alias="time.workspace.root"
                .enforceNoFooter=${true}>
            </umb-workspace-editor>
        `
    }
}

export default TimeWorkspaceElement;


Enter fullscreen mode Exit fullscreen mode

the <umb-workspace-editor> component gives us the nice header bar (and footer if you don't turn it off), so you can give your page the 'umbraco' look and feel.

Page with workspace element

Workspace content,

Now at this point you can put content between the <umb-workspace-editor> and it will render on the page.

if we replace our workspace element's render method with this :



render() {
    return html`
        <umb-workspace-editor
            headline="Time" 
            alias="time.workspace" 
            .enforceNoFooter=${true}>
            <uui-box headline='my workspace content'>
                <p>Some content goes here</p>
            </uui-box>
         </umb-workspace-editor>
    `;
}


Enter fullscreen mode Exit fullscreen mode

That will render some content like so:

Workspace content

but you can be a bit more fancy, and have options.

Workspace views.

Workspace views, are individual views, that can be reached via the icons in the top right hand corner of a workspace.

these are where 'content apps' have gone to

when we are not making a custom section, we can define a view in an existin workspace (like the document workspace) and it will appear like a content app.!

workspace views have a manifest definition:



var workspaceViews : Array<ManifestWorkspaceView> = [
 {
  type: 'workspaceView',
  alias: 'time.workspace.default',
  name: 'default view',
  js: () => import('./views/defaultWorkspace.element.js'),
  weight: 300,
  meta: {
     icon: 'icon-alarm-clock',
     pathname: 'overview',
     label: 'time'
  },
  conditions: [
     {
    alias: 'Umb.Condition.WorkspaceAlias',
        match: workspace.alias
     },
   ],    
 },
];


Enter fullscreen mode Exit fullscreen mode

although obviously if you are using views you would have more than one

🚨Potential pain point alert🚨
the trick to views.... and i spent a long time figuring this one out, is that you need to have an active workspace context, before the <umb-workspace-editor> will render the icons in the view.

Workspace context.

In order for views to work a workspace context has to do three things.

  1. impliment the UmbWorkspaceContextInterface
  2. Provide a UMB_WORKSPACE_CONTEXT to itself,
  3. be instanciated somewhere (i have done this in the WorkspaceElement

1. Impliment (UmbWorkspaceContextInterface)



export class TimeWorkspaceContext 
    extends UmbBaseController 
    implements UmbWorkspaceContextInterface {

    public readonly workspaceAlias: string = 'time.workspace';

    constructor(host:UmbControllerHostElement) {
        super(host);
        this.provideContext(UMB_WORKSPACE_CONTEXT, this);
        this.provideContext(TIME_WORKSPACE_CONTEXT, this);
    }

    getEntityType(): string {
        return 'time-workspace';
    }

    getUnique(): string | undefined {
        return undefined;
    }
}


Enter fullscreen mode Exit fullscreen mode

2. Provide UMB_WORKSPACE_CONTEXT

The note here which is missed is UMB_WORKSPACE_CONTEXT - i think this is like adding the context to a collection or workspace contexts across the app, and when the <umb-workspace-editor> tag comes to find workspaces it does so by getting hold of your context. 🤷

3. be instanciated somewhere

For this i have added it to the top of my workspace element



@customElement('time-workspace-root')
export class TimeWorkspaceElement extends UmbElementMixin(LitElement) {
    #workspaceContext = new TimeWorkspaceContext(this);
    ...



Enter fullscreen mode Exit fullscreen mode

Now all that is in place, and i am less some hair. we get a workspace with 'tabs'

Workspace with tabs in a custom section

. Result !

I think next time we might step back and make a content app.


Updated: 2/3/2024 - preview008 renamed getEntityId -> getUnique

Top comments (1)

Collapse
 
frytzl profile image
David Jazbec

This is gold, thank you for this guide, its going to spare me hours of research. I have a question though. Is it possible to use a normal .html file as a dashboard "view"? It seems that everything needs to be a lit element now.