Skip to content

Commit 6086c68

Browse files
Take into account embedded content when displaying service contents
1 parent 3b1663a commit 6086c68

File tree

4 files changed

+99
-45
lines changed

4 files changed

+99
-45
lines changed

frontend/index.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
/* Outlet */
2828
#outlet {
29-
padding: 20px;
3029
min-width: fit-content;
3130
}
3231
</style>

frontend/src/components/breadcrumb-nav.ts

Lines changed: 76 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ import { css, html, LitElement } from 'lit';
1919
import { customElement, property, state } from 'lit/decorators.js';
2020
import { Router, RouterLocation } from '@vaadin/router';
2121
import { getRootPath } from '../common/util';
22+
import { IS_EMBEDDED } from '../common/constants';
2223

2324
/**
2425
* Represents a part of the breadcrumb navigation
2526
*/
2627
interface BreadcrumbPart {
2728
path: string;
2829
name: string;
30+
icon?: string;
2931
}
3032

3133
/**
@@ -42,7 +44,31 @@ export class BreadcrumbNav extends LitElement {
4244
align-items: center;
4345
gap: 8px;
4446
margin-bottom: 16px;
45-
width: fit-content;
47+
width: 100%;
48+
justify-content: space-between;
49+
}
50+
51+
.breadcrumb-container {
52+
display: flex;
53+
align-items: center;
54+
gap: 8px;
55+
}
56+
57+
.realm-badge {
58+
background-color: var(--or-app-color4);
59+
color: white;
60+
padding: 4px 12px;
61+
border-radius: 16px;
62+
font-size: 12px;
63+
font-weight: 500;
64+
text-transform: uppercase;
65+
letter-spacing: 0.5px;
66+
margin-left: auto;
67+
min-width: 60px;
68+
text-align: center;
69+
display: flex;
70+
align-items: center;
71+
justify-content: center;
4672
}
4773
4874
a {
@@ -53,7 +79,7 @@ export class BreadcrumbNav extends LitElement {
5379
gap: 4px;
5480
--or-icon-width: 16px;
5581
--or-icon-height: 16px;
56-
max-width: 200px;
82+
max-width: 300px;
5783
}
5884
5985
a:hover {
@@ -63,7 +89,7 @@ export class BreadcrumbNav extends LitElement {
6389
span[aria-current='page'] {
6490
color: rgba(0, 0, 0, 0.87);
6591
font-weight: 500;
66-
max-width: 200px;
92+
max-width: 300px;
6793
overflow: hidden;
6894
text-overflow: ellipsis;
6995
white-space: nowrap;
@@ -86,26 +112,17 @@ export class BreadcrumbNav extends LitElement {
86112

87113
protected readonly rootPath = getRootPath();
88114

89-
protected get HOME_LINK(): BreadcrumbPart {
90-
return {
91-
path: `${this.rootPath}/${this.realm}/configs`,
92-
name: 'ML Forecast Service'
93-
};
94-
}
95-
96-
protected readonly MAX_TEXT_LENGTH = 20;
115+
protected readonly MAX_TEXT_LENGTH = 40;
97116

98117
willUpdate(changedProperties: Map<string, any>) {
99118
if (changedProperties.has('realm') && this.realm) {
100-
// Trigger location change event
101119
const location: Partial<RouterLocation> = {
102120
pathname: `${this.rootPath}/${this.realm}/configs`,
103121
params: {
104122
realm: this.realm
105123
}
106124
};
107125

108-
// Update the breadcrumbs and title
109126
this.updateBreadcrumbs(location as RouterLocation);
110127
}
111128
}
@@ -115,7 +132,6 @@ export class BreadcrumbNav extends LitElement {
115132
*/
116133
protected readonly handleLocationChange = (event: CustomEvent<{ location: RouterLocation }>) => {
117134
const location = event.detail.location;
118-
// Update the breadcrumbs and title
119135
this.updateBreadcrumbs(location);
120136
};
121137

