Skip to content

Commit

Permalink
docs: add open in IDX support (angular#57099)
Browse files Browse the repository at this point in the history
This change adds a menu to the in-browser code editor on adev and adds the option for open in IDX.

PR Close angular#57099
  • Loading branch information
MarkTechson authored and dylhunn committed Jul 26, 2024
1 parent 56816bb commit ca8bd5b
Show file tree
Hide file tree
Showing 12 changed files with 273 additions and 3 deletions.
1 change: 1 addition & 0 deletions adev/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ APPLICATION_DEPS = [
"@npm//@lezer/javascript",
"@npm//@lezer/common",
"@npm//@stackblitz/sdk",
"@npm//open-in-idx",
"@npm//@xterm/xterm",
"@npm//@xterm/addon-fit",
"@npm//algoliasearch",
Expand Down
16 changes: 14 additions & 2 deletions adev/src/app/editor/code-editor/code-editor.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,23 @@
<button
class="adev-editor-download-button"
type="button"
(click)="openCurrentCodeInStackBlitz()"
aria-label="Open current code in editor in StackBlitz"
aria-label="Open current code in editor in an online editor"
[cdkMenuTriggerFor]="launcherMenu"
>
<docs-icon>launch</docs-icon>
</button>
<!-- launcher dropdown window -->
<ng-template #launcherMenu>
<div class="adev-editor-dropdown" cdkMenu>
<button cdkMenuItem (click)="openCurrentSolutionInIDX()">
<span>Open in IDX </span>
<img class="icon" src="assets/images/tutorials/common/idx_logo.svg" height="32">
</button>
<button cdkMenuItem (click)="openCurrentCodeInStackBlitz()">
Open in StackBlitz
</button>
</div>
</ng-template>
<button
class="adev-editor-download-button"
type="button"
Expand Down
31 changes: 31 additions & 0 deletions adev/src/app/editor/code-editor/code-editor.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,34 @@
}
}
}

.adev-editor-dropdown {
border: 1px solid var(--senary-contrast);
border-radius: 0.25rem;
padding: 0;
transform: translateY(-0.7rem);

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;
display: flex;
justify-content: space-between;
align-items: center;

&:hover {
background: var(--senary-contrast);
color: var(--primary-contrast);
}
.icon {
margin: initial;
padding: initial;
width: auto;
}
}
}
17 changes: 16 additions & 1 deletion adev/src/app/editor/code-editor/code-editor.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import {DiagnosticWithLocation, DiagnosticsState} from './services/diagnostics-s
import {DownloadManager} from '../download-manager.service';
import {StackBlitzOpener} from '../stackblitz-opener.service';
import {ClickOutside, IconComponent} from '@angular/docs';
import {CdkMenu, CdkMenuItem, CdkMenuTrigger} from '@angular/cdk/menu';
import {IDXLauncher} from '../idx-launcher.service';

