Skip to content

Commit 8d3817e

Browse files
new updates to handle version
1 parent 5249f94 commit 8d3817e

File tree

1 file changed

+121
-67
lines changed

1 file changed

+121
-67
lines changed

src/jio-navbar.ts

Lines changed: 121 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -40,31 +40,43 @@ export class Navbar extends LitElement {
4040
@property()
4141
locationPathname: string = location.pathname;
4242

43-
4443
/**
4544
* Header theme (light/dark/auto)
4645
*/
4746
@property()
4847
theme = 'light';
4948

49+
/**
50+
* Supported documentation versions with labels
51+
* @example [{version: '2.504.x', label: 'Stable'}, {version: 'latest', label: 'Nightly'}]
52+
*/
53+
@property({type: Array})
54+
docVersions: Array<{version: string, label: string}> = [
55+
{version: '2.504.x', label: 'Stable'}
56+
];
57+
58+
/**
59+
* Currently active documentation version
60+
*/
61+
@property({type: String})
62+
currentDocVersion = '2.504.x';
63+
5064
/**
5165
* Keeps track of what menu is opened.
52-
*
53-
* Never to be set externally, though storybook shows it.
5466
* @private
5567
*/
5668
@state()
5769
private visibleMenu = -1;
5870

5971
/**
6072
* Keeps track if the collapsed (mobile) menu is shown or not
61-
*
62-
* Never to be set externally, though storybook shows it.
6373
* @private
6474
*/
6575
@state()
6676
private menuToggled = false;
6777

78+
private isDocsSite = window.location.hostname === 'docs.jenkins.io';
79+
6880
constructor() {
6981
super();
7082
this.handleDocumentClick = this.handleDocumentClick.bind(this);
@@ -73,6 +85,11 @@ export class Navbar extends LitElement {
7385
override connectedCallback() {
7486
super.connectedCallback();
7587
document.addEventListener('click', this.handleDocumentClick);
88+
89+
// Initialize current version from first available if not set
90+
if (!this.currentDocVersion && this.docVersions.length > 0) {
91+
this.currentDocVersion = this.docVersions[0].version;
92+
}
7693
}
7794

7895
override disconnectedCallback() {
@@ -83,12 +100,10 @@ export class Navbar extends LitElement {
83100
handleDocumentClick() {
84101
this.visibleMenu = -1;
85102
}
86-
private isDocsSite = window.location.hostname === 'docs.jenkins.io';
87-
private docsVersion = '2.504.x';
88103

89104
private getDocsUrl(originalPath: string): string {
90-
91-
const cleanPath = originalPath.replace(/^https?:\/\/[^/]+/, '').split(/[#?]/)[0];
105+
const [cleanPath, query, hash] = originalPath.replace(/^https?:\/\/[^\/]+/, '').split(/[?#]/);
106+
92107
const docMappings: Record<string, {path: string, versioned: boolean}> = {
93108
// User Guide sections (versioned)
94109
'/doc/book': {path: '/user-docs', versioned: true},
@@ -142,23 +157,38 @@ export class Navbar extends LitElement {
142157
if (versioned) {
143158
const pathParts = newPath.split('/').filter(part => part !== '');
144159
if (pathParts.length >= 1) {
145-
pathParts.splice(1, 0, this.docsVersion);
160+
pathParts.splice(1, 0, this.currentDocVersion);
146161
newPath = '/' + pathParts.join('/');
147162
} else {
148-
newPath = `/${this.docsVersion}`;
163+
newPath = `/${this.currentDocVersion}`;
149164
}
150165
}
151166

152167
if (!newPath.endsWith('index.html')) {
153168
newPath = newPath.replace(/(\/)?$/, '/') + 'index.html';
154169
}
155-
156-
return `https://docs.jenkins.io${newPath}`;
170+
171+
// Reconstruct URL with query/hash if they existed
172+
let finalUrl = `https://docs.jenkins.io${newPath}`;
173+
if (query) finalUrl += `?${query}`;
174+
if (hash) finalUrl += `#${hash}`;
175+
return finalUrl;
157176
}
158177

159-
return this.isDocsSite
160-
? `https://docs.jenkins.io${cleanPath}`
161-
: `https://www.jenkins.io${cleanPath}`;
178+
// For all other paths, use standard behavior
179+
const baseUrl = this.isDocsSite ? 'https://docs.jenkins.io' : 'https://www.jenkins.io';
180+
return `${baseUrl}${cleanPath}`;
181+
}
182+
183+
private _handleVersionChange(e: Event) {
184+
const newVersion = (e.target as HTMLSelectElement).value;
185+
if (newVersion !== this.currentDocVersion) {
186+
this.currentDocVersion = newVersion;
187+
// Dispatch event to notify parent of version change
188+
this.dispatchEvent(new CustomEvent('version-changed', {
189+
detail: { version: this.currentDocVersion }
190+
}));
191+
}
162192
}
163193

164194
override render() {
@@ -168,117 +198,147 @@ export class Navbar extends LitElement {
168198
{label: msg("Tekton"), link: "https://tekton.dev/"},
169199
{label: msg("Spinnaker"), link: "https://www.spinnaker.io/"},
170200
];
201+
171202
const menuItems = [
172203
{label: msg("Blog"), link: "/blog/"},
173204
{label: msg("Success Stories"), link: "https://stories.jenkins.io/"},
174205
{label: msg("Contributor Spotlight"), link: "https://contributors.jenkins.io/"},
175206
{
176207
label: msg("Documentation"), link: [
177208
{
178-
label: msg("User Guide"), link: "/doc/book", header: true
209+
label: msg("User Guide"),
210+
link: this.getDocsUrl("/doc/book"),
211+
header: true
179212
},
180-
{label: "- " + msg("Installing Jenkins"), link: "/doc/book/installing/"},
181-
{label: "- " + msg("Jenkins Pipeline"), link: "/doc/book/pipeline/"},
182-
{label: "- " + msg("Managing Jenkins"), link: "/doc/book/managing/"},
183-
{label: "- " + msg("Securing Jenkins"), link: "/doc/book/security/"},
184-
{label: "- " + msg("System Administration"), link: "/doc/book/system-administration/"},
185-
{label: "- " + msg("Troubleshooting Jenkins"), link: "/doc/book/troubleshooting/"},
186-
{label: "- " + msg("Terms and Definitions"), link: "/doc/book/glossary/"},
187-
{label: msg("Solution Pages"), link: "/solutions", header: true},
213+
{label: "- " + msg("Installing Jenkins"), link: this.getDocsUrl("/doc/book/installing/")},
214+
{label: "- " + msg("Jenkins Pipeline"), link: this.getDocsUrl("/doc/book/pipeline/")},
215+
{label: "- " + msg("Managing Jenkins"), link: this.getDocsUrl("/doc/book/managing/")},
216+
{label: "- " + msg("Securing Jenkins"), link: this.getDocsUrl("/doc/book/security/")},
217+
{label: "- " + msg("System Administration"), link: this.getDocsUrl("/doc/book/system-administration/")},
218+
{label: "- " + msg("Troubleshooting Jenkins"), link: this.getDocsUrl("/doc/book/troubleshooting/")},
219+
{label: "- " + msg("Terms and Definitions"), link: this.getDocsUrl("/doc/book/glossary/")},
220+
221+
{label: msg("Solution Pages"), link: this.getDocsUrl("/solutions"), header: true},
222+
188223
{
189-
label: msg("Tutorials"), link: "/doc/tutorials", header: true
224+
label: msg("Tutorials"),
225+
link: this.getDocsUrl("/doc/tutorials"),
226+
header: true
190227
},
228+
191229
{
192-
label: msg("Developer Guide"), link: "/doc/developer", header: true
230+
label: msg("Developer Guide"),
231+
link: this.getDocsUrl("/doc/developer"),
232+
header: true
193233
},
194-
{label: msg("Contributor Guide"), link: "/participate", header: true},
195-
{label: msg("Books"), link: "/books", header: true},
234+
235+
{label: msg("Contributor Guide"), link: this.getDocsUrl("/participate"), header: true},
236+
{label: msg("Books"), link: this.getDocsUrl("/books"), header: true},
196237
]
197238
},
198239
{label: msg("Plugins"), link: "https://plugins.jenkins.io/"},
199240
{
200241
label: msg("Community"), link: [
201242
{
202-
label: msg("Overview"), link: "/participate/"
243+
label: msg("Overview"), link: this.getDocsUrl("/participate/")
203244
},
204245
{
205-
label: msg("Chat"), link: "/chat/", title: "Chat with the rest of the Jenkins community on IRC"
246+
label: msg("Chat"), link: this.getDocsUrl("/chat/"), title: "Chat with the rest of the Jenkins community on IRC"
206247
},
207-
{label: msg("Meet"), link: "/projects/jam/"},
248+
{label: msg("Meet"), link: this.getDocsUrl("/projects/jam/")},
208249
{
209-
label: msg("Events"), link: "/events/"
250+
label: msg("Events"), link: this.getDocsUrl("/events/")
210251
},
211252
{label: msg("Forum"), link: "https://community.jenkins.io/"},
212253
{label: msg("Issue Tracker"), link: "https://issues.jenkins.io/"},
213-
{label: msg("Mailing Lists"), link: "/mailing-lists/", title: "Browse Jenkins mailing list archives and/ or subscribe to lists"},
214-
{label: msg("Roadmap"), link: "/project/roadmap/"},
254+
{label: msg("Mailing Lists"), link: this.getDocsUrl("/mailing-lists/"), title: "Browse Jenkins mailing list archives and/ or subscribe to lists"},
255+
{label: msg("Roadmap"), link: this.getDocsUrl("/project/roadmap/")},
215256
{label: msg("Account Management"), link: "https://accounts.jenkins.io/", title: "Create/manage your account for accessing wiki, issue tracker, etc"},
216257
{
217-
label: msg("Special Interest Groups"), link: "/sigs/", header: true
258+
label: msg("Special Interest Groups"), link: this.getDocsUrl("/sigs/"), header: true
218259
},
219-
{label: "- " + msg("Advocacy and Outreach"), link: "/sigs/advocacy-and-outreach/"},
220-
{label: "- " + msg("Documentation"), link: "/sigs/docs/"},
221-
{label: "- " + msg("Google Summer of Code"), link: "/sigs/gsoc/"},
222-
{label: "- " + msg("Platform"), link: "/sigs/platform/"},
223-
{label: "- " + msg("User Experience"), link: "/sigs/ux/"},
260+
{label: "- " + msg("Advocacy and Outreach"), link: this.getDocsUrl("/sigs/advocacy-and-outreach/")},
261+
{label: "- " + msg("Documentation"), link: this.getDocsUrl("/sigs/docs/")},
262+
{label: "- " + msg("Google Summer of Code"), link: this.getDocsUrl("/sigs/gsoc/")},
263+
{label: "- " + msg("Platform"), link: this.getDocsUrl("/sigs/platform/")},
264+
{label: "- " + msg("User Experience"), link: this.getDocsUrl("/sigs/ux/")},
224265
]
225266
},
226267
{
227268
label: msg("Subprojects"), link: [
228269
{
229-
label: msg("Overview"), link: "/projects/"
270+
label: msg("Overview"), link: this.getDocsUrl("/projects/")
230271
},
231-
{label: msg("Google Summer of Code in Jenkins"), link: "/projects/gsoc/"},
232-
{label: msg("Infrastructure"), link: "/projects/infrastructure/"},
233-
{label: msg("CI/CD and Jenkins Area Meetups"), link: "/projects/jam/"},
234-
{label: msg("Jenkins Configuration as Code"), link: "/projects/jcasc/"},
235-
{label: msg("Jenkins Operator"), link: "/projects/jenkins-operator/"},
236-
{label: msg("Jenkins Remoting"), link: "/projects/remoting/"},
237-
{label: msg("Document Jenkins on Kubernetes"), link: "/sigs/docs/gsod/2020/projects/document-jenkins-on-kubernetes/"},
272+
{label: msg("Google Summer of Code in Jenkins"), link: this.getDocsUrl("/projects/gsoc/")},
273+
{label: msg("Infrastructure"), link: this.getDocsUrl("/projects/infrastructure/")},
274+
{label: msg("CI/CD and Jenkins Area Meetups"), link: this.getDocsUrl("/projects/jam/")},
275+
{label: msg("Jenkins Configuration as Code"), link: this.getDocsUrl("/projects/jcasc/")},
276+
{label: msg("Jenkins Operator"), link: this.getDocsUrl("/projects/jenkins-operator/")},
277+
{label: msg("Jenkins Remoting"), link: this.getDocsUrl("/projects/remoting/")},
278+
{label: msg("Document Jenkins on Kubernetes"), link: this.getDocsUrl("/sigs/docs/gsod/2020/projects/document-jenkins-on-kubernetes/")},
238279
]
239280
},
240281
{
241282
label: msg("Security"), link: [
242283
{
243-
label: msg("Overview"), link: "/security/"
284+
label: msg("Overview"), link: this.getDocsUrl("/security/")
244285
},
245-
{label: msg("Security Advisories"), link: "/security/advisories/"},
246-
{label: msg("Reporting Vulnerabilities"), link: "/security/reporting/"},
286+
{label: msg("Security Advisories"), link: this.getDocsUrl("/security/advisories/")},
287+
{label: msg("Reporting Vulnerabilities"), link: this.getDocsUrl("/security/reporting/")},
247288
]
248289
},
249290
{
250291
label: msg("About"), link: [
251-
{label: msg("Roadmap"), link: "/project/roadmap/"},
292+
{label: msg("Roadmap"), link: this.getDocsUrl("/project/roadmap/")},
252293
{
253-
label: msg("Press"), link: "/press/"
294+
label: msg("Press"), link: this.getDocsUrl("/press/")
254295
},
255296
{
256-
label: msg("Awards"), link: "/awards/"
297+
label: msg("Awards"), link: this.getDocsUrl("/awards/")
257298
},
258-
{label: msg("Conduct"), link: "/project/conduct/"},
259-
{label: msg("Artwork"), link: "/artwork/"},
299+
{label: msg("Conduct"), link: this.getDocsUrl("/project/conduct/")},
300+
{label: msg("Artwork"), link: this.getDocsUrl("/artwork/")},
260301
]
261302
}
262303
] as Array<NavbarItemLink>;
304+
263305
const menuItemsHtml = menuItems.map((menuItem, idx) => {
264306
let body;
265307
if (menuItem.link && Array.isArray(menuItem.link)) {
266-
// eslint-disable-next-line lit/no-this-assign-in-render
267308
body = this.renderNavItemDropdown(menuItem, idx, this.visibleMenu === idx);
268309
} else {
269-
// eslint-disable-next-line lit/no-this-assign-in-render
270310
body = html`<li class="nav-item">${this.renderNavItemLink(menuItem)}</li>`;
271311
}
272312
return body;
273313
});
314+
315+
const versionSelector = this.docVersions.length > 1 ? html`
316+
<div class="version-selector">
317+
<select @change=${this._handleVersionChange}>
318+
${this.docVersions.map(v => html`
319+
<option
320+
value=${v.version}
321+
?selected=${v.version === this.currentDocVersion}
322+
>
323+
${v.label} (${v.version})
324+
</option>
325+
`)}
326+
</select>
327+
</div>
328+
` : nothing;
329+
274330
const searchboxHtml = !this.showSearchBox ? nothing : html`<jio-searchbox @click=${this._handleSearchboxClick}></jio-searchbox>`;
331+
275332
return html`
276333
<nav class="navbar" data-theme=${this.theme}>
277334
<span class="navbar-brand">
278335
<slot name="brand">
279336
<a href="/">Jenkins</a>
280337
</slot>
281338
</span>
339+
340+
${versionSelector}
341+
282342
<button
283343
class="navbar-toggler collapsed btn"
284344
type="button"
@@ -288,6 +348,7 @@ export class Navbar extends LitElement {
288348
aria-label="Toggle navigation">
289349
<ion-icon name=${this.menuToggled ? "close-outline" : "menu-outline"} title="Toggle Menu Visible"></ion-icon>
290350
</button>
351+
291352
<div class="navbar-menu collapse ${this.menuToggled ? "show" : ""}">
292353
<ul class="nav navbar-nav mr-auto">
293354
${this.renderNavItemDropdown({label: html`<jio-cdf-logo></jio-cdf-logo>`, link: cdfMenuItems}, 99, this.visibleMenu === 99)}
@@ -310,11 +371,6 @@ export class Navbar extends LitElement {
310371
const assignedElements = slotElement.assignedElements();
311372
const container = slotElement.parentNode as HTMLElement;
312373
for (const element of assignedElements) {
313-
//if (element.slot === "rightMenuItems") {
314-
// const divider = document.createElement('li');
315-
// divider.className = "divider";
316-
// container.appendChild(divider);
317-
//}
318374
for (const link of element.querySelectorAll('jio-navbar-link')) {
319375
const wrapper = document.createElement('li');
320376
wrapper.className = "nav-item";
@@ -388,6 +444,4 @@ declare global {
388444
interface HTMLElementTagNameMap {
389445
'jio-navbar': Navbar;
390446
}
391-
}
392-
393-
447+
}

0 commit comments

Comments
 (0)