All the code for this series of posts is available in the DoStuffWithUmbraco Repository on GitHub
In the last article we got to the point where we had our own custom section, with a side menu (or "sidebarApp") and a basic menu item.
but for now clicking on that menu item just shows us some loading dots 😞
What we need to do know is define a workspace.
So what are workspaces ? well to lift the description directly from the umbraco docs :
Workspaces provide dedicated editing environments for specific entity types in Umbraco. They create isolated areas where users can edit content, media, members, or other entities with specialized interfaces and functionality.
basically menu items are assigned an 'entity type' and when you click on them Umbraco looks for the workspace that renders that entity type.
entity types are really just Identifiers at this point, usually you might have in two entity types a 'root' and and 'item' - the root is as you might expect the one at the root, and the item is an item in your tree (if you have one.
Item workspace
For our "simple" time item, we only have a single "do-stuff-time-item" entity type, and that's the one we need to build a workspace for to show information to the user.
Workspaces at their most basic have two things, a workspace context and a workspace element.
Workspace Context
Your workspace context is the code that controls the state and data for your workspace. here you have all your data and ways to fetch and save it.
To be clear, you don't need to do this in a context, you can just fetch , store and manipulate data in the element, but as you will see in a bit, that is probably going to lead to duplication and a more complex bunch of code
So without being to complicated a workspace will look something like this:
export class MySampleWorkspaceContext
extends UmbEditableWorkspaceContextBase<TimeSettings>
implements UmbSubmittableWorkspaceContext
{
#settingsRepository = new DoStuffTimeSettingsRepository(this);
readonly unique: Observable<string | null | undefined>;
public readonly workspaceAlias = DOSTUFF_WORKSPACE_ALIAS;
constructor(host: UmbControllerHost) {
super(host, DOSTUFF_WORKSPACE_ALIAS);
this.provideContext(DOSTUFF_WORKSPACE_CONTEXT, this);
}
getUnique() {
return undefined;
}
getData() {
return this.#timeSettings.value;
}
getEntityType() {
return DOSTUFF_TIME_ITEM_ALIAS;
}
protected submit() {
const settings = this.#timeSettings.value;
if (!settings) return;
await this.#settingsRepository.saveTimeSettings(settings);
}
}
Workspaces can even be simpler than this, but here we are implementing a UmbSubmittableWorkspaceContext because we want to be able to save things that we update on our context, if you don't want to tie into other things like workspace actions, you don't need to do this, but its a relatively simple implementation, so in my opinion it's worth it.
There are few things we are going to pick out in the context :
ProvideContext
You can see that inside the constructor for the context we are calling this.provideContext . this tells the rest of the app, that we are responsible for the DOSTUFF_WORKSPACE_CONTEXT so if anything wants to interact with this context they can. by asking for it in their own constructor.
For example - a view might ask for the context like this.
this.consumeContext(DOSTUFF_WORKSPACE_CONTEXT, (context) => {
// do stuff with the context here.
});
Workspace contexts have a scope, they will only exist while you are in the workspace, you can't call a workspace context from somewhere else or another section - if you need to do that you might need a global context, which work in a similar way they are just defined slightly differently
Repositories
Another thing you might have noticed about this context is we randomly just call save in a #settingsRepository and we've haven't told you what one of them is yet - we will get to them in a bit.
But for now, that's just the place where the actual calls to API end points and the like are stored - it means our context doesn't need to know the inner workings of the API it can just say go get this or save that.
Views
So now we have registered our workspace and we have a workspace context, you will notice, we still have nothing to show to our user! So now its time to fix that, and present them with something. You define what things show in a workspace via workspaceView elements.
again we define these in a manifest.
type: "workspaceView",
alias: "DoStuff.DefaultWorkspaceView",
name: "DoStuff Default Workspace View",
js: () => import("./default-workspace-view.element.js"),
weight: 500,
meta: {
label: "#doStuff_defaultWorkspaceViewName",
pathname: "default",
icon: "icon-alarm-clock",
},
conditions: [
{
alias: "Umb.Condition.WorkspaceAlias",
match: DOSTUFF_WORKSPACE_ALIAS,
},
],
},
So the things to note :
- the
jsentry points the file that will render the element - the
metadata defines the name and icon for the view - the
conditionsmake sure our view only shows up on our workspace.
View element
The view element is a UmbLitElement that renders what you want to show the user
@customElement("do-stuff-default-workspace-view-element")
export class DoStuffDefaultWorkspaceViewElement extends UmbLitElement {
override render() {
return html`<umb-body-layout>
<div class="layout">
<uui-box
.headline=${this.localize.term("doStuff_defaultWorkspaceTitle")}
>
<h1>Hello Time</h1>
</uui-box>
</div>
</umb-body-layout>`;
}
}
With this in place we get something to show the user !
Multiple views, and icons.
So we defined that icon, and name, but it's not anywhere on the screen, what's up with that?.
Well the icon and name are used when we have multiple views in a workspace. so if we add another workspaceView manifest to the workspace
{
type: "workspaceView",
alias: "DoStuff.SettingsWorkspaceView",
name: "DoStuff Settings Workspace View",
js: () => import("./settings-workspace-view.element.js"),
weight: 200,
meta: {
label: "#doStuff_settingsWorkspaceViewName",
pathname: "settings",
icon: "icon-settings",
},
conditions: [
{
alias: "Umb.Condition.WorkspaceAlias",
match: DOSTUFF_WORKSPACE_ALIAS,
},
],
},
We get our 'tabs'
Summarry
This gets us the skeleton of our workspace up and showing something to the user - there is much more to workspaces , and we will go into them in some later posts, but for now, we have a section, a menu and some workspaces. so 🎉



Top comments (0)