mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
committed by
Dylan Hunn
parent
e3eb5fea47
commit
19d782b469
@@ -17,6 +17,7 @@ export enum PagePrefix {
|
||||
PLAYGROUND = 'playground',
|
||||
REFERENCE = 'reference',
|
||||
TUTORIALS = 'tutorials',
|
||||
UPDATE = 'update-guide',
|
||||
}
|
||||
|
||||
// The enum with the default pages for each main tab
|
||||
@@ -25,4 +26,5 @@ export enum DefaultPage {
|
||||
REFERENCE = 'api',
|
||||
TUTORIALS = 'tutorials',
|
||||
PLAYGROUND = 'playground',
|
||||
UPDATE = 'update-guide',
|
||||
}
|
||||
|
||||
@@ -202,7 +202,8 @@ export class Navigation implements OnInit {
|
||||
this.activeRouteItem.set(PagePrefix.DOCS);
|
||||
} else if (
|
||||
urlAfterRedirects.startsWith(PagePrefix.REFERENCE) ||
|
||||
urlAfterRedirects.startsWith(PagePrefix.API)
|
||||
urlAfterRedirects.startsWith(PagePrefix.API) ||
|
||||
urlAfterRedirects.startsWith(PagePrefix.UPDATE)
|
||||
) {
|
||||
this.activeRouteItem.set(PagePrefix.REFERENCE);
|
||||
} else if (urlAfterRedirects === PagePrefix.PLAYGROUND) {
|
||||
|
||||
@@ -65,12 +65,12 @@ export class SecondaryNavigation implements OnInit {
|
||||
private readonly router = inject(Router);
|
||||
private readonly window = inject(WINDOW);
|
||||
|
||||
isSecondaryNavVisible = this.navigationState.isMobileNavVisible;
|
||||
primaryActiveRouteItem = this.navigationState.primaryActiveRouteItem;
|
||||
maxVisibleLevelsOnSecondaryNav = computed(() =>
|
||||
readonly isSecondaryNavVisible = this.navigationState.isMobileNavVisible;
|
||||
readonly primaryActiveRouteItem = this.navigationState.primaryActiveRouteItem;
|
||||
readonly maxVisibleLevelsOnSecondaryNav = computed(() =>
|
||||
this.primaryActiveRouteItem() === PagePrefix.REFERENCE ? 1 : 2,
|
||||
);
|
||||
navigationItemsSlides = this.navigationState.expandedItems;
|
||||
readonly navigationItemsSlides = this.navigationState.expandedItems;
|
||||
navigationItems: NavigationItem[] | undefined;
|
||||
|
||||
translateX = computed(() => {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,191 @@
|
||||
<div class="page docs-viewer">
|
||||
<h1 tabindex="-1">Update Guide</h1>
|
||||
<div class="wizard">
|
||||
<div>
|
||||
<h2>Select the options that match your update</h2>
|
||||
|
||||
<h3>Angular versions</h3>
|
||||
|
||||
<div class="adev-version-selector">
|
||||
<span class="adev-template-select">
|
||||
From v.
|
||||
|
||||
<button [cdkMenuTriggerFor]="templatesMenu">
|
||||
<span>{{ from.name }}</span>
|
||||
<docs-icon>expand_more</docs-icon>
|
||||
</button>
|
||||
|
||||
<ng-template #templatesMenu>
|
||||
<ul class="adev-template-dropdown" cdkMenu>
|
||||
@for (version of versions; track $index) {
|
||||
<li>
|
||||
<button cdkMenuItem type="button" (click)="from=version; showUpdatePath()">
|
||||
<span>{{ version.name }}</span>
|
||||
</button>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</ng-template>
|
||||
</span>
|
||||
|
||||
<span>
|
||||
<span class="adev-template-select">
|
||||
To v.
|
||||
<button [cdkMenuTriggerFor]="templatesMenu">
|
||||
<span>{{ to.name }}</span>
|
||||
<docs-icon>expand_more</docs-icon>
|
||||
</button>
|
||||
|
||||
<ng-template #templatesMenu>
|
||||
<ul class="adev-template-dropdown" cdkMenu>
|
||||
@for (version of versions; track $index) {
|
||||
<li>
|
||||
<button cdkMenuItem type="button" (click)="to=version; showUpdatePath()">
|
||||
<span>{{ version.name }}</span>
|
||||
</button>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</ng-template>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@if (from.number >= futureVersion || to.number >= futureVersion) {
|
||||
<div class="docs-alert docs-alert-critical">
|
||||
<p>
|
||||
<strong>Warning:</strong>
|
||||
Plans for releases after the current major release are not finalized and may change.
|
||||
These recommendations are based on scheduled deprecations.
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (from.number > to.number) {
|
||||
<div class="docs-alert docs-alert-critical">
|
||||
<p>
|
||||
<strong>Warning:</strong>
|
||||
We do not support downgrading versions of Angular.
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if ((to.number - from.number > 150) && from.number > 240) {
|
||||
<div class="docs-alert docs-alert-critical">
|
||||
<p>
|
||||
<strong>Warning:</strong>
|
||||
Be sure to follow the guide below to migrate your application to the new version. You
|
||||
can't run
|
||||
<code>ng update</code>
|
||||
to update Angular applications more than one major version at a time.
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
<h3>Application complexity</h3>
|
||||
<mat-button-toggle-group
|
||||
(change)="level = $event.value;"
|
||||
[value]="level"
|
||||
style="margin-bottom:16px;"
|
||||
>
|
||||
<mat-button-toggle [value]="1">Basic</mat-button-toggle>
|
||||
<mat-button-toggle [value]="2">Medium</mat-button-toggle>
|
||||
<mat-button-toggle [value]="3">Advanced</mat-button-toggle>
|
||||
</mat-button-toggle-group>
|
||||
@if (level === 1) {
|
||||
<p>Shows information for all Angular developers.</p>
|
||||
} @else if (level === 2) {
|
||||
<p>Shows information that's of interest to more advanced Angular developers.</p>
|
||||
} @else if (level === 3) {
|
||||
<p>Shows all the information we have about this update.</p>
|
||||
}
|
||||
|
||||
<h3>Other dependencies</h3>
|
||||
@for (option of optionList; track $index) {
|
||||
<p>
|
||||
<mat-checkbox
|
||||
(change)="options[option.id] = $event.checked; showUpdatePath()"
|
||||
[checked]="options[option.id]"
|
||||
>I use {{option.name}} {{option.description}}</mat-checkbox
|
||||
>
|
||||
</p>
|
||||
}
|
||||
|
||||
@if (from.number < 600) {
|
||||
<h4>Package Manager</h4>
|
||||
<mat-button-toggle-group
|
||||
(change)="packageManager = $event.value; showUpdatePath()"
|
||||
[value]="packageManager"
|
||||
>
|
||||
<mat-button-toggle value="npm install">npm</mat-button-toggle>
|
||||
<mat-button-toggle value="yarn add">yarn</mat-button-toggle>
|
||||
</mat-button-toggle-group>
|
||||
}
|
||||
|
||||
<button
|
||||
type="button"
|
||||
(click)="showUpdatePath()"
|
||||
class="docs-primary-btn show-button"
|
||||
[attr.text]="'Show me how to update!'"
|
||||
>
|
||||
Show me how to update!
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<!-- RECOMMENDATIONS SECTION -->
|
||||
|
||||
@if (
|
||||
beforeRecommendations.length > 0 || duringRecommendations.length > 0 || afterRecommendations.length > 0
|
||||
) {
|
||||
<div class="recommendations">
|
||||
<h2>{{title}}</h2>
|
||||
|
||||
<h3>Before you update</h3>
|
||||
@for (r of beforeRecommendations; track $index) {
|
||||
<div class="adev-recommentation-item">
|
||||
<mat-checkbox></mat-checkbox>
|
||||
<div [innerHTML]="r.renderedStep"></div>
|
||||
</div>
|
||||
}
|
||||
@if (beforeRecommendations.length <= 0) {
|
||||
<div>
|
||||
<em>You don't need to do anything before moving between these versions.</em>
|
||||
</div>
|
||||
}
|
||||
|
||||
<h3>Update to the new version</h3>
|
||||
@if (duringRecommendations.length > 0) {
|
||||
<div>
|
||||
<em>Review these changes and perform the actions to update your application.</em>
|
||||
</div>
|
||||
}
|
||||
|
||||
@for (r of duringRecommendations; track $index) {
|
||||
<div class="adev-recommentation-item">
|
||||
<mat-checkbox></mat-checkbox>
|
||||
<div [innerHTML]="r.renderedStep"></div>
|
||||
</div>
|
||||
}
|
||||
@if (duringRecommendations.length <= 0) {
|
||||
<div>
|
||||
<em>There aren't any recommendations for moving between these versions.</em>
|
||||
</div>
|
||||
}
|
||||
|
||||
<h3>After you update</h3>
|
||||
@for (r of afterRecommendations; track $index) {
|
||||
<div class="adev-recommentation-item">
|
||||
<mat-checkbox></mat-checkbox>
|
||||
<div [innerHTML]="r.renderedStep"></div>
|
||||
</div>
|
||||
}
|
||||
@if (afterRecommendations.length <= 0) {
|
||||
<div>
|
||||
<em>You don't need to do anything after moving between these versions.</em>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@@ -0,0 +1,100 @@
|
||||
.page {
|
||||
padding: var(--layout-padding);
|
||||
max-width: var(--page-width);
|
||||
container: update-guide-page / inline-size;
|
||||
}
|
||||
|
||||
h3,
|
||||
h4 {
|
||||
margin-block-start: 2em;
|
||||
}
|
||||
|
||||
.wizard {
|
||||
padding-inline: 1rem;
|
||||
|
||||
.show-button {
|
||||
display: block;
|
||||
margin-block-start: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.adev-version-selector {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.adev-template-dropdown {
|
||||
border: 1px solid var(--senary-contrast);
|
||||
border-radius: 0.25rem;
|
||||
padding: 0;
|
||||
transform: translateY(-0.7rem);
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
|
||||
li {
|
||||
list-style: none;
|
||||
width: 198px;
|
||||
box-sizing: border-box;
|
||||
|
||||
button {
|
||||
background: var(--page-background);
|
||||
font-size: 0.875rem;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding-block: 0.5rem;
|
||||
color: var(--quaternary-contrast);
|
||||
transition:
|
||||
color 0.3s ease,
|
||||
background 0.3s ease;
|
||||
font-weight: 400;
|
||||
|
||||
&:hover {
|
||||
background: var(--senary-contrast);
|
||||
color: var(--primary-contrast);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.adev-template-select {
|
||||
margin-block-end: 0.5rem;
|
||||
|
||||
// cdk select button
|
||||
button {
|
||||
font-size: 0.875rem;
|
||||
border: 1px solid var(--senary-contrast);
|
||||
border-radius: 0.25rem;
|
||||
width: 200px;
|
||||
display: inline-flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-block: 0.5rem;
|
||||
font-weight: 400;
|
||||
transition: border 0.3s ease;
|
||||
span {
|
||||
color: var(--primary-contrast);
|
||||
transition: color 0.3s ease;
|
||||
margin-inline-start: 0.1rem;
|
||||
}
|
||||
|
||||
docs-icon {
|
||||
font-size: 1.3rem;
|
||||
color: var(--quaternary-contrast);
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.adev-recommentation-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> div {
|
||||
margin-inline-start: 2rem;
|
||||
}
|
||||
|
||||
// Code blocks are generable from the markdown, we need to opt-out of the scoping
|
||||
::ng-deep code {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
import {Component, HostListener, inject} from '@angular/core';
|
||||
import {Step, RECOMMENDATIONS} from './recommendations';
|
||||
import {Clipboard} from '@angular/cdk/clipboard';
|
||||
import {CdkMenuModule} from '@angular/cdk/menu';
|
||||
import {MatCheckboxModule} from '@angular/material/checkbox';
|
||||
import {MatInputModule} from '@angular/material/input';
|
||||
import {MatCardModule} from '@angular/material/card';
|
||||
import {MatGridListModule} from '@angular/material/grid-list';
|
||||
import {MatButtonToggleModule} from '@angular/material/button-toggle';
|
||||
import {IconComponent} from '@angular/docs';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
import {marked} from 'marked';
|
||||
|
||||
interface Option {
|
||||
id: keyof Step;
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'adev-update-guide',
|
||||
templateUrl: './update.component.html',
|
||||
styleUrl: './update.component.scss',
|
||||
imports: [
|
||||
MatCheckboxModule,
|
||||
MatInputModule,
|
||||
MatCardModule,
|
||||
MatGridListModule,
|
||||
MatButtonToggleModule,
|
||||
CdkMenuModule,
|
||||
IconComponent,
|
||||
],
|
||||
standalone: true,
|
||||
})
|
||||
export default class AppComponent {
|
||||
protected title = '';
|
||||
|
||||
protected level = 1;
|
||||
protected options: Record<string, boolean> = {
|
||||
ngUpgrade: false,
|
||||
material: false,
|
||||
windows: isWindows(),
|
||||
};
|
||||
|
||||
protected readonly optionList: Option[] = [
|
||||
{id: 'ngUpgrade', name: 'ngUpgrade', description: 'to combine AngularJS & Angular'},
|
||||
{id: 'material', name: 'Angular Material', description: ''},
|
||||
{id: 'windows', name: 'Windows', description: ''},
|
||||
];
|
||||
|
||||
protected packageManager: 'npm install' | 'yarn add' = 'npm install';
|
||||
|
||||
protected beforeRecommendations: Step[] = [];
|
||||
protected duringRecommendations: Step[] = [];
|
||||
protected afterRecommendations: Step[] = [];
|
||||
|
||||
protected readonly versions = [
|
||||
{name: '18.0', number: 1800},
|
||||
{name: '17.0', number: 1700},
|
||||
{name: '16.0', number: 1600},
|
||||
{name: '15.0', number: 1500},
|
||||
{name: '14.0', number: 1400},
|
||||
{name: '13.0', number: 1300},
|
||||
{name: '12.0', number: 1200},
|
||||
{name: '11.0', number: 1100},
|
||||
{name: '10.2', number: 1020},
|
||||
{name: '10.1', number: 1010},
|
||||
{name: '10.0', number: 1000},
|
||||
{name: '9.1', number: 910},
|
||||
{name: '9.0', number: 900},
|
||||
{name: '8.2', number: 820},
|
||||
{name: '8.1', number: 810},
|
||||
{name: '8.0', number: 800},
|
||||
{name: '7.2', number: 720},
|
||||
{name: '7.1', number: 710},
|
||||
{name: '7.0', number: 700},
|
||||
{name: '6.1', number: 610},
|
||||
{name: '6.0', number: 600},
|
||||
{name: '5.2', number: 520},
|
||||
{name: '5.1', number: 510},
|
||||
{name: '5.0', number: 500},
|
||||
{name: '4.4', number: 440},
|
||||
{name: '4.3', number: 430},
|
||||
{name: '4.2', number: 420},
|
||||
{name: '4.1', number: 410},
|
||||
{name: '4.0', number: 400},
|
||||
{name: '2.4', number: 204},
|
||||
{name: '2.3', number: 203},
|
||||
{name: '2.2', number: 202},
|
||||
{name: '2.1', number: 201},
|
||||
{name: '2.0', number: 200},
|
||||
];
|
||||
protected from = this.versions.find((version) => version.name === '16.0')!;
|
||||
protected to = this.versions.find((version) => version.name === '17.0')!;
|
||||
protected futureVersion = 1800;
|
||||
|
||||
protected readonly steps: Step[] = RECOMMENDATIONS;
|
||||
|
||||
private readonly clipboard = inject(Clipboard);
|
||||
private readonly router = inject(Router);
|
||||
private readonly activatedRoute = inject(ActivatedRoute);
|
||||
|
||||
constructor() {
|
||||
const queryMap = this.activatedRoute.snapshot.queryParamMap;
|
||||
// Detect settings in URL
|
||||
this.level = parseInt(queryMap.get('l')!, 10) || this.level;
|
||||
|
||||
// Detect versions of from and to
|
||||
const versions = queryMap.get('v');
|
||||
if (versions) {
|
||||
const [from, to] = versions.split('-');
|
||||
this.from = this.versions.find((version) => version.name === from)!;
|
||||
this.to = this.versions.find((version) => version.name === to)!;
|
||||
this.showUpdatePath();
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('click', ['$event.target'])
|
||||
copyCode({tagName, textContent}: Element) {
|
||||
if (tagName === 'CODE') {
|
||||
// TODO: add a toast notification
|
||||
this.clipboard.copy(textContent!);
|
||||
}
|
||||
}
|
||||
|
||||
async showUpdatePath() {
|
||||
this.beforeRecommendations = [];
|
||||
this.duringRecommendations = [];
|
||||
this.afterRecommendations = [];
|
||||
|
||||
// Refuse to generate recommendations for downgrades
|
||||
if (this.to.number < this.from.number) {
|
||||
alert('We do not support downgrading versions of Angular.');
|
||||
return;
|
||||
}
|
||||
|
||||
const labelTitle = 'Guide to update your Angular application';
|
||||
const labelBasic = 'basic applications';
|
||||
const labelMedium = 'medium applications';
|
||||
const labelAdvanced = 'advanced applications';
|
||||
|
||||
this.title = `${labelTitle} v${this.from.name} -> v${this.to.name}
|
||||
for
|
||||
${this.level < 2 ? labelBasic : this.level < 3 ? labelMedium : labelAdvanced}`;
|
||||
|
||||
// Find applicable steps and organize them into before, during, and after upgrade
|
||||
for (const step of this.steps) {
|
||||
if (step.level <= this.level && step.necessaryAsOf > this.from.number) {
|
||||
// Check Options
|
||||
// Only show steps that don't have a required option
|
||||
// Or when the user has a matching option selected
|
||||
let skip = false;
|
||||
for (const option of this.optionList) {
|
||||
// Skip steps which require an option not set by the user.
|
||||
if (step[option.id] && !this.options[option.id]) {
|
||||
skip = true;
|
||||
}
|
||||
|
||||
// Skip steps which require **not** using an option which **is** set
|
||||
// by the user.
|
||||
if (step[option.id] === false && this.options[option.id]) {
|
||||
skip = true;
|
||||
}
|
||||
}
|
||||
if (skip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Render and replace variables
|
||||
step.renderedStep = await marked(this.replaceVariables(step.action));
|
||||
|
||||
// If you could do it before now, but didn't have to finish it before now
|
||||
if (step.possibleIn <= this.from.number && step.necessaryAsOf >= this.from.number) {
|
||||
this.beforeRecommendations.push(step);
|
||||
// If you couldn't do it before now, and you must do it now
|
||||
} else if (step.possibleIn > this.from.number && step.necessaryAsOf <= this.to.number) {
|
||||
this.duringRecommendations.push(step);
|
||||
} else if (step.possibleIn <= this.to.number) {
|
||||
this.afterRecommendations.push(step);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the URL so users can link to this transition
|
||||
this.router.navigate([], {
|
||||
relativeTo: this.activatedRoute,
|
||||
queryParams: {v: `${this.from.name}-${this.to.name}`, l: this.level},
|
||||
queryParamsHandling: 'merge',
|
||||
});
|
||||
|
||||
// Tell everyone how to upgrade for v6 or earlier
|
||||
this.renderPreV6Instructions();
|
||||
}
|
||||
|
||||
private getAdditionalDependencies(version: number): string {
|
||||
if (version < 500) {
|
||||
return `typescript@'>=2.1.0 <2.4.0'`;
|
||||
} else if (version < 600) {
|
||||
return `typescript@2.4.2 rxjs@^5.5.2`;
|
||||
} else {
|
||||
return `typescript@2.7.x rxjs@^6.0.0`;
|
||||
}
|
||||
}
|
||||
|
||||
private getAngularVersion(version: number): string {
|
||||
if (version < 400) {
|
||||
return `'^2.0.0'`;
|
||||
} else {
|
||||
const major = Math.floor(version / 100);
|
||||
const minor = Math.floor((version - major * 100) / 10);
|
||||
return `^${major}.${minor}.0`;
|
||||
}
|
||||
}
|
||||
|
||||
private async renderPreV6Instructions(): Promise<void> {
|
||||
let upgradeStep: Step;
|
||||
const isWindows = /win/i.test(navigator.platform);
|
||||
const additionalDeps = this.getAdditionalDependencies(this.to.number);
|
||||
const angularVersion = this.getAngularVersion(this.to.number);
|
||||
const angularPackages = [
|
||||
'animations',
|
||||
'common',
|
||||
'compiler',
|
||||
'compiler-cli',
|
||||
'core',
|
||||
'forms',
|
||||
'http',
|
||||
'platform-browser',
|
||||
'platform-browser-dynamic',
|
||||
'platform-server',
|
||||
'router',
|
||||
];
|
||||
|
||||
// Provide npm/yarn instructions for versions before 6
|
||||
if (this.to.number < 600) {
|
||||
const actionMessage = `Update all of your dependencies to the latest Angular and the right version of TypeScript.`;
|
||||
|
||||
if (isWindows) {
|
||||
const packages =
|
||||
angularPackages
|
||||
.map((packageName) => `@angular/${packageName}@${angularVersion}`)
|
||||
.join(' ') +
|
||||
' ' +
|
||||
additionalDeps;
|
||||
|
||||
upgradeStep = {
|
||||
step: 'General Update',
|
||||
action: `${actionMessage}
|
||||
If you are using Windows, you can use:
|
||||
|
||||
\`${this.packageManager} ${packages}\``,
|
||||
} as Step;
|
||||
} else {
|
||||
const packages = `@angular/{${angularPackages.join(',')}}@${angularVersion} ${additionalDeps}`;
|
||||
upgradeStep = {
|
||||
step: 'General update',
|
||||
action: `${actionMessage}
|
||||
If you are using Linux/Mac, you can use:
|
||||
|
||||
\`${this.packageManager} ${packages}\``,
|
||||
} as Step;
|
||||
}
|
||||
|
||||
// Npm installs typescript wrong in v5, let's manually specify
|
||||
// https://github.com/npm/npm/issues/16813
|
||||
if (this.packageManager === 'npm install' && this.to.number === 500) {
|
||||
upgradeStep.action += `
|
||||
|
||||
\`npm install typescript@2.4.2 --save-exact\``;
|
||||
}
|
||||
|
||||
upgradeStep.renderedStep = await marked(upgradeStep.action);
|
||||
|
||||
this.duringRecommendations.push(upgradeStep);
|
||||
}
|
||||
}
|
||||
|
||||
private replaceVariables(action: string): string {
|
||||
let newAction = action;
|
||||
newAction = newAction.replace(
|
||||
'${packageManagerGlobalInstall}',
|
||||
this.packageManager === 'npm install' ? 'npm install -g' : 'yarn global add',
|
||||
);
|
||||
newAction = newAction.replace('${packageManagerInstall}', this.packageManager);
|
||||
return newAction;
|
||||
}
|
||||
}
|
||||
|
||||
/** Whether or not the user is running on a Windows OS. */
|
||||
function isWindows(): boolean {
|
||||
const platform = navigator.platform.toLowerCase();
|
||||
return platform.includes('windows') || platform.includes('win32');
|
||||
}
|
||||
@@ -41,6 +41,12 @@ const referencePageRoutes = mapNavigationItemsToRoutes(
|
||||
},
|
||||
);
|
||||
|
||||
const updateGuidePageRoute: Route = {
|
||||
path: referenceNavigationItems.find((r) => r.path === DefaultPage.UPDATE)!.path,
|
||||
loadComponent: () => import('./features/update/update.component'),
|
||||
data: commonReferenceRouteData,
|
||||
};
|
||||
|
||||
const cliReferencePageRoutes = mapNavigationItemsToRoutes(
|
||||
referenceNavigationItems.filter((r) => r.path?.startsWith(`${PagePrefix.CLI}/`)),
|
||||
{
|
||||
@@ -61,6 +67,7 @@ const docsReferencePageRoutes = mapNavigationItemsToRoutes(
|
||||
referenceNavigationItems.filter(
|
||||
(r) =>
|
||||
r.path !== DefaultPage.REFERENCE &&
|
||||
r.path !== DefaultPage.UPDATE &&
|
||||
!r.path?.startsWith(`${PagePrefix.API}/`) &&
|
||||
!r.path?.startsWith(`${PagePrefix.CLI}/`),
|
||||
),
|
||||
@@ -143,6 +150,7 @@ export const routes: Route[] = [
|
||||
...SUB_NAVIGATION_ROUTES,
|
||||
...API_REFERENCE_ROUTES,
|
||||
...FOOTER_ROUTES,
|
||||
updateGuidePageRoute,
|
||||
],
|
||||
},
|
||||
// Error page
|
||||
|
||||
@@ -1370,6 +1370,10 @@ const REFERENCE_SUB_NAVIGATION_DATA: NavigationItem[] = [
|
||||
path: 'reference/versions',
|
||||
contentPath: 'reference/versions',
|
||||
},
|
||||
{
|
||||
label: 'Update guide',
|
||||
path: 'update-guide',
|
||||
},
|
||||
{
|
||||
label: 'Configurations',
|
||||
children: [
|
||||
|
||||
Reference in New Issue
Block a user