export const REQUIRED_FILES = new Set([
'src/main.ts',
Expand All @@ -46,7 +48,16 @@ const ANGULAR_DEV = 'https://angular.dev';
templateUrl: './code-editor.component.html',
styleUrls: ['./code-editor.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [NgIf, NgFor, MatTabsModule, IconComponent, ClickOutside],
imports: [
NgIf,
NgFor,
MatTabsModule,
IconComponent,
ClickOutside,
CdkMenu,
CdkMenuItem,
CdkMenuTrigger,
],
})
export class CodeEditor implements AfterViewInit, OnDestroy {
@ViewChild('codeEditorWrapper') private codeEditorWrapperRef!: ElementRef<HTMLDivElement>;
Expand Down Expand Up @@ -78,6 +89,7 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
private readonly diagnosticsState = inject(DiagnosticsState);
private readonly downloadManager = inject(DownloadManager);
private readonly stackblitzOpener = inject(StackBlitzOpener);
private readonly idxLauncher = inject(IDXLauncher);
private readonly title = inject(Title);
private readonly location = inject(Location);
private readonly embeddedTutorialManager = inject(EmbeddedTutorialManager);
Expand Down Expand Up @@ -117,6 +129,9 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
this.codeMirrorEditor.disable();
}

openCurrentSolutionInIDX(): void {
this.idxLauncher.openCurrentSolutionInIDX();
}
async openCurrentCodeInStackBlitz(): Promise<void> {
const title = this.title.getTitle();

Expand Down
51 changes: 51 additions & 0 deletions adev/src/app/editor/idx-launcher.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*!
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/

import {EnvironmentInjector, Injectable, inject} from '@angular/core';
import {injectAsync} from '../core/services/inject-async';
import * as IDX from 'open-in-idx';

@Injectable({
providedIn: 'root',
})
export class IDXLauncher {
private readonly environmentInjector = inject(EnvironmentInjector);

async openCurrentSolutionInIDX(): Promise<void> {
const nodeRuntimeSandbox = await injectAsync(this.environmentInjector, () =>
import('./node-runtime-sandbox.service').then((c) => c.NodeRuntimeSandbox),
);

const runtimeFiles = await nodeRuntimeSandbox.getSolutionFiles();
const workspaceFiles: Record<string, string> = {};

for (let i = 0; i < runtimeFiles.length; i++) {
const file = runtimeFiles[i];

//don't include config.json, BUILD.bazel, package-lock.json, package.json.template
const doNotAllowList = [
'config.json',
'BUILD.bazel',
'package-lock.json',
'package.json.template',
];

const path = file.path.replace(/^\//, '');

//don't include binary formats
if (!doNotAllowList.includes(path) && typeof file.content === 'string') {
if (path === 'idx/dev.nix') {
workspaceFiles['.idx/dev.nix'] = file.content as string;
} else {
workspaceFiles[path] = file.content as string;
}
}
}
IDX.newAdhocWorkspace({files: workspaceFiles});
}
}
14 changes: 14 additions & 0 deletions adev/src/assets/images/tutorials/common/idx_logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions adev/src/content/tutorials/first-app/common/idx/dev.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# To learn more about how to use Nix to configure your environment
# see: https://developers.google.com/idx/guides/customize-idx-env
{ pkgs, ... }: {
# Which nixpkgs channel to use.
channel = "stable-23.11"; # or "unstable"
# Use https://search.nixos.org/packages to find packages
packages = [
pkgs.nodejs_18
];
# Sets environment variables in the workspace
env = {};
idx = {
# Search for the extensions you want on https://open-vsx.org/ and use "publisher.id"
extensions = [
"angular.ng-template"
];
workspace = {
# Runs when a workspace is first created with this \`dev.nix\` file
onCreate = {
npm-install = "npm install --no-audit --prefer-offline";
};
# To run something each time the environment is rebuilt, use the \`onStart\` hook
};
# Enable previews and customize configuration
previews = {
enable = true;
previews = {
web = {
command = ["npm" "run" "start" "--" "--port" "$PORT" "--host" "0.0.0.0"];
manager = "web";
};
};
};
};
}
35 changes: 35 additions & 0 deletions adev/src/content/tutorials/homepage/idx/dev.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# To learn more about how to use Nix to configure your environment
# see: https://developers.google.com/idx/guides/customize-idx-env
{ pkgs, ... }: {
# Which nixpkgs channel to use.
channel = "stable-23.11"; # or "unstable"
# Use https://search.nixos.org/packages to find packages
packages = [
pkgs.nodejs_18
];
# Sets environment variables in the workspace
env = {};
idx = {
# Search for the extensions you want on https://open-vsx.org/ and use "publisher.id"
extensions = [
"angular.ng-template"
];
workspace = {
# Runs when a workspace is first created with this \`dev.nix\` file
onCreate = {
npm-install = "npm install --no-audit --prefer-offline";
};
# To run something each time the environment is rebuilt, use the \`onStart\` hook
};
# Enable previews and customize configuration
previews = {
enable = true;
previews = {
web = {
command = ["npm" "run" "start" "--" "--port" "$PORT" "--host" "0.0.0.0"];
manager = "web";
};
};
};
};
}
35 changes: 35 additions & 0 deletions adev/src/content/tutorials/learn-angular/common/idx/dev.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# To learn more about how to use Nix to configure your environment
# see: https://developers.google.com/idx/guides/customize-idx-env
{ pkgs, ... }: {
# Which nixpkgs channel to use.
channel = "stable-23.11"; # or "unstable"
# Use https://search.nixos.org/packages to find packages
packages = [
pkgs.nodejs_18
];
# Sets environment variables in the workspace
env = {};
idx = {
# Search for the extensions you want on https://open-vsx.org/ and use "publisher.id"
extensions = [
"angular.ng-template"
];
workspace = {
# Runs when a workspace is first created with this \`dev.nix\` file
onCreate = {
npm-install = "npm install --no-audit --prefer-offline";
};
# To run something each time the environment is rebuilt, use the \`onStart\` hook
};
# Enable previews and customize configuration
previews = {
enable = true;
previews = {
web = {
command = ["npm" "run" "start" "--" "--port" "$PORT" "--host" "0.0.0.0"];
manager = "web";
};
};
};
};
}
35 changes: 35 additions & 0 deletions adev/src/content/tutorials/playground/common/idx/dev.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# To learn more about how to use Nix to configure your environment
# see: https://developers.google.com/idx/guides/customize-idx-env
{ pkgs, ... }: {
# Which nixpkgs channel to use.
channel = "stable-23.11"; # or "unstable"
# Use https://search.nixos.org/packages to find packages
packages = [
pkgs.nodejs_18
];
# Sets environment variables in the workspace
env = {};
idx = {
# Search for the extensions you want on https://open-vsx.org/ and use "publisher.id"
extensions = [
"angular.ng-template"
];
workspace = {
# Runs when a workspace is first created with this \`dev.nix\` file
onCreate = {
npm-install = "npm install --no-audit --prefer-offline";
};
# To run something each time the environment is rebuilt, use the \`onStart\` hook
};
# Enable previews and customize configuration
previews = {
enable = true;
previews = {
web = {
command = ["npm" "run" "start" "--" "--port" "$PORT" "--host" "0.0.0.0"];
manager = "web";
};
};
};
};
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
"memo-decorator": "^2.0.1",
"ngx-flamegraph": "0.0.12",
"ngx-progressbar": "^11.1.0",
"open-in-idx": "^0.1.1",
"protractor": "^7.0.0",
"reflect-metadata": "^0.2.0",
"requirejs": "^2.3.6",
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -13260,6 +13260,11 @@ onetime@^5.1.0, onetime@^5.1.2:
dependencies:
mimic-fn "^2.1.0"

open-in-idx@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/open-in-idx/-/open-in-idx-0.1.1.tgz#390cb0985146a461f5a662ed1fd0db3fce55b2f0"
integrity sha512-4Cks2eY4bnWpBP/fEj1deRrVYbHME36g0w4/IFDG4iwnkD7CwmK9HrF3A3LR/RKHs5AXUMj49YxnwdIxEizDpA==

[email protected]:
version "8.4.2"
resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9"
Expand Down

0 comments on commit ca8bd5b

Please sign in to comment.