@@ -136,28 +152,45 @@ export class BreadcrumbNav extends LitElement {
136152
const parts: BreadcrumbPart[] = [];
137153
const { pathname, params } = location;
138154

139-
// Add Smartcity part (realm)
140-
if (this.realm) {
141-
parts.push({
142-
path: `${this.rootPath}/${this.realm}/configs`,
143-
name: this.realm.charAt(0).toUpperCase() + this.realm.slice(1)
144-
});
155+
156+
const homePart = {
157+
path: `${this.rootPath}/${this.realm}/configs`,
158+
name: 'ML Forecast Service',
159+
icon: 'puzzle'
160+
};
161+
162+
// If we are not embedded, add the home part
163+
if (!IS_EMBEDDED) {
164+
parts.push(homePart);
145165
}
146166

167+
const configsPart = {
168+
path: `${this.rootPath}/${this.realm}/configs`,
169+
name: 'Configurations'
170+
};
171+
147172
// Add Configs part
148173
if (pathname.includes('/configs')) {
149-
parts.push({
150-
path: `${this.rootPath}/${this.realm}/configs`,
151-
name: 'Configs'
152-
});
174+
parts.push(configsPart);
153175

154-
// Add specific config part if we're on a config page
155-
if (params.id) {
176+
// Handle config editor page
177+
const isExistingConfig = params.id && !pathname.includes('/new');
178+
if (isExistingConfig) {
156179
parts.push({
157180
path: `${this.rootPath}/${this.realm}/configs/${params.id}`,
158-
name: params.id === 'new' ? 'New Config' : `${params.id}`
181+
name: `${params.id}`
159182
});
160183
}
184+
185+
const isNewConfig = pathname.includes('/new');
186+
if (isNewConfig) {
187+
parts.push({
188+
path: `${this.rootPath}/${this.realm}/configs/new`,
189+
name: 'New'
190+
});
191+
}
192+
193+
161194
}
162195

163196
this.parts = parts;
@@ -173,15 +206,18 @@ export class BreadcrumbNav extends LitElement {
173206
/**
174207
* Renders a single breadcrumb item
175208
*/
176-
protected renderBreadcrumbItem(part: BreadcrumbPart, readonly: boolean) {
209+
protected renderBreadcrumbItem(part: BreadcrumbPart, readonly: boolean, isFirst: boolean) {
177210
const truncatedName = this.truncateText(part.name);
178211

212+
const icon = part.icon ? html`<or-icon icon=${part.icon}></or-icon>` : html``;
213+
179214
return html`
180-
<span aria-hidden="true">&gt;</span>
215+
${!isFirst ? html`<span aria-hidden="true">&gt;</span>` : html``}
181216
${readonly
182217
? html`<span aria-current="page">${truncatedName}</span>`
183218
: html`
184219
<a href="${part.path}" @click=${(e: MouseEvent) => this.handleNavigation(e, part.path)}>
220+
${icon}
185221
<span class="truncate">${truncatedName}</span>
186222
</a>
187223
`}
@@ -197,15 +233,20 @@ export class BreadcrumbNav extends LitElement {
197233
}
198234

199235
render() {
200-
const truncatedHomeName = this.truncateText(this.HOME_LINK.name);
236+
// Hide breadcrumbs if there's only one part
237+
const shouldShowBreadcrumbs = this.parts.length > 1;
238+
if (!shouldShowBreadcrumbs) {
239+
return html``;
240+
}
241+
242+
const realmBadge = IS_EMBEDDED ? html`` : html`<div class="realm-badge">${this.realm}</div>`;
201243

202244
return html`
203245
<nav aria-label="breadcrumb">
204-
<a href="${this.HOME_LINK.path}" @click=${(e: MouseEvent) => this.handleNavigation(e, this.HOME_LINK.path)}>
205-
<or-icon icon="puzzle"></or-icon>
206-
<span class="truncate">${truncatedHomeName}</span>
207-
</a>
208-
${this.parts.map((part, index) => this.renderBreadcrumbItem(part, index === this.parts.length - 1))}
246+
<div class="breadcrumb-container">
247+
${this.parts.map((part, index) => this.renderBreadcrumbItem(part, index === this.parts.length - 1, index === 0))}
248+
</div>
249+
${realmBadge}
209250
</nav>
210251
`;
211252
}

frontend/src/pages/app-layout.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,30 @@
1717

1818
import { createContext, provide } from '@lit/context';
1919
import { PreventAndRedirectCommands, RouterLocation } from '@vaadin/router';
20-
import { html, LitElement } from 'lit';
20+
import { css, html, LitElement, unsafeCSS } from 'lit';
2121
import { customElement, state } from 'lit/decorators.js';
2222
import { setRealmTheme } from '../common/theme';
2323
import { AuthService } from '../services/auth-service';
2424
import { manager } from '@openremote/core';
25-
import { ML_OR_URL } from '../common/constants';
25+
import { IS_EMBEDDED, ML_OR_URL } from '../common/constants';
2626

2727
export const realmContext = createContext<string>(Symbol('realm'));
2828

2929
@customElement('app-layout')
3030
export class AppLayout extends LitElement {
31-
// Use a context to provide the realm to all child elements
32-
// Child elements can use the @consume decorator to receive the realm
33-
// This is done in the parent layout to extract the realm from the route params on route change in a single place
31+
32+
33+
static get styles() {
34+
const padding = IS_EMBEDDED ? '0 20px' : '20px';
35+
36+
return css`
37+
:host {
38+
display: block;
39+
padding: ${unsafeCSS(padding)};
40+
}
41+
`;
42+
}
43+
3444
@provide({ context: realmContext })
3545
@state()
3646
realm = '';

frontend/src/pages/pages-config-list.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,16 @@ export class PageConfigList extends LitElement {
5858
--or-icon-fill: var(--or-app-color3);
5959
}
6060
.title {
61-
font-size: 18px;
62-
font-weight: bold;
61+
font-size: 14px;
62+
font-weight: bolder;
6363
display: flex;
6464
flex-direction: row;
6565
align-items: center;
6666
color: var(--or-app-color3);
67+
text-transform: uppercase;
68+
line-height: 1em;
69+
flex: 0 0 auto;
70+
letter-spacing: 0.025em;
6771
}
6872
`;
6973
}
@@ -166,8 +170,8 @@ export class PageConfigList extends LitElement {
166170
<or-panel heading="">
167171
<div class="config-header">
168172
<div class="title-container">
169-
<or-icon icon="chart-bell-curve"></or-icon>
170-
<span class="title">Forecast Configurations</span>
173+
<or-icon icon="chart-line"></or-icon>
174+
<span class="title">Forecast configurations</span>
171175
</div>
172176
173177
<or-mwc-input

0 commit comments

Comments
 (0)