From e851b924499b9496501b21708757d752199e6ad1 Mon Sep 17 00:00:00 2001 From: polamoros Date: Mon, 22 May 2023 14:04:22 +0200 Subject: [PATCH 01/52] wip --- apps/tour/src/Editor.tsx | 44 ++++++++++--- packages/shared/src/Tabs.tsx | 116 +++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+), 8 deletions(-) create mode 100644 packages/shared/src/Tabs.tsx diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index 1dd0202c..963b3141 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -41,6 +41,7 @@ import {CongratsModal} from "./CongratsModal"; import {SimulatorTarget} from "@wing-playground/shared/src/SimulatorTarget"; import {TargetsView, TargetView} from "./TargetsView"; import {PanelHeader} from "@wing-playground/shared/src/PanelHeader"; +import {Tabs} from "@wing-playground/shared/src/Tabs"; const wingPackageJson = await import("winglang/package.json?raw").then( (i) => JSON.parse(i.default) @@ -204,6 +205,8 @@ export const ReactMonacoEditor: React.FC = ({ } }, [iframSrc, refIframe]); + + const [currentTab, setCurrentTab] = useState("simulator"); return ( <>
@@ -298,14 +301,39 @@ export const ReactMonacoEditor: React.FC = ({
-
- {loadingStatus != LoadingStatus.Completed ? - : - - } -
+ + {loadingStatus != LoadingStatus.Completed ? + : + + } + + ), + }, + { + id: "the other", + name: "SDK", + panel: ( +
:)
+ ), + }, + + ]} + currentTabId={currentTab} + onTabChange={setCurrentTab} + /> diff --git a/packages/shared/src/Tabs.tsx b/packages/shared/src/Tabs.tsx new file mode 100644 index 00000000..7148b628 --- /dev/null +++ b/packages/shared/src/Tabs.tsx @@ -0,0 +1,116 @@ +import classNames from "classnames"; +import { ReactNode, useEffect, useState } from "react"; + +export interface Tab { + id: string; + name: string; + icon?: ReactNode; + panel?: ReactNode | (() => ReactNode); + count?: number; + tabClassName?: string; +} + +export interface TabsProps { + tabs: Tab[]; + currentTabId?: string; + onTabChange?: (tabId: string) => void; + renderActiveTabPanelOnly?: boolean; + tabsWithNotifications?: string[]; + className?: string; +} + +export const Tabs = (props: TabsProps) => { + const [currentTabId, setCurrentTabId] = useState(props.currentTabId); + + useEffect(() => { + if (props.currentTabId) { + setCurrentTabId(props.currentTabId); + } + }, [props]); + + useEffect(() => { + if (props.onTabChange && currentTabId) { + props.onTabChange(currentTabId); + } + }, [currentTabId]); + + return ( +
+
+
+ {props.tabs.map((tab) => { + const isCurrent = tab.id === currentTabId; + return ( +
setCurrentTabId(tab.id)} + > + {tab.icon &&
{tab.icon}
} +
+ {tab.name} + {tab.count !== undefined && ( + ({tab.count}) + )} +
+ + {props.tabsWithNotifications?.includes(tab.id) && ( +
+ + + + +
+ )} +
+ ); + })} +
+
+ + {props.tabs.map((tab) => { + const isCurrent = tab.id === currentTabId; + if (props.renderActiveTabPanelOnly && !isCurrent) { + return; + } + + return ( +
+ {typeof tab.panel === "function" ? tab.panel() : tab.panel} +
+ ); + })} +
+ ); +}; From ece7193820a3deeada6a7c44b6240d2b5e7dee73 Mon Sep 17 00:00:00 2001 From: polamoros Date: Mon, 22 May 2023 15:58:08 +0200 Subject: [PATCH 02/52] wip --- apps/tour/src/Editor.tsx | 60 +++----- apps/tour/src/TargetsView.tsx | 46 ++++-- packages/shared/src/AwsTerraformTarget.tsx | 168 +++++++++++++++++++++ 3 files changed, 228 insertions(+), 46 deletions(-) create mode 100644 packages/shared/src/AwsTerraformTarget.tsx diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index 963b3141..9ec59138 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -39,9 +39,9 @@ import {installDependencies} from "@wing-playground/shared/src/containers"; import {WelcomeModal} from "./WelcomeModal"; import {CongratsModal} from "./CongratsModal"; import {SimulatorTarget} from "@wing-playground/shared/src/SimulatorTarget"; +import {AwsTerraformTarget} from "@wing-playground/shared/src/AwsTerraformTarget"; import {TargetsView, TargetView} from "./TargetsView"; import {PanelHeader} from "@wing-playground/shared/src/PanelHeader"; -import {Tabs} from "@wing-playground/shared/src/Tabs"; const wingPackageJson = await import("winglang/package.json?raw").then( (i) => JSON.parse(i.default) @@ -205,8 +205,18 @@ export const ReactMonacoEditor: React.FC = ({ } }, [iframSrc, refIframe]); + const awsTerraformTarget: TargetView = useMemo(() => { + return { + title: "AWS/Terraform", + Target: () => + + } + }, []); + + const [currentTarget, setCurrentTarget] = useState(simulatorTarget); - const [currentTab, setCurrentTab] = useState("simulator"); return ( <>
@@ -301,39 +311,19 @@ export const ReactMonacoEditor: React.FC = ({
- - {loadingStatus != LoadingStatus.Completed ? - : - - } - - ), - }, - { - id: "the other", - name: "SDK", - panel: ( -
:)
- ), - }, - - ]} - currentTabId={currentTab} - onTabChange={setCurrentTab} - /> +
+ {loadingStatus != LoadingStatus.Completed ? + : + + } +
diff --git a/apps/tour/src/TargetsView.tsx b/apps/tour/src/TargetsView.tsx index 9a24e575..fd40d8c6 100644 --- a/apps/tour/src/TargetsView.tsx +++ b/apps/tour/src/TargetsView.tsx @@ -1,6 +1,6 @@ -import {SimulatorTarget} from "@wing-playground/shared/src/SimulatorTarget"; -import React from "react"; -import {PanelHeader} from "@wing-playground/shared/src/PanelHeader"; +import React, { useEffect, useState } from "react"; +import { Tab, Tabs } from "@wing-playground/shared/src/Tabs"; +import classNames from "classnames"; export interface TargetView { title: string; @@ -12,13 +12,37 @@ export interface TargetsViewProps { setCurrentTarget?: (target: TargetView) => void; } export const TargetsView = ({targets, setCurrentTarget, currentTarget}: TargetsViewProps) => { + + const [tabs, setTabs] = useState([]); + + useEffect(() => { + const tabs: Tab[] = []; + targets.forEach((target) => { + tabs.push({ + id: target.title, + name: target.title, + panel: , + }); + }); + setTabs(tabs); + }, [targets]); + return ( -
- {targets.map((target, index) => ( -
- {target.title} - -
))} -
+ { + const target = targets.find((target) => target.title === tabId); + if (!target || !setCurrentTarget) { + return; + } + setCurrentTarget(target); + }} + /> ); -} \ No newline at end of file +} diff --git a/packages/shared/src/AwsTerraformTarget.tsx b/packages/shared/src/AwsTerraformTarget.tsx new file mode 100644 index 00000000..0d764e20 --- /dev/null +++ b/packages/shared/src/AwsTerraformTarget.tsx @@ -0,0 +1,168 @@ +import {useEffect, useRef, useState} from "react"; +import Editor from "@monaco-editor/react"; +import * as monaco from 'monaco-editor'; +import classNames from "classnames"; + +export interface AwsTerraformTargetProps { + compilations: any[]; +} + +export interface TerraformFile { + name: string; + description: string; + content: string; +} + +export interface Asset { + name: string; + description: string; + content: string; +} + +const FileButton = ({file, icon, selected, onClick}: { + file: TerraformFile, + icon?: React.ReactNode, + selected: boolean, + onClick: () => void +}) => { + return ( + + ) +} + + +export const AwsTerraformTarget = ({compilations}: AwsTerraformTargetProps) => { + + const compileEditorRef = useRef(); + + const tfFiles: TerraformFile[] = [ + { + name: "main.tf", + description: "The main file", + content: `resource "aws_instance" "example" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t2.micro" +}`, + }, + { + name: "variables.tf", + description: "The variables file", + content: `variable "aws_region" { + default = "us-east-1" +}`, + }, + { + name: "outputs.tf", + description: "The outputs file", + content: `output "instance_ip_addr" { + value = aws_instance.example.public_ip +}`, + }, + ]; + + const asseets: Asset[] = [ + { + name: "Javascript", + description: "cloud.Function1/Code", + content: `exports.handler = async (event) => { + const response = { + statusCode: 200, + body: JSON.stringify('Hello from Lambda!'), + }; + return response; +};`, + }, + { + name: "Javascript 2", + description: "cloud.Function2/Code", + content: `exports.handler = async (event) => { + const response = { + statusCode: 200, + body: JSON.stringify('Hello from Lambda!'), + }; + return response; +};`} + ]; + + const [selectedFile, setSelectedFile] = useState(tfFiles[0]); + + const options: monaco.editor.IStandaloneEditorConstructionOptions = { + minimap: { enabled: false }, + }; + + +const compileEditorDidMount = async (editor: any, monaco: any) => { + compileEditorRef.current = editor +} + + useEffect(() => { + console.log("AwsTerraformTarget", compilations[compilations.length - 1]); + console.log("AwsTerraformTarget", compilations); + }, [compilations]); + + return ( +
+
+
+
Terraform
+
+
+ {tfFiles.map((file) => { + return ( + setSelectedFile(file)} + /> + ) + })} +
+
+
+
Assets
+
+
+ {asseets.map((asset) => { + return ( + setSelectedFile(asset)} + /> + ) + })} +
+
+ +
+ +
+
+ ) +} From 19056d45d3ebf8768fe3f87f29b490c1ce1e9205 Mon Sep 17 00:00:00 2001 From: polamoros Date: Mon, 22 May 2023 16:42:31 +0200 Subject: [PATCH 03/52] wip --- apps/tour/src/Editor.tsx | 48 +++++++++- packages/shared/src/AwsTerraformTarget.tsx | 100 ++++++--------------- 2 files changed, 73 insertions(+), 75 deletions(-) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index 9ec59138..5ba2015e 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -25,7 +25,7 @@ import { WebContainer } from '@webcontainer/api'; import ReactMarkdown from 'react-markdown' import { Loading } from '@wing-playground/shared/src/Loading'; -import { Compiler, Target } from '@wing-playground/shared/src/compiler/compiler'; +import { CompilationItem, CompilationResult, Compiler, Target } from '@wing-playground/shared/src/compiler/compiler'; import { CompilationRequest } from '@wing-playground/shared/src/compiler/request'; import { useExamples, Example } from '@wing-playground/shared/src/use-examples.js'; import { tutorials } from './tutorials/index.js'; @@ -42,6 +42,7 @@ import {SimulatorTarget} from "@wing-playground/shared/src/SimulatorTarget"; import {AwsTerraformTarget} from "@wing-playground/shared/src/AwsTerraformTarget"; import {TargetsView, TargetView} from "./TargetsView"; import {PanelHeader} from "@wing-playground/shared/src/PanelHeader"; +import { CompletionItem } from 'monaco-languageclient/.'; const wingPackageJson = await import("winglang/package.json?raw").then( (i) => JSON.parse(i.default) @@ -205,12 +206,55 @@ export const ReactMonacoEditor: React.FC = ({ } }, [iframSrc, refIframe]); + const [items, setItems] = useState([ + { + name: "main.tf", + + contents: `resource "aws_instance" "example" { +ami = "ami-0c55b159cbfafe1f0" +instance_type = "t2.micro" +}`, + }, + { + name: "variables.tf", + contents: `variable "aws_region" { +default = "us-east-1" +}`, + }, + { + name: "outputs.tf", + contents: `output "instance_ip_addr" { +value = aws_instance.example.public_ip +}`, + }, + { + name: "Javascript", + contents: `exports.handler = async (event) => { + const response = { + statusCode: 200, + body: JSON.stringify('Hello from Lambda!'), + }; + return response; +};`, + }, + { + name: "Javascript 2", + + contents: `exports.handler = async (event) => { + const response = { + statusCode: 200, + body: JSON.stringify('Hello from Lambda!'), + }; + return response; +};`} + ]); + const awsTerraformTarget: TargetView = useMemo(() => { return { title: "AWS/Terraform", Target: () => } }, []); diff --git a/packages/shared/src/AwsTerraformTarget.tsx b/packages/shared/src/AwsTerraformTarget.tsx index 0d764e20..82ca635c 100644 --- a/packages/shared/src/AwsTerraformTarget.tsx +++ b/packages/shared/src/AwsTerraformTarget.tsx @@ -2,25 +2,14 @@ import {useEffect, useRef, useState} from "react"; import Editor from "@monaco-editor/react"; import * as monaco from 'monaco-editor'; import classNames from "classnames"; +import { CompilationItem } from "./compiler/compiler"; export interface AwsTerraformTargetProps { - compilations: any[]; -} - -export interface TerraformFile { - name: string; - description: string; - content: string; -} - -export interface Asset { - name: string; - description: string; - content: string; + items?: CompilationItem[]; } const FileButton = ({file, icon, selected, onClick}: { - file: TerraformFile, + file: CompilationItem, icon?: React.ReactNode, selected: boolean, onClick: () => void @@ -48,60 +37,12 @@ const FileButton = ({file, icon, selected, onClick}: { } -export const AwsTerraformTarget = ({compilations}: AwsTerraformTargetProps) => { +export const AwsTerraformTarget = ({ items }: AwsTerraformTargetProps) => { const compileEditorRef = useRef(); - - const tfFiles: TerraformFile[] = [ - { - name: "main.tf", - description: "The main file", - content: `resource "aws_instance" "example" { - ami = "ami-0c55b159cbfafe1f0" - instance_type = "t2.micro" -}`, - }, - { - name: "variables.tf", - description: "The variables file", - content: `variable "aws_region" { - default = "us-east-1" -}`, - }, - { - name: "outputs.tf", - description: "The outputs file", - content: `output "instance_ip_addr" { - value = aws_instance.example.public_ip -}`, - }, - ]; - - const asseets: Asset[] = [ - { - name: "Javascript", - description: "cloud.Function1/Code", - content: `exports.handler = async (event) => { - const response = { - statusCode: 200, - body: JSON.stringify('Hello from Lambda!'), - }; - return response; -};`, - }, - { - name: "Javascript 2", - description: "cloud.Function2/Code", - content: `exports.handler = async (event) => { - const response = { - statusCode: 200, - body: JSON.stringify('Hello from Lambda!'), - }; - return response; -};`} - ]; - - const [selectedFile, setSelectedFile] = useState(tfFiles[0]); + const [tfFiles, setTfFiles] = useState([]); + const [assets, setAssets] = useState([]); + const [selectedFile, setSelectedFile] = useState(); const options: monaco.editor.IStandaloneEditorConstructionOptions = { minimap: { enabled: false }, @@ -113,9 +54,22 @@ const compileEditorDidMount = async (editor: any, monaco: any) => { } useEffect(() => { - console.log("AwsTerraformTarget", compilations[compilations.length - 1]); - console.log("AwsTerraformTarget", compilations); - }, [compilations]); + if (!items) { + return; + } + const files: CompilationItem[] = []; + const assets: CompilationItem[] = [] + items.forEach((file) => { + if (file.name.endsWith(".tf")) { + files.push(file); + } else { + assets.push(file); + } + }); + setTfFiles(files); + setAssets(assets); + setSelectedFile(files[0]); + }, [items]); return (
@@ -129,7 +83,7 @@ const compileEditorDidMount = async (editor: any, monaco: any) => { setSelectedFile(file)} /> ) @@ -140,12 +94,12 @@ const compileEditorDidMount = async (editor: any, monaco: any) => {
Assets
- {asseets.map((asset) => { + {assets.map((asset) => { return ( setSelectedFile(asset)} /> ) @@ -160,7 +114,7 @@ const compileEditorDidMount = async (editor: any, monaco: any) => { language="js" options={Object.assign({}, options, { readOnly: true })} onMount={compileEditorDidMount} - value={selectedFile.content} + value={selectedFile?.contents} />
From 85ef17f2973e33fcef28ef1621e6a03a0824c03e Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 09:35:32 +0200 Subject: [PATCH 04/52] wip --- apps/tour/src/Editor.tsx | 68 +++++----------------- apps/tour/src/TargetsView.tsx | 16 +++-- packages/shared/src/AwsTerraformTarget.tsx | 33 +++++------ packages/shared/src/compiler/compiler.ts | 4 +- packages/shared/src/editor/use-editor.tsx | 30 ++++++++-- 5 files changed, 59 insertions(+), 92 deletions(-) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index 5ba2015e..1562fdbf 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -94,7 +94,7 @@ export const ReactMonacoEditor: React.FC = ({ version: wingPackageJson.version }); } - const {evaluateCode, editorWillMount, editorDidMount } = useEditor({ + const {evaluateCode, editorWillMount, editorDidMount, targetsOutput } = useEditor({ editorRef, onLoadingStatusChange: setLoadingStatus, onLspError, @@ -102,6 +102,7 @@ export const ReactMonacoEditor: React.FC = ({ languageContext, code: tutorials[0].code, compiler, + targets: [Target.TFAWS], editorOptions, shouldInitContainer: true, }); @@ -206,58 +207,13 @@ export const ReactMonacoEditor: React.FC = ({ } }, [iframSrc, refIframe]); - const [items, setItems] = useState([ - { - name: "main.tf", - - contents: `resource "aws_instance" "example" { -ami = "ami-0c55b159cbfafe1f0" -instance_type = "t2.micro" -}`, - }, - { - name: "variables.tf", - contents: `variable "aws_region" { -default = "us-east-1" -}`, - }, - { - name: "outputs.tf", - contents: `output "instance_ip_addr" { -value = aws_instance.example.public_ip -}`, - }, - { - name: "Javascript", - contents: `exports.handler = async (event) => { - const response = { - statusCode: 200, - body: JSON.stringify('Hello from Lambda!'), - }; - return response; -};`, - }, - { - name: "Javascript 2", - - contents: `exports.handler = async (event) => { - const response = { - statusCode: 200, - body: JSON.stringify('Hello from Lambda!'), - }; - return response; -};`} - ]); - const awsTerraformTarget: TargetView = useMemo(() => { - return { - title: "AWS/Terraform", - Target: () => - - } - }, []); + const files = targetsOutput.find(t => t.target === Target.TFAWS)?.files ?? []; + return { + title: "AWS/Terraform", + Target: () => + } + }, [targetsOutput]); const [currentTarget, setCurrentTarget] = useState(simulatorTarget); @@ -356,8 +312,10 @@ value = aws_instance.example.public_ip
- {loadingStatus != LoadingStatus.Completed ? - : + {loadingStatus != LoadingStatus.Completed && + + } + {loadingStatus == LoadingStatus.Completed && ( - } + )}
diff --git a/apps/tour/src/TargetsView.tsx b/apps/tour/src/TargetsView.tsx index fd40d8c6..4329d2ad 100644 --- a/apps/tour/src/TargetsView.tsx +++ b/apps/tour/src/TargetsView.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useMemo } from "react"; import { Tab, Tabs } from "@wing-playground/shared/src/Tabs"; import classNames from "classnames"; @@ -7,15 +7,13 @@ export interface TargetView { Target: React.FC; } export interface TargetsViewProps { - targets: TargetView[]; - currentTarget?: TargetView; - setCurrentTarget?: (target: TargetView) => void; + targets: TargetView[]; + currentTarget?: TargetView; + setCurrentTarget?: (target: TargetView) => void; } export const TargetsView = ({targets, setCurrentTarget, currentTarget}: TargetsViewProps) => { - const [tabs, setTabs] = useState([]); - - useEffect(() => { + const tabs = useMemo(() => { const tabs: Tab[] = []; targets.forEach((target) => { tabs.push({ @@ -24,7 +22,7 @@ export const TargetsView = ({targets, setCurrentTarget, currentTarget}: TargetsV panel: , }); }); - setTabs(tabs); + return tabs; }, [targets]); return ( @@ -32,7 +30,7 @@ export const TargetsView = ({targets, setCurrentTarget, currentTarget}: TargetsV className={classNames( "text-white bg-gray-800 border-b border-black", "uppercase text-xs font-semibold leading-7 tracking-widest", - "rounded-t-lg overflow-hidden" + "rounded-t-lg overflow-hidden", )} tabs={tabs} currentTabId={currentTarget?.title} diff --git a/packages/shared/src/AwsTerraformTarget.tsx b/packages/shared/src/AwsTerraformTarget.tsx index 82ca635c..cd51111f 100644 --- a/packages/shared/src/AwsTerraformTarget.tsx +++ b/packages/shared/src/AwsTerraformTarget.tsx @@ -5,7 +5,7 @@ import classNames from "classnames"; import { CompilationItem } from "./compiler/compiler"; export interface AwsTerraformTargetProps { - items?: CompilationItem[]; + files?: CompilationItem[]; } const FileButton = ({file, icon, selected, onClick}: { @@ -37,11 +37,9 @@ const FileButton = ({file, icon, selected, onClick}: { } -export const AwsTerraformTarget = ({ items }: AwsTerraformTargetProps) => { +export const AwsTerraformTarget = ({ files }: AwsTerraformTargetProps) => { const compileEditorRef = useRef(); - const [tfFiles, setTfFiles] = useState([]); - const [assets, setAssets] = useState([]); const [selectedFile, setSelectedFile] = useState(); const options: monaco.editor.IStandaloneEditorConstructionOptions = { @@ -52,24 +50,13 @@ export const AwsTerraformTarget = ({ items }: AwsTerraformTargetProps) => { const compileEditorDidMount = async (editor: any, monaco: any) => { compileEditorRef.current = editor } - useEffect(() => { - if (!items) { + if (!files) { return; } - const files: CompilationItem[] = []; - const assets: CompilationItem[] = [] - items.forEach((file) => { - if (file.name.endsWith(".tf")) { - files.push(file); - } else { - assets.push(file); - } - }); - setTfFiles(files); - setAssets(assets); + console.log(files); setSelectedFile(files[0]); - }, [items]); + }, [files]); return (
@@ -78,7 +65,10 @@ const compileEditorDidMount = async (editor: any, monaco: any) => {
Terraform
- {tfFiles.map((file) => { + {files?.map((file) => { + if (file.name.endsWith(".js")) { + return null; + } return ( {
Assets
- {assets.map((asset) => { + {files?.map((asset) => { + if (!asset.name.endsWith(".js")) { + return null; + } return ( ) => Promise; editorTheme?: string; shouldInitContainer: boolean; } +export type TargetOutput = { + target: Target, + files: CompilationItem[] +} + const darkPlusTheme = convertTheme(darkPlusTMTheme); -export const useEditor = ({editorRef, onLoadingStatusChange, onLspError, code, languageContext, compiler, installConsole, editorTheme, shouldInitContainer}: UseEditorOptions) => { +export const useEditor = ({editorRef, onLoadingStatusChange, onLspError, code, languageContext, compiler, targets, installConsole, editorTheme, shouldInitContainer}: UseEditorOptions) => { const [isCompiling, setIsCompiling] = useState(false); const containerRef = useRef(); const monacoRef = useRef(); + const [targetsOutput, setTargetsOutput] = useState([]); const editorWillMount = (monaco: any) => { @@ -89,11 +96,21 @@ export const useEditor = ({editorRef, onLoadingStatusChange, onLspError, code, l return; } console.log('evaluating...', languageContext) - setIsCompiling(true) + setIsCompiling(true); + try { - let compileValue = editorRef.current?.getValue() - await prepareForEvaluation(containerRef.current, compileValue, languageContext.file) - await compiler.submit(new CompilationRequest(compileValue!, Target.TFAWS)); + const outputs: TargetOutput[] = []; + let compileValue = editorRef.current?.getValue() + await prepareForEvaluation(containerRef.current, compileValue, languageContext.file) + targets.forEach(async target => { + const compilation = await compiler.compile(new CompilationRequest(compileValue!, target)); + const output = { + target, + files: compilation.files + } + outputs.push(output); + }) + setTargetsOutput(outputs); } finally { onLoadingStatusChange(LoadingStatus.Completed) setIsCompiling(false) @@ -105,5 +122,6 @@ export const useEditor = ({editorRef, onLoadingStatusChange, onLspError, code, l editorDidMount, evaluateCode, isCompiling, + targetsOutput, } } From d4e71a2400ec8196848cd63649cb32e64838d37a Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 09:42:29 +0200 Subject: [PATCH 05/52] wip --- packages/shared/src/editor/use-editor.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/shared/src/editor/use-editor.tsx b/packages/shared/src/editor/use-editor.tsx index f4c25ea9..89742f0a 100644 --- a/packages/shared/src/editor/use-editor.tsx +++ b/packages/shared/src/editor/use-editor.tsx @@ -99,18 +99,18 @@ export const useEditor = ({editorRef, onLoadingStatusChange, onLspError, code, l setIsCompiling(true); try { - const outputs: TargetOutput[] = []; let compileValue = editorRef.current?.getValue() await prepareForEvaluation(containerRef.current, compileValue, languageContext.file) + + setTargetsOutput([]); targets.forEach(async target => { const compilation = await compiler.compile(new CompilationRequest(compileValue!, target)); const output = { target, files: compilation.files } - outputs.push(output); - }) - setTargetsOutput(outputs); + setTargetsOutput(prev => [...prev, output]); + }); } finally { onLoadingStatusChange(LoadingStatus.Completed) setIsCompiling(false) From 22e667e8a8dc148ebcd215876b17a081fd9e6540 Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 10:05:55 +0200 Subject: [PATCH 06/52] add multiple target support --- apps/tour/src/Editor.tsx | 30 ++++++++++++------- apps/tour/src/tutorials/index.ts | 22 +++++++++----- ...erraformTarget.tsx => TerraformTarget.tsx} | 26 ++++++++++++---- 3 files changed, 54 insertions(+), 24 deletions(-) rename packages/shared/src/{AwsTerraformTarget.tsx => TerraformTarget.tsx} (70%) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index 1562fdbf..ba5c6b46 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -39,10 +39,9 @@ import {installDependencies} from "@wing-playground/shared/src/containers"; import {WelcomeModal} from "./WelcomeModal"; import {CongratsModal} from "./CongratsModal"; import {SimulatorTarget} from "@wing-playground/shared/src/SimulatorTarget"; -import {AwsTerraformTarget} from "@wing-playground/shared/src/AwsTerraformTarget"; +import {TerraformTarget} from "@wing-playground/shared/src/TerraformTarget"; import {TargetsView, TargetView} from "./TargetsView"; import {PanelHeader} from "@wing-playground/shared/src/PanelHeader"; -import { CompletionItem } from 'monaco-languageclient/.'; const wingPackageJson = await import("winglang/package.json?raw").then( (i) => JSON.parse(i.default) @@ -94,6 +93,9 @@ export const ReactMonacoEditor: React.FC = ({ version: wingPackageJson.version }); } + + const [targets, setTargets] = useState(tutorials[0].targets); + const {evaluateCode, editorWillMount, editorDidMount, targetsOutput } = useEditor({ editorRef, onLoadingStatusChange: setLoadingStatus, @@ -102,7 +104,7 @@ export const ReactMonacoEditor: React.FC = ({ languageContext, code: tutorials[0].code, compiler, - targets: [Target.TFAWS], + targets, editorOptions, shouldInitContainer: true, }); @@ -177,6 +179,7 @@ export const ReactMonacoEditor: React.FC = ({ analytics.track(`tutorial: step: ${currentStepId}: changed`, { step: currentStep }) + setTargets(currentStep.targets); }, [currentStep]); const downloadCompiledCode = async (target: Target) => { @@ -207,13 +210,18 @@ export const ReactMonacoEditor: React.FC = ({ } }, [iframSrc, refIframe]); - const awsTerraformTarget: TargetView = useMemo(() => { - const files = targetsOutput.find(t => t.target === Target.TFAWS)?.files ?? []; - return { - title: "AWS/Terraform", - Target: () => - } - }, [targetsOutput]); + const terraformTargets: TargetView[] = useMemo(() => { + return targets.map(target => { + const files = targetsOutput.find(t => t.target === target)?.files ?? []; + console.log("TARGET", target); + console.log("files", files); + return { + title: target, + Target: () => + + } + }); + }, [targets, targetsOutput]); const [currentTarget, setCurrentTarget] = useState(simulatorTarget); @@ -319,7 +327,7 @@ export const ReactMonacoEditor: React.FC = ({ { +export const TerraformTarget = ({ files }: TerraformTargetProps) => { const compileEditorRef = useRef(); const [selectedFile, setSelectedFile] = useState(); @@ -54,13 +67,12 @@ const compileEditorDidMount = async (editor: any, monaco: any) => { if (!files) { return; } - console.log(files); setSelectedFile(files[0]); }, [files]); return (
-
+
Terraform
@@ -79,7 +91,7 @@ const compileEditorDidMount = async (editor: any, monaco: any) => { ) })}
-
+
Assets
@@ -100,8 +112,10 @@ const compileEditorDidMount = async (editor: any, monaco: any) => {
-
+
+ Date: Tue, 23 May 2023 12:49:17 +0200 Subject: [PATCH 07/52] wip --- apps/tour/public/aws_lambda.svg | 7 + apps/tour/public/aws_s3.svg | 7 + apps/tour/public/aws_sqs.svg | 7 + apps/tour/src/Editor.tsx | 48 ++-- .../tour}/src/TerraformTarget.tsx | 2 +- apps/tour/src/TfAwsTarget.tsx | 214 ++++++++++++++++++ apps/tour/src/tutorials/index.ts | 10 +- packages/shared/src/compiler/compiler.ts | 1 + packages/shared/tsconfig.json | 2 +- 9 files changed, 274 insertions(+), 24 deletions(-) create mode 100644 apps/tour/public/aws_lambda.svg create mode 100644 apps/tour/public/aws_s3.svg create mode 100644 apps/tour/public/aws_sqs.svg rename {packages/shared => apps/tour}/src/TerraformTarget.tsx (98%) create mode 100644 apps/tour/src/TfAwsTarget.tsx diff --git a/apps/tour/public/aws_lambda.svg b/apps/tour/public/aws_lambda.svg new file mode 100644 index 00000000..b30cd9d9 --- /dev/null +++ b/apps/tour/public/aws_lambda.svg @@ -0,0 +1,7 @@ + + + Icon-Resource/Compute/Res_AWS-Lambda_Lambda-Function_48 + + + + \ No newline at end of file diff --git a/apps/tour/public/aws_s3.svg b/apps/tour/public/aws_s3.svg new file mode 100644 index 00000000..8d2bced6 --- /dev/null +++ b/apps/tour/public/aws_s3.svg @@ -0,0 +1,7 @@ + + + Icon-Resource/Storage/Res_Amazon-Simple-Storage-Service_S3-Standard_48 + + + + \ No newline at end of file diff --git a/apps/tour/public/aws_sqs.svg b/apps/tour/public/aws_sqs.svg new file mode 100644 index 00000000..d1270107 --- /dev/null +++ b/apps/tour/public/aws_sqs.svg @@ -0,0 +1,7 @@ + + + Icon-Resource/Application-Integration/Res_Amazon-Simple-Queue-Service_Queue_48 + + + + \ No newline at end of file diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index ba5c6b46..b9314697 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -25,7 +25,7 @@ import { WebContainer } from '@webcontainer/api'; import ReactMarkdown from 'react-markdown' import { Loading } from '@wing-playground/shared/src/Loading'; -import { CompilationItem, CompilationResult, Compiler, Target } from '@wing-playground/shared/src/compiler/compiler'; +import { Compiler, Target } from '@wing-playground/shared/src/compiler/compiler'; import { CompilationRequest } from '@wing-playground/shared/src/compiler/request'; import { useExamples, Example } from '@wing-playground/shared/src/use-examples.js'; import { tutorials } from './tutorials/index.js'; @@ -38,10 +38,13 @@ import {useEditor} from "@wing-playground/shared/src/editor/use-editor"; import {installDependencies} from "@wing-playground/shared/src/containers"; import {WelcomeModal} from "./WelcomeModal"; import {CongratsModal} from "./CongratsModal"; + import {SimulatorTarget} from "@wing-playground/shared/src/SimulatorTarget"; -import {TerraformTarget} from "@wing-playground/shared/src/TerraformTarget"; + import {TargetsView, TargetView} from "./TargetsView"; import {PanelHeader} from "@wing-playground/shared/src/PanelHeader"; +import { TerraformTarget } from './TerraformTarget.js'; +import { TfAwsTarget } from './TfAwsTarget.js'; const wingPackageJson = await import("winglang/package.json?raw").then( (i) => JSON.parse(i.default) @@ -210,17 +213,31 @@ export const ReactMonacoEditor: React.FC = ({ } }, [iframSrc, refIframe]); - const terraformTargets: TargetView[] = useMemo(() => { - return targets.map(target => { - const files = targetsOutput.find(t => t.target === target)?.files ?? []; - console.log("TARGET", target); - console.log("files", files); - return { + const targetViews: TargetView[] = useMemo(() => { + const views: TargetView[] = []; + + targets.forEach(target => { + if (target === Target.SIMULATOR) { + views.push(simulatorTarget); + } + if (target.includes("tf-")) { + const files = targetsOutput.find(t => t.target === target)?.files ?? []; + + if (target === Target.TFAWS) { + views.push({ + title: "Terraform AWS", + Target: () => + }); + } + else { + views.push({ title: target, Target: () => - - } - }); + }) + } + } + }); + return views; }, [targets, targetsOutput]); const [currentTarget, setCurrentTarget] = useState(simulatorTarget); @@ -244,8 +261,8 @@ export const ReactMonacoEditor: React.FC = ({
- setShowWelcomeModal(false)}/> - setShowFinishModal(false)}/> + {/* setShowWelcomeModal(false)}/> + setShowFinishModal(false)}/> */}
@@ -325,10 +342,7 @@ export const ReactMonacoEditor: React.FC = ({ } {loadingStatus == LoadingStatus.Completed && ( diff --git a/packages/shared/src/TerraformTarget.tsx b/apps/tour/src/TerraformTarget.tsx similarity index 98% rename from packages/shared/src/TerraformTarget.tsx rename to apps/tour/src/TerraformTarget.tsx index 73fc28ea..89c5ac9a 100644 --- a/packages/shared/src/TerraformTarget.tsx +++ b/apps/tour/src/TerraformTarget.tsx @@ -15,7 +15,7 @@ import 'monaco-editor/esm/vs/editor/standalone/browser/toggleHighContrast/toggle import * as monaco from 'monaco-editor'; import classNames from "classnames"; -import { CompilationItem } from "./compiler/compiler"; +import { CompilationItem } from "@wing-playground/shared/src/compiler/compiler"; export interface TerraformTargetProps { files?: CompilationItem[]; diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx new file mode 100644 index 00000000..b4d6a1b5 --- /dev/null +++ b/apps/tour/src/TfAwsTarget.tsx @@ -0,0 +1,214 @@ +import {useEffect, useRef, useState} from "react"; +import Editor from "@monaco-editor/react"; + +// support all editor features +import 'monaco-editor/esm/vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/inspectTokens/inspectTokens.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneHelpQuickAccess.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneGotoLineQuickAccess.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneGotoSymbolQuickAccess.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneCommandsQuickAccess.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/quickInput/standaloneQuickInputService.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/referenceSearch/standaloneReferenceSearch.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast.js'; + +import * as monaco from 'monaco-editor'; +import classNames from "classnames"; +import { CompilationItem } from "@wing-playground/shared/src/compiler/compiler"; + + +const FileButton = ({file, icon, selected, onClick}: { + file: CompilationItem, + icon?: React.ReactNode, + selected: boolean, + onClick: () => void +}) => { + return ( + + ) +} + +const getResourceName = (type: string) => { + if (type === "aws_sqs_queue") { + return "SQS"; + + } + return type; +} + +const getIconName = (type: string) => { + switch (type) { + case "aws_sqs_queue": + return "aws_sqs.svg"; + case "aws_s3_bucket": + return "aws_s3.svg"; + case "aws_lambda_function": + return "aws_lambda.svg"; + default: + return null; + } +} + + +const ResourceIcon = ({type}: {type: string}) => { + const iconName = getIconName(type); + if (!iconName) { + return null; + } + return +} + +export type Resource = { + name: string; + type: string; + contents: string; +} + +const ResourceRow = ({resource, selected, onClick}: { + resource: Resource, + selected: boolean, + onClick: () => void +}) => { + return ( + + ) +} + +const extractAwsResources = (tfFile: string) => { + try { + const json = JSON.parse(tfFile); + console.log(json); + if (!json.resource) { + return []; + } + + const resources: Resource[] = []; + for (const [key, value] of Object.entries(json.resource)) { + const resourceId = Object.keys(value as object)[0]; + resources.push({ + name: resourceId, + type: key, + contents: JSON.stringify(value, null, 2) + }); + } + return resources; + } catch (e) { + return []; + } +} + +export interface TfAwsTargetProps { + files?: CompilationItem[]; +} + +export const TfAwsTarget = ({ files }: TfAwsTargetProps) => { + + const compileEditorRef = useRef(); + const [selectedFile, setSelectedFile] = useState(files?.[0]); + const [resources, setResources] = useState([]); + + const options: monaco.editor.IStandaloneEditorConstructionOptions = { + minimap: { enabled: false }, + }; + + const compileEditorDidMount = async (editor: any, monaco: any) => { + compileEditorRef.current = editor + } + + useEffect(() => { + const filename = "main.tf.json"; + const newResources = extractAwsResources( + files?.find((f) => f.name === filename)?.contents || "" + ); + console.log(newResources); + setResources(newResources); + }, [files]); + + return ( +
+
+
+
Terraform
+
+
+ {resources?.map((resource) => { + return ( + setSelectedFile(resource)} + /> + ) + })} +
+
+
+
Assets
+
+
+ {files?.map((file) => { + return ( + setSelectedFile(file)} + /> + ) + })} +
+
+ +
+ + +
+
+ ) +} diff --git a/apps/tour/src/tutorials/index.ts b/apps/tour/src/tutorials/index.ts index 84f85c63..f6d2ff36 100644 --- a/apps/tour/src/tutorials/index.ts +++ b/apps/tour/src/tutorials/index.ts @@ -39,7 +39,7 @@ export const tutorials = [ code: code01, solution: solution01, tutorial: tutorial01, - targets: [Target.TFAWS, Target.TFGCP], + targets: [Target.SIMULATOR, Target.TFAWS, Target.TFGCP], }, { id: "2", @@ -47,7 +47,7 @@ export const tutorials = [ code: code02, // solution: solution02, tutorial: tutorial02, - targets: [Target.TFAWS], + targets: [Target.SIMULATOR, Target.TFAWS], }, { id: "3", @@ -55,7 +55,7 @@ export const tutorials = [ code: code03, solution: solution03, tutorial: tutorial03, - targets: [Target.TFAWS], + targets: [Target.SIMULATOR, Target.TFAWS], }, { id: "4", @@ -63,7 +63,7 @@ export const tutorials = [ code: code04, solution: solution04, tutorial: tutorial04, - targets: [Target.TFAWS], + targets: [Target.SIMULATOR, Target.TFAWS], }, { id: "5", @@ -71,7 +71,7 @@ export const tutorials = [ code: code05, solution: solution05, tutorial: tutorial05, - targets: [Target.TFAWS], + targets: [Target.SIMULATOR, Target.TFAWS], }, { id: "6", diff --git a/packages/shared/src/compiler/compiler.ts b/packages/shared/src/compiler/compiler.ts index 77d52efd..d47fa94d 100644 --- a/packages/shared/src/compiler/compiler.ts +++ b/packages/shared/src/compiler/compiler.ts @@ -3,6 +3,7 @@ import { Base64Binary } from '../utils'; import { CompilationRequest } from './request'; export enum Target { + SIMULATOR = 'simulator', TFAWS = 'tf-aws', TFGCP = 'tf-gcp', TFAzure = 'tf-azure' diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json index 3d0a51a8..07561f9a 100644 --- a/packages/shared/tsconfig.json +++ b/packages/shared/tsconfig.json @@ -16,6 +16,6 @@ "noEmit": true, "jsx": "react-jsx" }, - "include": ["src"], + "include": ["src", "../../apps/tour/src/TerraformTarget.tsx"], "references": [{ "path": "./tsconfig.node.json" }] } From c42552b7a48c0847f07965acecd7ea5737a870eb Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 13:41:00 +0200 Subject: [PATCH 08/52] wip --- apps/tour/public/aws/aws_iam_role.svg | 3 + apps/tour/public/aws/aws_iam_role_policy.svg | 3 + apps/tour/public/aws/aws_lambda.svg | 3 + apps/tour/public/aws/aws_s3_bucket.svg | 3 + apps/tour/public/aws/aws_s3_object.svg | 3 + apps/tour/public/aws/aws_sqs_queue.svg | 3 + apps/tour/public/aws_lambda.svg | 7 - apps/tour/public/aws_s3.svg | 7 - apps/tour/public/aws_sqs.svg | 7 - apps/tour/src/TfAwsTarget.tsx | 162 +++++++++---------- 10 files changed, 93 insertions(+), 108 deletions(-) create mode 100644 apps/tour/public/aws/aws_iam_role.svg create mode 100644 apps/tour/public/aws/aws_iam_role_policy.svg create mode 100644 apps/tour/public/aws/aws_lambda.svg create mode 100644 apps/tour/public/aws/aws_s3_bucket.svg create mode 100644 apps/tour/public/aws/aws_s3_object.svg create mode 100644 apps/tour/public/aws/aws_sqs_queue.svg delete mode 100644 apps/tour/public/aws_lambda.svg delete mode 100644 apps/tour/public/aws_s3.svg delete mode 100644 apps/tour/public/aws_sqs.svg diff --git a/apps/tour/public/aws/aws_iam_role.svg b/apps/tour/public/aws/aws_iam_role.svg new file mode 100644 index 00000000..79330f47 --- /dev/null +++ b/apps/tour/public/aws/aws_iam_role.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/tour/public/aws/aws_iam_role_policy.svg b/apps/tour/public/aws/aws_iam_role_policy.svg new file mode 100644 index 00000000..11c091ba --- /dev/null +++ b/apps/tour/public/aws/aws_iam_role_policy.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/tour/public/aws/aws_lambda.svg b/apps/tour/public/aws/aws_lambda.svg new file mode 100644 index 00000000..b025b9da --- /dev/null +++ b/apps/tour/public/aws/aws_lambda.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/tour/public/aws/aws_s3_bucket.svg b/apps/tour/public/aws/aws_s3_bucket.svg new file mode 100644 index 00000000..0856fd63 --- /dev/null +++ b/apps/tour/public/aws/aws_s3_bucket.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/tour/public/aws/aws_s3_object.svg b/apps/tour/public/aws/aws_s3_object.svg new file mode 100644 index 00000000..f51e0059 --- /dev/null +++ b/apps/tour/public/aws/aws_s3_object.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/tour/public/aws/aws_sqs_queue.svg b/apps/tour/public/aws/aws_sqs_queue.svg new file mode 100644 index 00000000..a28e479c --- /dev/null +++ b/apps/tour/public/aws/aws_sqs_queue.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/tour/public/aws_lambda.svg b/apps/tour/public/aws_lambda.svg deleted file mode 100644 index b30cd9d9..00000000 --- a/apps/tour/public/aws_lambda.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - Icon-Resource/Compute/Res_AWS-Lambda_Lambda-Function_48 - - - - \ No newline at end of file diff --git a/apps/tour/public/aws_s3.svg b/apps/tour/public/aws_s3.svg deleted file mode 100644 index 8d2bced6..00000000 --- a/apps/tour/public/aws_s3.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - Icon-Resource/Storage/Res_Amazon-Simple-Storage-Service_S3-Standard_48 - - - - \ No newline at end of file diff --git a/apps/tour/public/aws_sqs.svg b/apps/tour/public/aws_sqs.svg deleted file mode 100644 index d1270107..00000000 --- a/apps/tour/public/aws_sqs.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - Icon-Resource/Application-Integration/Res_Amazon-Simple-Queue-Service_Queue_48 - - - - \ No newline at end of file diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index b4d6a1b5..b4830137 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -1,4 +1,4 @@ -import {useEffect, useRef, useState} from "react"; +import {useEffect, useMemo, useRef, useState} from "react"; import Editor from "@monaco-editor/react"; // support all editor features @@ -18,62 +18,69 @@ import classNames from "classnames"; import { CompilationItem } from "@wing-playground/shared/src/compiler/compiler"; -const FileButton = ({file, icon, selected, onClick}: { - file: CompilationItem, +const FileRow = ({title, description, icon, selected, onClick}: { + title: string, + description?: string, icon?: React.ReactNode, selected: boolean, onClick: () => void }) => { return ( - +
) } const getResourceName = (type: string) => { - if (type === "aws_sqs_queue") { - return "SQS"; - } - return type; -} - -const getIconName = (type: string) => { switch (type) { case "aws_sqs_queue": - return "aws_sqs.svg"; + return "SQS"; case "aws_s3_bucket": - return "aws_s3.svg"; + return "S3"; + case "aws_s3_object": + return "S3 Object"; case "aws_lambda_function": - return "aws_lambda.svg"; + return "Lambda"; + case "aws_iam_role": + return "IAM Role"; + case "aws_iam_role_policy": + return "IAM Policy"; default: - return null; + return type.split("_").slice(1).join(" ").toUpperCase(); } } - const ResourceIcon = ({type}: {type: string}) => { - const iconName = getIconName(type); - if (!iconName) { + const validType = [ + "aws_sqs_queue", + "aws_s3_bucket", + "aws_s3_object", + "aws_lambda_function", + "aws_iam_role", + "aws_iam_role_policy", + ].includes(type); + if (!validType) { return null; } - return + return } export type Resource = { @@ -82,36 +89,7 @@ export type Resource = { contents: string; } -const ResourceRow = ({resource, selected, onClick}: { - resource: Resource, - selected: boolean, - onClick: () => void -}) => { - return ( - - ) -} - -const extractAwsResources = (tfFile: string) => { +const getAwsResources = (tfFile: string) => { try { const json = JSON.parse(tfFile); console.log(json); @@ -139,10 +117,18 @@ export interface TfAwsTargetProps { } export const TfAwsTarget = ({ files }: TfAwsTargetProps) => { - const compileEditorRef = useRef(); const [selectedFile, setSelectedFile] = useState(files?.[0]); - const [resources, setResources] = useState([]); + + const resources = useMemo(() => { + if (!files) { + return []; + } + const newResources = getAwsResources( + files?.find((f) => f.name === "main.tf.json")?.contents || "" + ); + return newResources; + }, [files]); const options: monaco.editor.IStandaloneEditorConstructionOptions = { minimap: { enabled: false }, @@ -152,43 +138,46 @@ export const TfAwsTarget = ({ files }: TfAwsTargetProps) => { compileEditorRef.current = editor } - useEffect(() => { - const filename = "main.tf.json"; - const newResources = extractAwsResources( - files?.find((f) => f.name === filename)?.contents || "" - ); - console.log(newResources); - setResources(newResources); - }, [files]); - return ( -
-
-
+
+
+
Terraform
-
+
+ {resources?.length === 0 && ( +
+ No resources found +
+ )} {resources?.map((resource) => { return ( - setSelectedFile(resource)} - /> - ) - })} + } + selected={selectedFile?.name === resource.name} + onClick={() => setSelectedFile(resource)} + /> + ) + })}
-
-
+ +
Assets
-
+ +
+ {files?.length === 0 && ( +
+ No assets found +
+ )} {files?.map((file) => { return ( - setSelectedFile(file)} /> @@ -197,8 +186,7 @@ export const TfAwsTarget = ({ files }: TfAwsTargetProps) => {
-
- +
Date: Tue, 23 May 2023 13:41:15 +0200 Subject: [PATCH 09/52] wip --- apps/tour/public/aws/{aws_lambda.svg => aws_lambda_function.svg} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/tour/public/aws/{aws_lambda.svg => aws_lambda_function.svg} (100%) diff --git a/apps/tour/public/aws/aws_lambda.svg b/apps/tour/public/aws/aws_lambda_function.svg similarity index 100% rename from apps/tour/public/aws/aws_lambda.svg rename to apps/tour/public/aws/aws_lambda_function.svg From c342c8e0c97e273b8e42d8d4dc20f4bcf2c61127 Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 14:11:04 +0200 Subject: [PATCH 10/52] wip --- apps/tour/src/TfAwsTarget.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index b4830137..d78cd5a9 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -30,17 +30,20 @@ const FileRow = ({title, description, icon, selected, onClick}: { @@ -92,7 +95,6 @@ export type Resource = { const getAwsResources = (tfFile: string) => { try { const json = JSON.parse(tfFile); - console.log(json); if (!json.resource) { return []; } @@ -153,6 +155,7 @@ export const TfAwsTarget = ({ files }: TfAwsTargetProps) => { {resources?.map((resource) => { return ( } From b98e36158db7704784f84f1b10a6b8cae3d14a27 Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 15:15:25 +0200 Subject: [PATCH 11/52] wip --- .../aws/aws_iam_role_policy_attachment.svg | 3 + apps/tour/src/Editor.tsx | 12 +- apps/tour/src/TfAwsTarget.tsx | 122 ++++++++++-------- packages/shared/src/editor/use-editor.tsx | 26 ++-- 4 files changed, 90 insertions(+), 73 deletions(-) create mode 100644 apps/tour/public/aws/aws_iam_role_policy_attachment.svg diff --git a/apps/tour/public/aws/aws_iam_role_policy_attachment.svg b/apps/tour/public/aws/aws_iam_role_policy_attachment.svg new file mode 100644 index 00000000..11c091ba --- /dev/null +++ b/apps/tour/public/aws/aws_iam_role_policy_attachment.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index b9314697..a7cc357a 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -99,7 +99,7 @@ export const ReactMonacoEditor: React.FC = ({ const [targets, setTargets] = useState(tutorials[0].targets); - const {evaluateCode, editorWillMount, editorDidMount, targetsOutput } = useEditor({ + const {evaluateCode, editorWillMount, editorDidMount, compilerOutput, isCompiling } = useEditor({ editorRef, onLoadingStatusChange: setLoadingStatus, onLspError, @@ -221,12 +221,12 @@ export const ReactMonacoEditor: React.FC = ({ views.push(simulatorTarget); } if (target.includes("tf-")) { - const files = targetsOutput.find(t => t.target === target)?.files ?? []; + const files = compilerOutput.find(t => t.target === target)?.files ?? []; if (target === Target.TFAWS) { views.push({ title: "Terraform AWS", - Target: () => + Target: () => }); } else { @@ -238,7 +238,7 @@ export const ReactMonacoEditor: React.FC = ({ } }); return views; - }, [targets, targetsOutput]); + }, [targets, compilerOutput, isCompiling, simulatorTarget]); const [currentTarget, setCurrentTarget] = useState(simulatorTarget); @@ -261,8 +261,8 @@ export const ReactMonacoEditor: React.FC = ({
- {/* setShowWelcomeModal(false)}/> - setShowFinishModal(false)}/> */} + setShowWelcomeModal(false)}/> + setShowFinishModal(false)}/>
diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index d78cd5a9..5d192b0a 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -16,6 +16,7 @@ import 'monaco-editor/esm/vs/editor/standalone/browser/toggleHighContrast/toggle import * as monaco from 'monaco-editor'; import classNames from "classnames"; import { CompilationItem } from "@wing-playground/shared/src/compiler/compiler"; +import { Loading } from "@wing-playground/shared/src/Loading"; const FileRow = ({title, description, icon, selected, onClick}: { @@ -32,7 +33,7 @@ const FileRow = ({title, description, icon, selected, onClick}: { "flex items-center w-full px-2 py-1", "text-left text-sm font-medium leading-5", "text-gray-900", - "hover:bg-gray-300 focus:bg-gray-300", + "hover:bg-gray-300 focus:bg-gray-300 focus:outline-none", selected && "bg-gray-200", )} onClick={onClick} @@ -79,6 +80,7 @@ const ResourceIcon = ({type}: {type: string}) => { "aws_lambda_function", "aws_iam_role", "aws_iam_role_policy", + "aws_iam_role_policy_attachment", ].includes(type); if (!validType) { return null; @@ -116,9 +118,10 @@ const getAwsResources = (tfFile: string) => { export interface TfAwsTargetProps { files?: CompilationItem[]; + loading?: boolean; } -export const TfAwsTarget = ({ files }: TfAwsTargetProps) => { +export const TfAwsTarget = ({ files, loading }: TfAwsTargetProps) => { const compileEditorRef = useRef(); const [selectedFile, setSelectedFile] = useState(files?.[0]); @@ -141,65 +144,70 @@ export const TfAwsTarget = ({ files }: TfAwsTargetProps) => { } return ( -
-
-
-
Terraform
-
-
- {resources?.length === 0 && ( -
- No resources found -
- )} - {resources?.map((resource) => { - return ( - } - selected={selectedFile?.name === resource.name} - onClick={() => setSelectedFile(resource)} - /> - ) - })} -
+
+ {loading && ( +
+ +
+ )} -
-
Assets
+
+
+
Terraform
+
+
+ {resources?.length === 0 && !loading && ( +
+ No resources found
+ )} + {resources?.map((resource) => { + return ( + } + selected={selectedFile?.name === resource.name} + onClick={() => setSelectedFile(resource)} + /> + ) + })} +
+ +
+
Assets
+
-
- {files?.length === 0 && ( -
- No assets found -
- )} - {files?.map((file) => { - return ( - setSelectedFile(file)} - /> - ) - })} +
+ {files?.length === 0 && !loading && ( +
+ No assets found
-
- -
- -
+ )} + {files?.map((file) => { + return ( + setSelectedFile(file)} + /> + ) + })} +
+
+
+
+
) } diff --git a/packages/shared/src/editor/use-editor.tsx b/packages/shared/src/editor/use-editor.tsx index 89742f0a..6b79a93c 100644 --- a/packages/shared/src/editor/use-editor.tsx +++ b/packages/shared/src/editor/use-editor.tsx @@ -22,14 +22,14 @@ export interface UseEditorOptions { code: string; languageContext: LanguageContext; compiler: Compiler; - targets: Target[]; + targets?: Target[]; editorOptions: monaco.editor.IStandaloneEditorConstructionOptions; installConsole?: (containerRef: React.MutableRefObject) => Promise; editorTheme?: string; shouldInitContainer: boolean; } -export type TargetOutput = { +export type CompilerOutput = { target: Target, files: CompilationItem[] } @@ -41,7 +41,8 @@ export const useEditor = ({editorRef, onLoadingStatusChange, onLspError, code, l const [isCompiling, setIsCompiling] = useState(false); const containerRef = useRef(); const monacoRef = useRef(); - const [targetsOutput, setTargetsOutput] = useState([]); + + const [compilerOutput, setCompilerOutput] = useState([]); const editorWillMount = (monaco: any) => { @@ -102,18 +103,23 @@ export const useEditor = ({editorRef, onLoadingStatusChange, onLspError, code, l let compileValue = editorRef.current?.getValue() await prepareForEvaluation(containerRef.current, compileValue, languageContext.file) - setTargetsOutput([]); - targets.forEach(async target => { + setCompilerOutput([]); + targets?.forEach(async (target, index) => { const compilation = await compiler.compile(new CompilationRequest(compileValue!, target)); const output = { target, files: compilation.files } - setTargetsOutput(prev => [...prev, output]); + setCompilerOutput(prev => [...prev, output]); + if (index === targets.length - 1) { + onLoadingStatusChange(LoadingStatus.Completed) + setIsCompiling(false) + } }); - } finally { - onLoadingStatusChange(LoadingStatus.Completed) - setIsCompiling(false) + } catch (error) { + console.error(error); + onLoadingStatusChange(LoadingStatus.CompileError) + setIsCompiling(false) } }, 700); @@ -122,6 +128,6 @@ export const useEditor = ({editorRef, onLoadingStatusChange, onLspError, code, l editorDidMount, evaluateCode, isCompiling, - targetsOutput, + compilerOutput, } } From 7f61c5f89c746e3ad1bf38bfb06a138f7be8d778 Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 15:42:34 +0200 Subject: [PATCH 12/52] wip --- apps/tour/src/Editor.tsx | 7 ++-- apps/tour/src/TargetsView.tsx | 66 +++++++++++++++++------------------ apps/tour/src/TfAwsTarget.tsx | 6 +++- 3 files changed, 42 insertions(+), 37 deletions(-) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index a7cc357a..28885e1d 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -183,6 +183,7 @@ export const ReactMonacoEditor: React.FC = ({ step: currentStep }) setTargets(currentStep.targets); + setCurrentTargetId(targetViews[0]?.title); }, [currentStep]); const downloadCompiledCode = async (target: Target) => { @@ -240,7 +241,7 @@ export const ReactMonacoEditor: React.FC = ({ return views; }, [targets, compilerOutput, isCompiling, simulatorTarget]); - const [currentTarget, setCurrentTarget] = useState(simulatorTarget); + const [currentTargetId, setCurrentTargetId] = useState(targetViews[0]?.title); return ( <> @@ -343,8 +344,8 @@ export const ReactMonacoEditor: React.FC = ({ {loadingStatus == LoadingStatus.Completed && ( )}
diff --git a/apps/tour/src/TargetsView.tsx b/apps/tour/src/TargetsView.tsx index 4329d2ad..ababa823 100644 --- a/apps/tour/src/TargetsView.tsx +++ b/apps/tour/src/TargetsView.tsx @@ -1,46 +1,46 @@ -import React, { useMemo } from "react"; +import {FC, useEffect, useMemo, useState } from "react"; import { Tab, Tabs } from "@wing-playground/shared/src/Tabs"; import classNames from "classnames"; export interface TargetView { title: string; - Target: React.FC; + Target: FC; } export interface TargetsViewProps { targets: TargetView[]; - currentTarget?: TargetView; - setCurrentTarget?: (target: TargetView) => void; + currentTargetId?: string; + setCurrentTargetId?: (targetId: string) => void; } -export const TargetsView = ({targets, setCurrentTarget, currentTarget}: TargetsViewProps) => { +export const TargetsView = ({targets, setCurrentTargetId, currentTargetId}: TargetsViewProps) => { - const tabs = useMemo(() => { - const tabs: Tab[] = []; - targets.forEach((target) => { - tabs.push({ - id: target.title, - name: target.title, - panel: , - }); + const tabs = useMemo(() => { + const tabs: Tab[] = []; + targets.forEach((target) => { + tabs.push({ + id: target.title, + name: target.title, + panel: , }); - return tabs; - }, [targets]); + }); + return tabs; + }, [targets]); - return ( - { - const target = targets.find((target) => target.title === tabId); - if (!target || !setCurrentTarget) { - return; - } - setCurrentTarget(target); - }} - /> - ); + return ( + { + const target = targets.find((target) => target.title === tabId); + if (!target || !setCurrentTargetId) { + return; + } + setCurrentTargetId(target.title); + }} + /> + ); } diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index 5d192b0a..35b27f49 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -42,7 +42,7 @@ const FileRow = ({title, description, icon, selected, onClick}: { {icon &&
{icon}
} -
+
{title}
{description &&
{description}
}
@@ -143,6 +143,10 @@ export const TfAwsTarget = ({ files, loading }: TfAwsTargetProps) => { compileEditorRef.current = editor } + useEffect(() => { + setSelectedFile(resources?.[0] || files?.[0]); + }, [files, resources]); + return (
{loading && ( From b6a99e2c5da681ad15dc53891c8c58ec5efe3834 Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 15:56:04 +0200 Subject: [PATCH 13/52] wip --- apps/tour/src/TfAwsTarget.tsx | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index 35b27f49..23330701 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -89,6 +89,7 @@ const ResourceIcon = ({type}: {type: string}) => { } export type Resource = { + path: string; name: string; type: string; contents: string; @@ -103,12 +104,16 @@ const getAwsResources = (tfFile: string) => { const resources: Resource[] = []; for (const [key, value] of Object.entries(json.resource)) { - const resourceId = Object.keys(value as object)[0]; - resources.push({ - name: resourceId, - type: key, - contents: JSON.stringify(value, null, 2) - }); + for (const [key2, value2] of Object.entries(value as object)) { + const path = value2["//"]["metadata"]["path"] || key2; + const resourceName = path.split("/").slice(-2, -1)[0]; + resources.push({ + path: path, + name: resourceName, + type: key, + contents: JSON.stringify(value2, null, 2) + }); + } } return resources; } catch (e) { @@ -172,8 +177,11 @@ export const TfAwsTarget = ({ files, loading }: TfAwsTargetProps) => { title={getResourceName(resource.type)} description={resource.name} icon={} - selected={selectedFile?.name === resource.name} - onClick={() => setSelectedFile(resource)} + selected={selectedFile?.name === resource.path} + onClick={() => setSelectedFile({ + name: resource.path, + contents: resource.contents, + })} /> ) })} @@ -200,6 +208,11 @@ export const TfAwsTarget = ({ files, loading }: TfAwsTargetProps) => { ) })}
+ +
+
Download
+
+
Date: Tue, 23 May 2023 15:56:15 +0200 Subject: [PATCH 14/52] wip --- apps/tour/src/TfAwsTarget.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index 23330701..17db0553 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -173,7 +173,7 @@ export const TfAwsTarget = ({ files, loading }: TfAwsTargetProps) => { {resources?.map((resource) => { return ( } From a25ce6fd84a0a93d2ce42732bb5e8bc75b0881f6 Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 16:16:45 +0200 Subject: [PATCH 15/52] wip --- apps/tour/src/Editor.tsx | 21 +-- apps/tour/src/TfAwsTarget.tsx | 158 +++++++++++++--------- packages/shared/src/editor/use-editor.tsx | 8 +- 3 files changed, 109 insertions(+), 78 deletions(-) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index 28885e1d..cca64fcc 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -222,16 +222,17 @@ export const ReactMonacoEditor: React.FC = ({ views.push(simulatorTarget); } if (target.includes("tf-")) { - const files = compilerOutput.find(t => t.target === target)?.files ?? []; - - if (target === Target.TFAWS) { - views.push({ - title: "Terraform AWS", - Target: () => - }); - } - else { - views.push({ + const compilation = compilerOutput.find(t => t.target === target); + const files = compilation?.files; + + if (target === Target.TFAWS) { + views.push({ + title: "Terraform AWS", + Target: () => + }); + } + else { + views.push({ title: target, Target: () => }) diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index 17db0553..1b03aab3 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -17,6 +17,8 @@ import * as monaco from 'monaco-editor'; import classNames from "classnames"; import { CompilationItem } from "@wing-playground/shared/src/compiler/compiler"; import { Loading } from "@wing-playground/shared/src/Loading"; +import { ArrowDownTrayIcon } from "@heroicons/react/24/solid"; +import AdmZip from "adm-zip"; const FileRow = ({title, description, icon, selected, onClick}: { @@ -53,7 +55,6 @@ const FileRow = ({title, description, icon, selected, onClick}: { } const getResourceName = (type: string) => { - switch (type) { case "aws_sqs_queue": return "SQS"; @@ -121,12 +122,27 @@ const getAwsResources = (tfFile: string) => { } } +const downloadZip = (zip?: AdmZip) => { + if (!zip) { + return; + } + const zipBlob = new Blob([new Uint8Array(zip.toBuffer())]); + const url = window.URL.createObjectURL(zipBlob); + const zipDownload = document.createElement("a"); + + zipDownload.href = url; + zipDownload.download = "wing.zip"; + document.body.appendChild(zipDownload); + zipDownload.click(); +} + export interface TfAwsTargetProps { files?: CompilationItem[]; + zip?: AdmZip; loading?: boolean; } -export const TfAwsTarget = ({ files, loading }: TfAwsTargetProps) => { +export const TfAwsTarget = ({ files, zip, loading }: TfAwsTargetProps) => { const compileEditorRef = useRef(); const [selectedFile, setSelectedFile] = useState(files?.[0]); @@ -153,77 +169,89 @@ export const TfAwsTarget = ({ files, loading }: TfAwsTargetProps) => { }, [files, resources]); return ( -
- {loading && ( -
- -
- )} +
+
+ {loading && ( +
+ +
+ )} -
-
-
Terraform
-
-
- {resources?.length === 0 && !loading && ( -
- No resources found +
+
+
+
+ Terraform + ({resources?.length}) +
- )} - {resources?.map((resource) => { - return ( - } - selected={selectedFile?.name === resource.path} - onClick={() => setSelectedFile({ - name: resource.path, - contents: resource.contents, - })} - /> - ) - })} -
- -
-
Assets
-
- -
- {files?.length === 0 && !loading && ( -
- No assets found -
- )} - {files?.map((file) => { - return ( +
+
+ {resources?.length === 0 && !loading && ( +
+ No resources found +
+ )} + {resources?.map((resource) => { + return ( setSelectedFile(file)} + key={resource.path} + title={getResourceName(resource.type)} + description={resource.name} + icon={} + selected={selectedFile?.name === resource.path} + onClick={() => setSelectedFile({ + name: resource.path, + contents: resource.contents, + })} /> ) })} -
+
-
-
Download
-
+
+
+
+ Assets + ({files?.length}) +
+
+ +
+
+
-
-
- +
+ {files?.length === 0 && !loading && ( +
+ No assets found +
+ )} + {files?.map((file) => { + return ( + setSelectedFile(file)} + /> + ) + })} +
+
+
+ +
) diff --git a/packages/shared/src/editor/use-editor.tsx b/packages/shared/src/editor/use-editor.tsx index 6b79a93c..565ffd0e 100644 --- a/packages/shared/src/editor/use-editor.tsx +++ b/packages/shared/src/editor/use-editor.tsx @@ -13,7 +13,7 @@ import {CompilationRequest} from "../compiler/request"; import {CompilationItem, Compiler, Target} from "../compiler/compiler"; import React, {useRef, useState} from "react"; import * as monaco from 'monaco-editor'; - +import AdmZip from "adm-zip"; export interface UseEditorOptions { editorRef: React.MutableRefObject; @@ -31,7 +31,8 @@ export interface UseEditorOptions { export type CompilerOutput = { target: Target, - files: CompilationItem[] + files: CompilationItem[], + zip: AdmZip, } const darkPlusTheme = convertTheme(darkPlusTMTheme); @@ -108,7 +109,8 @@ export const useEditor = ({editorRef, onLoadingStatusChange, onLspError, code, l const compilation = await compiler.compile(new CompilationRequest(compileValue!, target)); const output = { target, - files: compilation.files + files: compilation.files, + zip: compilation.zip } setCompilerOutput(prev => [...prev, output]); if (index === targets.length - 1) { From 03b88368f2a36a20f8ffca777e0488d1c1a10f6d Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 16:19:13 +0200 Subject: [PATCH 16/52] wip --- apps/tour/src/TfAwsTarget.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index 1b03aab3..4fa250e0 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -182,7 +182,7 @@ export const TfAwsTarget = ({ files, zip, loading }: TfAwsTargetProps) => {
Terraform - ({resources?.length}) + {resources?.length && ({resources?.length})}
@@ -213,7 +213,7 @@ export const TfAwsTarget = ({ files, zip, loading }: TfAwsTargetProps) => {
Assets - ({files?.length}) + {files?.length && ({files?.length})}
- {files?.length === 0 && !loading && ( + {files?.length === 0 && !loading && (
No assets found
From 2a6b5186b6eb4a51000ce429e9ef9e859c3302ba Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 16:19:33 +0200 Subject: [PATCH 17/52] wip --- apps/tour/src/TfAwsTarget.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index 4fa250e0..ddd15067 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -186,7 +186,7 @@ export const TfAwsTarget = ({ files, zip, loading }: TfAwsTargetProps) => {
-
+
{resources?.length === 0 && !loading && (
No resources found @@ -223,7 +223,7 @@ export const TfAwsTarget = ({ files, zip, loading }: TfAwsTargetProps) => {
-
+
{files?.length === 0 && !loading && (
No assets found From 78a32f82cf896e6a35f5d5356219ccdfab98d89d Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 16:28:46 +0200 Subject: [PATCH 18/52] wip --- apps/tour/src/Editor.tsx | 4 ++++ apps/tour/src/TargetsView.tsx | 8 ++++++++ apps/tour/src/TfAwsTarget.tsx | 5 +++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index cca64fcc..27bcb46a 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -242,6 +242,10 @@ export const ReactMonacoEditor: React.FC = ({ return views; }, [targets, compilerOutput, isCompiling, simulatorTarget]); + useEffect(() => { + setCurrentTargetId(targetViews[0]?.title); + }, [targetViews.length]); + const [currentTargetId, setCurrentTargetId] = useState(targetViews[0]?.title); return ( diff --git a/apps/tour/src/TargetsView.tsx b/apps/tour/src/TargetsView.tsx index ababa823..1773fe15 100644 --- a/apps/tour/src/TargetsView.tsx +++ b/apps/tour/src/TargetsView.tsx @@ -25,6 +25,14 @@ export const TargetsView = ({targets, setCurrentTargetId, currentTargetId}: Targ return tabs; }, [targets]); + useEffect(() => { + if (targets.find((target) => target.title === currentTargetId)) { + return; + } + setCurrentTargetId?.(targets[0].title); + console.log("SET NEW TAB", targets[0].title); + }, [currentTargetId, targets, setCurrentTargetId]); + return ( { setSelectedFile(resources?.[0] || files?.[0]); }, [files, resources]); + return (
@@ -182,7 +183,7 @@ export const TfAwsTarget = ({ files, zip, loading }: TfAwsTargetProps) => {
Terraform - {resources?.length && ({resources?.length})} + ({resources.length || 0})
@@ -213,7 +214,7 @@ export const TfAwsTarget = ({ files, zip, loading }: TfAwsTargetProps) => {
Assets - {files?.length && ({files?.length})} + ({files?.length || 0})
- ) -} - - -export const TerraformTarget = ({ files }: TerraformTargetProps) => { - - const compileEditorRef = useRef(); - const [selectedFile, setSelectedFile] = useState(); - - const options: monaco.editor.IStandaloneEditorConstructionOptions = { - minimap: { enabled: false }, - }; - - -const compileEditorDidMount = async (editor: any, monaco: any) => { - compileEditorRef.current = editor -} - useEffect(() => { - if (!files) { - return; - } - setSelectedFile(files[0]); - }, [files]); - - return ( -
-
-
-
Terraform
-
-
- {files?.map((file) => { - if (file.name.endsWith(".js")) { - return null; - } - return ( - setSelectedFile(file)} - /> - ) - })} -
-
-
-
Assets
-
-
- {files?.map((asset) => { - if (!asset.name.endsWith(".js")) { - return null; - } - return ( - setSelectedFile(asset)} - /> - ) - })} -
-
- -
- - -
-
- ) -} diff --git a/apps/tour/src/tutorials/index.ts b/apps/tour/src/tutorials/index.ts index f6d2ff36..41e919b3 100644 --- a/apps/tour/src/tutorials/index.ts +++ b/apps/tour/src/tutorials/index.ts @@ -39,7 +39,7 @@ export const tutorials = [ code: code01, solution: solution01, tutorial: tutorial01, - targets: [Target.SIMULATOR, Target.TFAWS, Target.TFGCP], + targets: [Target.SIMULATOR, Target.TFAWS], }, { id: "2", From cab0c01572afed3ce3721921c520f18e7265e6b8 Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 16:37:27 +0200 Subject: [PATCH 20/52] wip --- apps/tour/src/Editor.tsx | 15 --------------- apps/tour/src/TfAwsTarget.tsx | 5 ++++- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index ad28df12..ab67d537 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -1,18 +1,3 @@ - -import 'monaco-editor/esm/vs/editor/editor.all.js'; - -// support all editor features -import 'monaco-editor/esm/vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/inspectTokens/inspectTokens.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneHelpQuickAccess.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneGotoLineQuickAccess.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneGotoSymbolQuickAccess.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneCommandsQuickAccess.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/quickInput/standaloneQuickInputService.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/referenceSearch/standaloneReferenceSearch.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast.js'; - import * as monaco from 'monaco-editor'; import { buildWorkerDefinition } from 'monaco-editor-workers'; diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index c3f88a12..85263504 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -165,7 +165,10 @@ export const TfAwsTarget = ({ files, zip, loading }: TfAwsTargetProps) => { } useEffect(() => { - setSelectedFile(resources?.[0] || files?.[0]); + setSelectedFile({ + name: resources[0].path || files?.[0].name || "", + contents: resources[0].contents || files?.[0].contents || "", + }); }, [files, resources]); From 88ba0ed020afd134da0db5ad89c685bc9cad5ff3 Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 16:38:13 +0200 Subject: [PATCH 21/52] wip --- apps/tour/src/TfAwsTarget.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index 85263504..7701f44a 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -166,8 +166,8 @@ export const TfAwsTarget = ({ files, zip, loading }: TfAwsTargetProps) => { useEffect(() => { setSelectedFile({ - name: resources[0].path || files?.[0].name || "", - contents: resources[0].contents || files?.[0].contents || "", + name: resources[0]?.path || files?.[0].name || "", + contents: resources[0]?.contents || files?.[0].contents || "", }); }, [files, resources]); From f50a46f137a230c30f3cd6126081b745660e9318 Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 16:39:47 +0200 Subject: [PATCH 22/52] wip --- apps/tour/src/Editor.tsx | 15 +++++++++++++++ apps/tour/src/TfAwsTarget.tsx | 22 ++++++++++++---------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index ab67d537..ad28df12 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -1,3 +1,18 @@ + +import 'monaco-editor/esm/vs/editor/editor.all.js'; + +// support all editor features +import 'monaco-editor/esm/vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/inspectTokens/inspectTokens.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneHelpQuickAccess.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneGotoLineQuickAccess.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneGotoSymbolQuickAccess.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneCommandsQuickAccess.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/quickInput/standaloneQuickInputService.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/referenceSearch/standaloneReferenceSearch.js'; +import 'monaco-editor/esm/vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast.js'; + import * as monaco from 'monaco-editor'; import { buildWorkerDefinition } from 'monaco-editor-workers'; diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index 7701f44a..d65404b9 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -1,17 +1,19 @@ import {useEffect, useMemo, useRef, useState} from "react"; import Editor from "@monaco-editor/react"; +import "monaco-editor/esm/vs/editor/editor.all.js"; + // support all editor features -import 'monaco-editor/esm/vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/inspectTokens/inspectTokens.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneHelpQuickAccess.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneGotoLineQuickAccess.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneGotoSymbolQuickAccess.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneCommandsQuickAccess.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/quickInput/standaloneQuickInputService.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/referenceSearch/standaloneReferenceSearch.js'; -import 'monaco-editor/esm/vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast.js'; +import "monaco-editor/esm/vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp.js"; +import "monaco-editor/esm/vs/editor/standalone/browser/inspectTokens/inspectTokens.js"; +import "monaco-editor/esm/vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard.js"; +import "monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneHelpQuickAccess.js"; +import "monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneGotoLineQuickAccess.js"; +import "monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneGotoSymbolQuickAccess.js"; +import "monaco-editor/esm/vs/editor/standalone/browser/quickAccess/standaloneCommandsQuickAccess.js"; +import "monaco-editor/esm/vs/editor/standalone/browser/quickInput/standaloneQuickInputService.js"; +import "monaco-editor/esm/vs/editor/standalone/browser/referenceSearch/standaloneReferenceSearch.js"; +import "monaco-editor/esm/vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast.js"; import * as monaco from 'monaco-editor'; import classNames from "classnames"; From b886e2ec20e0aefd86451d8a83503a2ed424ca66 Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 16:41:21 +0200 Subject: [PATCH 23/52] wip --- packages/shared/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json index 07561f9a..3d0a51a8 100644 --- a/packages/shared/tsconfig.json +++ b/packages/shared/tsconfig.json @@ -16,6 +16,6 @@ "noEmit": true, "jsx": "react-jsx" }, - "include": ["src", "../../apps/tour/src/TerraformTarget.tsx"], + "include": ["src"], "references": [{ "path": "./tsconfig.node.json" }] } From 7dc9ae58b6a6c3178d53f4fad8589034c91303e8 Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 16:43:34 +0200 Subject: [PATCH 24/52] wip --- apps/tour/src/Editor.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index ad28df12..116abb25 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -224,7 +224,7 @@ export const ReactMonacoEditor: React.FC = ({ const compilation = compilerOutput.find(t => t.target === target); const files = compilation?.files; views.push({ - title: "Terraform AWS", + title: "AWS/TERRAFORM", Target: () => }); } From e984dd36bd418aff62b3ca4a6031d1251262ebfd Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 18:26:38 +0200 Subject: [PATCH 25/52] wip --- apps/tour/src/Editor.tsx | 11 +++++------ apps/tour/src/TfAwsTarget.tsx | 23 ++++------------------- apps/tour/src/tutorials/index.ts | 2 +- packages/shared/src/editor/use-editor.tsx | 3 --- 4 files changed, 10 insertions(+), 29 deletions(-) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index 116abb25..3d308113 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -225,7 +225,11 @@ export const ReactMonacoEditor: React.FC = ({ const files = compilation?.files; views.push({ title: "AWS/TERRAFORM", - Target: () => + Target: () => downloadCompiledCode(target)} + /> }); } }); @@ -286,11 +290,6 @@ export const ReactMonacoEditor: React.FC = ({ }
- {isLastStep && - - } {!isFirstStep &&
-
diff --git a/apps/tour/src/tutorials/index.ts b/apps/tour/src/tutorials/index.ts index 41e919b3..fa74b161 100644 --- a/apps/tour/src/tutorials/index.ts +++ b/apps/tour/src/tutorials/index.ts @@ -79,6 +79,6 @@ export const tutorials = [ code: code06, // solution: solution06, tutorial: tutorial06, - targets: [Target.TFAWS], + targets: [Target.SIMULATOR, Target.TFAWS], }, ] diff --git a/packages/shared/src/editor/use-editor.tsx b/packages/shared/src/editor/use-editor.tsx index 565ffd0e..545b330b 100644 --- a/packages/shared/src/editor/use-editor.tsx +++ b/packages/shared/src/editor/use-editor.tsx @@ -13,7 +13,6 @@ import {CompilationRequest} from "../compiler/request"; import {CompilationItem, Compiler, Target} from "../compiler/compiler"; import React, {useRef, useState} from "react"; import * as monaco from 'monaco-editor'; -import AdmZip from "adm-zip"; export interface UseEditorOptions { editorRef: React.MutableRefObject; @@ -32,7 +31,6 @@ export interface UseEditorOptions { export type CompilerOutput = { target: Target, files: CompilationItem[], - zip: AdmZip, } const darkPlusTheme = convertTheme(darkPlusTMTheme); @@ -110,7 +108,6 @@ export const useEditor = ({editorRef, onLoadingStatusChange, onLspError, code, l const output = { target, files: compilation.files, - zip: compilation.zip } setCompilerOutput(prev => [...prev, output]); if (index === targets.length - 1) { From d2691fce330694b348a92aa9664b90a1e39f5f36 Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 18:32:54 +0200 Subject: [PATCH 26/52] wip --- apps/tour/src/TfAwsTarget.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index 904bf1cf..2e22fd8f 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -160,7 +160,7 @@ export const TfAwsTarget = ({ files, downloadCompiledCode, loading, disabled }: return ( -
+
{loading && (
From fce5fee8f6e8d09c6be7b27ff4c60de89b148915 Mon Sep 17 00:00:00 2001 From: polamoros Date: Tue, 23 May 2023 18:50:32 +0200 Subject: [PATCH 27/52] wip --- apps/tour/src/TfAwsTarget.tsx | 120 ++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 58 deletions(-) diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index 2e22fd8f..f4f165bc 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -160,78 +160,82 @@ export const TfAwsTarget = ({ files, downloadCompiledCode, loading, disabled }: return ( -
-
+
+
{loading && (
)} -
-
-
-
- Terraform - ({resources.length || 0}) +
+
+
+
+
+ Terraform + ({resources.length || 0}) +
-
-
- {resources?.length === 0 && !loading && ( -
- No resources found -
- )} - {resources?.map((resource) => { - return ( - } - selected={selectedFile?.name === resource.path} - onClick={() => setSelectedFile({ - name: resource.path, - contents: resource.contents, - })} - /> - ) - })} -
- -
-
-
- Assets - ({files?.length || 0}) -
-
- -
-
-
- -
- {files?.length === 0 && !loading && ( -
- No assets found -
- )} - {files?.map((file) => { - return ( +
+ {resources?.length === 0 && !loading && ( +
+ No resources found +
+ )} + {resources?.map((resource) => { + return ( setSelectedFile(file)} + key={resource.path} + title={getResourceName(resource.type)} + description={resource.name} + icon={} + selected={selectedFile?.name === resource.path} + onClick={() => setSelectedFile({ + name: resource.path, + contents: resource.contents, + })} /> ) })} +
+
+ +
+
+
+
+ Assets + ({files?.length || 0}) +
+
+ +
+
+
+
+ {files?.length === 0 && !loading && ( +
+ No assets found +
+ )} + {files?.map((file) => { + return ( + setSelectedFile(file)} + /> + ) + })} +
+
Date: Wed, 24 May 2023 10:08:22 +0200 Subject: [PATCH 28/52] wip --- apps/tour/src/Editor.tsx | 120 +++++++++++++--------- apps/tour/src/TargetsView.tsx | 16 +-- apps/tour/src/TfAwsTarget.tsx | 4 +- apps/tour/src/tutorials/index.ts | 12 +-- packages/shared/src/compiler/compiler.ts | 1 - packages/shared/src/editor/use-editor.tsx | 36 ++++--- 6 files changed, 113 insertions(+), 76 deletions(-) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index 3d308113..bedb4999 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -25,7 +25,7 @@ import { WebContainer } from '@webcontainer/api'; import ReactMarkdown from 'react-markdown' import { Loading } from '@wing-playground/shared/src/Loading'; -import { Compiler, Target } from '@wing-playground/shared/src/compiler/compiler'; +import { Compiler, Target, CompilationItem } from '@wing-playground/shared/src/compiler/compiler'; import { CompilationRequest } from '@wing-playground/shared/src/compiler/request'; import { useExamples, Example } from '@wing-playground/shared/src/use-examples.js'; import { tutorials } from './tutorials/index.js'; @@ -96,9 +96,16 @@ export const ReactMonacoEditor: React.FC = ({ }); } - const [targets, setTargets] = useState(tutorials[0].targets); + const [outputTargets, setOutputTarget] = useState(tutorials[0].targets); + const targets: Target[] = useMemo(() => { + return outputTargets.filter(t => t !== "simulator") as Target[]; + }, [outputTargets]); - const {evaluateCode, editorWillMount, editorDidMount, compilerOutput, isCompiling } = useEditor({ + const { + evaluateCode, + editorWillMount, + editorDidMount, + } = useEditor({ editorRef, onLoadingStatusChange: setLoadingStatus, onLspError, @@ -111,6 +118,9 @@ export const ReactMonacoEditor: React.FC = ({ shouldInitContainer: true, }); + const [isCompiling, setIsCompiling] = useState(false); + const [compilationItems, setCompilationItems] = useState([]); + useEffect(() => { if (ref.current != null) { return () => { @@ -172,75 +182,91 @@ export const ReactMonacoEditor: React.FC = ({ }, [currentStep, steps]); useEffect(() => { - if (!currentStep) { - return; - } + if (!currentStep) { + return; + } - editorRef.current?.setValue(currentStep.code); + editorRef.current?.setValue(currentStep.code); - analytics.track(`tutorial: step: ${currentStepId}: changed`, { - step: currentStep - }) - setTargets(currentStep.targets); - setCurrentTargetId(targetViews[0]?.title); + analytics.track(`tutorial: step: ${currentStepId}: changed`, { + step: currentStep + }) + setOutputTarget(currentStep.targets); + setCurrentTargetId(targetViews[0]?.title); }, [currentStep]); const downloadCompiledCode = async (target: Target) => { - setDownloadInProgress(true); - const result = await compiler.compile(new CompilationRequest(editorRef.current?.getValue()!, target)); - if (result.error) { - console.error('compilation failed', result.error.stderr); - return; - } - console.log("download compile code", result); - const zipBlob = new Blob([new Uint8Array(result.zip.toBuffer())]); - const url = window.URL.createObjectURL(zipBlob); - const zipDownload = document.createElement("a"); - zipDownload.href = url; - zipDownload.download = "hello.tfaws.zip"; - document.body.appendChild(zipDownload); - zipDownload.click(); - setDownloadInProgress(false); + setDownloadInProgress(true); + const result = await compiler.compile(new CompilationRequest(editorRef.current?.getValue()!, target)); + if (result.error) { + console.error('compilation failed', result.error.stderr); + return; + } + console.log("download compile code", result); + const zipBlob = new Blob([new Uint8Array(result.zip.toBuffer())]); + const url = window.URL.createObjectURL(zipBlob); + const zipDownload = document.createElement("a"); + zipDownload.href = url; + zipDownload.download = "hello.tfaws.zip"; + document.body.appendChild(zipDownload); + zipDownload.click(); + setDownloadInProgress(false); }; const [showWelcomeModal, setShowWelcomeModal] = useState(true); const [showFinishModal, setShowFinishModal] = useState(false); const simulatorTarget: TargetView = useMemo(() => { - return { - title: "Wing Simulator", - Target: () => - } + return { + id: "simulator", + title: "Wing Simulator", + Target: () => + } }, [iframSrc, refIframe]); + const tfAwsTarget: TargetView = useMemo(() => { + return { + id: Target.TFAWS, + title: "AWS/TERRAFORM", + Target: () => downloadCompiledCode(Target.TFAWS)} + disabled={downloadInProgress} + /> + } + }, [isCompiling, downloadInProgress, downloadCompiledCode, compilationItems]); + const targetViews: TargetView[] = useMemo(() => { const views: TargetView[] = []; - - targets.forEach(target => { - if (target === Target.SIMULATOR) { + outputTargets.forEach(target => { + if (target === "simulator") { views.push(simulatorTarget); } if (target === Target.TFAWS) { - const compilation = compilerOutput.find(t => t.target === target); - const files = compilation?.files; - views.push({ - title: "AWS/TERRAFORM", - Target: () => downloadCompiledCode(target)} - /> - }); + views.push(tfAwsTarget); } }); return views; - }, [targets, compilerOutput, isCompiling, simulatorTarget]); + }, [outputTargets, simulatorTarget, tfAwsTarget]); + + const [currentTargetId, setCurrentTargetId] = useState(targetViews[0]?.id); useEffect(() => { - setCurrentTargetId(targetViews[0]?.title); + setCurrentTargetId(targetViews[0]?.id); }, [targetViews.length]); - const [currentTargetId, setCurrentTargetId] = useState(targetViews[0]?.title); + useEffect(() => { + setCompilationItems([]); + if (currentTargetId === tfAwsTarget.id) { + setIsCompiling(true); + const compilation = compiler.compile(new CompilationRequest(editorRef.current?.getValue()!, Target.TFAWS)); + compilation.then(result => { + setCompilationItems(result.files); + setIsCompiling(false); + }); + } + }, [currentTargetId, compiler, editorRef]); return ( <> diff --git a/apps/tour/src/TargetsView.tsx b/apps/tour/src/TargetsView.tsx index 1773fe15..7c0e8cc2 100644 --- a/apps/tour/src/TargetsView.tsx +++ b/apps/tour/src/TargetsView.tsx @@ -3,8 +3,9 @@ import { Tab, Tabs } from "@wing-playground/shared/src/Tabs"; import classNames from "classnames"; export interface TargetView { - title: string; - Target: FC; + id: string; + title: string; + Target: FC; } export interface TargetsViewProps { targets: TargetView[]; @@ -17,7 +18,7 @@ export const TargetsView = ({targets, setCurrentTargetId, currentTargetId}: Targ const tabs: Tab[] = []; targets.forEach((target) => { tabs.push({ - id: target.title, + id: target.id, name: target.title, panel: , }); @@ -26,11 +27,10 @@ export const TargetsView = ({targets, setCurrentTargetId, currentTargetId}: Targ }, [targets]); useEffect(() => { - if (targets.find((target) => target.title === currentTargetId)) { + if (targets.find((target) => target.id === currentTargetId)) { return; } - setCurrentTargetId?.(targets[0].title); - console.log("SET NEW TAB", targets[0].title); + setCurrentTargetId?.(targets[0].id); }, [currentTargetId, targets, setCurrentTargetId]); return ( @@ -43,11 +43,11 @@ export const TargetsView = ({targets, setCurrentTargetId, currentTargetId}: Targ tabs={tabs} currentTabId={currentTargetId} onTabChange={(tabId) => { - const target = targets.find((target) => target.title === tabId); + const target = targets.find((target) => target.id === tabId); if (!target || !setCurrentTargetId) { return; } - setCurrentTargetId(target.title); + setCurrentTargetId(target.id); }} /> ); diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index f4f165bc..25e84cd9 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -153,8 +153,8 @@ export const TfAwsTarget = ({ files, downloadCompiledCode, loading, disabled }: useEffect(() => { setSelectedFile({ - name: resources[0]?.path || files?.[0].name || "", - contents: resources[0]?.contents || files?.[0].contents || "", + name: resources[0]?.path || files?.[0]?.name || "", + contents: resources[0]?.contents || files?.[0]?.contents || "", }); }, [files, resources]); diff --git a/apps/tour/src/tutorials/index.ts b/apps/tour/src/tutorials/index.ts index fa74b161..ce33ef23 100644 --- a/apps/tour/src/tutorials/index.ts +++ b/apps/tour/src/tutorials/index.ts @@ -39,7 +39,7 @@ export const tutorials = [ code: code01, solution: solution01, tutorial: tutorial01, - targets: [Target.SIMULATOR, Target.TFAWS], + targets: ["simulator", Target.TFAWS], }, { id: "2", @@ -47,7 +47,7 @@ export const tutorials = [ code: code02, // solution: solution02, tutorial: tutorial02, - targets: [Target.SIMULATOR, Target.TFAWS], + targets: ["simulator", Target.TFAWS], }, { id: "3", @@ -55,7 +55,7 @@ export const tutorials = [ code: code03, solution: solution03, tutorial: tutorial03, - targets: [Target.SIMULATOR, Target.TFAWS], + targets: ["simulator", Target.TFAWS], }, { id: "4", @@ -63,7 +63,7 @@ export const tutorials = [ code: code04, solution: solution04, tutorial: tutorial04, - targets: [Target.SIMULATOR, Target.TFAWS], + targets: ["simulator", Target.TFAWS], }, { id: "5", @@ -71,7 +71,7 @@ export const tutorials = [ code: code05, solution: solution05, tutorial: tutorial05, - targets: [Target.SIMULATOR, Target.TFAWS], + targets: ["simulator", Target.TFAWS], }, { id: "6", @@ -79,6 +79,6 @@ export const tutorials = [ code: code06, // solution: solution06, tutorial: tutorial06, - targets: [Target.SIMULATOR, Target.TFAWS], + targets: ["simulator", Target.TFAWS], }, ] diff --git a/packages/shared/src/compiler/compiler.ts b/packages/shared/src/compiler/compiler.ts index d47fa94d..77d52efd 100644 --- a/packages/shared/src/compiler/compiler.ts +++ b/packages/shared/src/compiler/compiler.ts @@ -3,7 +3,6 @@ import { Base64Binary } from '../utils'; import { CompilationRequest } from './request'; export enum Target { - SIMULATOR = 'simulator', TFAWS = 'tf-aws', TFGCP = 'tf-gcp', TFAzure = 'tf-azure' diff --git a/packages/shared/src/editor/use-editor.tsx b/packages/shared/src/editor/use-editor.tsx index 545b330b..56ffa638 100644 --- a/packages/shared/src/editor/use-editor.tsx +++ b/packages/shared/src/editor/use-editor.tsx @@ -11,11 +11,11 @@ import {LanguageContext} from "../use-examples"; import {debounce} from "lodash"; import {CompilationRequest} from "../compiler/request"; import {CompilationItem, Compiler, Target} from "../compiler/compiler"; -import React, {useRef, useState} from "react"; +import {useRef, useState, MutableRefObject, useEffect} from "react"; import * as monaco from 'monaco-editor'; export interface UseEditorOptions { - editorRef: React.MutableRefObject; + editorRef: MutableRefObject; onLoadingStatusChange: (state: LoadingStatus) => void; onLspError: () => void; code: string; @@ -23,7 +23,7 @@ export interface UseEditorOptions { compiler: Compiler; targets?: Target[]; editorOptions: monaco.editor.IStandaloneEditorConstructionOptions; - installConsole?: (containerRef: React.MutableRefObject) => Promise; + installConsole?: (containerRef: MutableRefObject) => Promise; editorTheme?: string; shouldInitContainer: boolean; } @@ -35,7 +35,18 @@ export type CompilerOutput = { const darkPlusTheme = convertTheme(darkPlusTMTheme); -export const useEditor = ({editorRef, onLoadingStatusChange, onLspError, code, languageContext, compiler, targets, installConsole, editorTheme, shouldInitContainer}: UseEditorOptions) => { +export const useEditor = ({ + editorRef, + onLoadingStatusChange, + onLspError, + code, + languageContext, + compiler, + targets, + installConsole, + editorTheme, + shouldInitContainer +}: UseEditorOptions) => { const [isCompiling, setIsCompiling] = useState(false); const containerRef = useRef(); @@ -102,14 +113,15 @@ export const useEditor = ({editorRef, onLoadingStatusChange, onLspError, code, l let compileValue = editorRef.current?.getValue() await prepareForEvaluation(containerRef.current, compileValue, languageContext.file) - setCompilerOutput([]); + //setCompilerOutput([]); targets?.forEach(async (target, index) => { - const compilation = await compiler.compile(new CompilationRequest(compileValue!, target)); - const output = { - target, - files: compilation.files, - } - setCompilerOutput(prev => [...prev, output]); + compiler.submit(new CompilationRequest(compileValue!, target)); + //const compilation = await compiler.compile(new CompilationRequest(compileValue!, target)); + // const output = { + // target, + // files: compilation.files, + // } + //setCompilerOutput(prev => [...prev, output]); if (index === targets.length - 1) { onLoadingStatusChange(LoadingStatus.Completed) setIsCompiling(false) @@ -127,6 +139,6 @@ export const useEditor = ({editorRef, onLoadingStatusChange, onLspError, code, l editorDidMount, evaluateCode, isCompiling, - compilerOutput, + compilerOutput } } From c2a9c0f330d9ff89b6e9eb18152198f973a7a30f Mon Sep 17 00:00:00 2001 From: polamoros Date: Wed, 24 May 2023 10:42:54 +0200 Subject: [PATCH 29/52] wip --- apps/tour/src/Editor.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index bedb4999..c5f325a2 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -266,7 +266,7 @@ export const ReactMonacoEditor: React.FC = ({ setIsCompiling(false); }); } - }, [currentTargetId, compiler, editorRef]); + }, [currentTargetId, compiler, editorRef.current?.getValue()]); return ( <> From edbf3ed87a737288cd2421badba69f8a54a73fec Mon Sep 17 00:00:00 2001 From: polamoros Date: Wed, 24 May 2023 10:44:00 +0200 Subject: [PATCH 30/52] wip --- packages/shared/src/editor/use-editor.tsx | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/packages/shared/src/editor/use-editor.tsx b/packages/shared/src/editor/use-editor.tsx index 56ffa638..100da5be 100644 --- a/packages/shared/src/editor/use-editor.tsx +++ b/packages/shared/src/editor/use-editor.tsx @@ -52,8 +52,6 @@ export const useEditor = ({ const containerRef = useRef(); const monacoRef = useRef(); - const [compilerOutput, setCompilerOutput] = useState([]); - const editorWillMount = (monaco: any) => { try { @@ -113,15 +111,8 @@ export const useEditor = ({ let compileValue = editorRef.current?.getValue() await prepareForEvaluation(containerRef.current, compileValue, languageContext.file) - //setCompilerOutput([]); targets?.forEach(async (target, index) => { compiler.submit(new CompilationRequest(compileValue!, target)); - //const compilation = await compiler.compile(new CompilationRequest(compileValue!, target)); - // const output = { - // target, - // files: compilation.files, - // } - //setCompilerOutput(prev => [...prev, output]); if (index === targets.length - 1) { onLoadingStatusChange(LoadingStatus.Completed) setIsCompiling(false) @@ -139,6 +130,5 @@ export const useEditor = ({ editorDidMount, evaluateCode, isCompiling, - compilerOutput } } From 2f4e9cf9e7a8e2fbc6d5398a6cfac59f65eb8edb Mon Sep 17 00:00:00 2001 From: polamoros Date: Wed, 24 May 2023 11:14:00 +0200 Subject: [PATCH 31/52] wip --- apps/tour/src/Editor.tsx | 3 +- apps/tour/src/TfAwsTarget.tsx | 85 ++++++++++++++++++----------------- packages/shared/src/Tabs.tsx | 4 +- 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index c5f325a2..77940978 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -260,7 +260,8 @@ export const ReactMonacoEditor: React.FC = ({ setCompilationItems([]); if (currentTargetId === tfAwsTarget.id) { setIsCompiling(true); - const compilation = compiler.compile(new CompilationRequest(editorRef.current?.getValue()!, Target.TFAWS)); + const request = new CompilationRequest(editorRef.current?.getValue()!, Target.TFAWS); + const compilation = compiler.compile(request); compilation.then(result => { setCompilationItems(result.files); setIsCompiling(false); diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index 25e84cd9..e94d7d2e 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -160,25 +160,24 @@ export const TfAwsTarget = ({ files, downloadCompiledCode, loading, disabled }: return ( -
-
- {loading && ( -
- -
- )} - -
-
-
-
-
- Terraform - ({resources.length || 0}) -
-
+
+ {loading && ( +
+ +
+ )} +
+
+
+
+ Terraform + ({resources.length || 0})
-
+
+
+
+
+
{resources?.length === 0 && !loading && (
No resources found @@ -201,21 +200,23 @@ export const TfAwsTarget = ({ files, downloadCompiledCode, loading, disabled }: })}
+
-
-
-
-
- Assets - ({files?.length || 0}) -
-
- -
-
+
+
+
+ Assets + ({files?.length || 0})
+
+ +
+
+
+
+
{files?.length === 0 && !loading && (
@@ -235,18 +236,18 @@ export const TfAwsTarget = ({ files, downloadCompiledCode, loading, disabled }:
+
-
- -
+
+
) diff --git a/packages/shared/src/Tabs.tsx b/packages/shared/src/Tabs.tsx index 7148b628..0234169b 100644 --- a/packages/shared/src/Tabs.tsx +++ b/packages/shared/src/Tabs.tsx @@ -55,8 +55,8 @@ export const Tabs = (props: TabsProps) => { className={classNames( "relative flex items-center cursor-pointer group", "px-4 py-1 h-full", - isCurrent && "bg-slate-500", - !isCurrent && ["bg-transparent", "hover:bg-slate-500"], + isCurrent && "bg-slate-700", + !isCurrent && ["bg-transparent", "hover:bg-slate-700"], tab.tabClassName, )} onClick={() => setCurrentTabId(tab.id)} From a3887cc7cc49929c139386c2ad8c45325b2628d8 Mon Sep 17 00:00:00 2001 From: polamoros Date: Wed, 24 May 2023 11:34:06 +0200 Subject: [PATCH 32/52] wip --- apps/tour/src/Editor.tsx | 28 +++++++++++++++++++--------- apps/tour/src/TfAwsTarget.tsx | 8 ++++---- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index 77940978..9a0945b7 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -213,6 +213,21 @@ export const ReactMonacoEditor: React.FC = ({ setDownloadInProgress(false); }; + const retrieveCompilationFiles = useCallback(async (value: string, target: Target) => { + setIsCompiling(true); + const request = new CompilationRequest(value, target); + + const result = await compiler.compile(request); + if (result.error) { + console.error('compilation failed', result.error.stderr); + setIsCompiling(false); + return; + } + setCompilationItems(result.files); + setIsCompiling(false); + }, [compiler]); + + const [showWelcomeModal, setShowWelcomeModal] = useState(true); const [showFinishModal, setShowFinishModal] = useState(false); @@ -258,16 +273,11 @@ export const ReactMonacoEditor: React.FC = ({ useEffect(() => { setCompilationItems([]); - if (currentTargetId === tfAwsTarget.id) { - setIsCompiling(true); - const request = new CompilationRequest(editorRef.current?.getValue()!, Target.TFAWS); - const compilation = compiler.compile(request); - compilation.then(result => { - setCompilationItems(result.files); - setIsCompiling(false); - }); + if (currentTargetId === Target.TFAWS) { + const value = editorRef.current?.getValue(); + retrieveCompilationFiles(value, Target.TFAWS); } - }, [currentTargetId, compiler, editorRef.current?.getValue()]); + }, [currentTargetId, editorRef.current?.getValue()]); return ( <> diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index e94d7d2e..36de3d98 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -168,7 +168,7 @@ export const TfAwsTarget = ({ files, downloadCompiledCode, loading, disabled }: )}
-
+
Terraform ({resources.length || 0}) @@ -179,7 +179,7 @@ export const TfAwsTarget = ({ files, downloadCompiledCode, loading, disabled }:
{resources?.length === 0 && !loading && ( -
+
No resources found
)} @@ -203,7 +203,7 @@ export const TfAwsTarget = ({ files, downloadCompiledCode, loading, disabled }:
-
+
Assets ({files?.length || 0}) @@ -219,7 +219,7 @@ export const TfAwsTarget = ({ files, downloadCompiledCode, loading, disabled }:
{files?.length === 0 && !loading && ( -
+
No assets found
)} From 264940c724325b4691b4869f45bed529c9e7fc89 Mon Sep 17 00:00:00 2001 From: polamoros Date: Wed, 24 May 2023 11:47:31 +0200 Subject: [PATCH 33/52] wip --- apps/tour/src/Editor.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index 9a0945b7..4f57d27e 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -44,6 +44,7 @@ import {SimulatorTarget} from "@wing-playground/shared/src/SimulatorTarget"; import {TargetsView, TargetView} from "./TargetsView"; import {PanelHeader} from "@wing-playground/shared/src/PanelHeader"; import { TfAwsTarget } from './TfAwsTarget.js'; +import { debounce } from 'lodash'; const wingPackageJson = await import("winglang/package.json?raw").then( (i) => JSON.parse(i.default) @@ -213,10 +214,9 @@ export const ReactMonacoEditor: React.FC = ({ setDownloadInProgress(false); }; - const retrieveCompilationFiles = useCallback(async (value: string, target: Target) => { + const retrieveCompilationFiles = useCallback(debounce(async (value: string, target: Target) => { setIsCompiling(true); const request = new CompilationRequest(value, target); - const result = await compiler.compile(request); if (result.error) { console.error('compilation failed', result.error.stderr); @@ -225,7 +225,7 @@ export const ReactMonacoEditor: React.FC = ({ } setCompilationItems(result.files); setIsCompiling(false); - }, [compiler]); + }, 700), [compiler]); const [showWelcomeModal, setShowWelcomeModal] = useState(true); From dc8a731bf5abefdebbf1f3ef17b736d143846f46 Mon Sep 17 00:00:00 2001 From: polamoros Date: Wed, 24 May 2023 12:13:19 +0200 Subject: [PATCH 34/52] wip --- apps/tour/src/Editor.tsx | 2 +- apps/tour/src/TfAwsTarget.tsx | 40 +++++++++++++++++++++++++---------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index 4f57d27e..9d89b71f 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -275,7 +275,7 @@ export const ReactMonacoEditor: React.FC = ({ setCompilationItems([]); if (currentTargetId === Target.TFAWS) { const value = editorRef.current?.getValue(); - retrieveCompilationFiles(value, Target.TFAWS); + retrieveCompilationFiles(value || "", Target.TFAWS); } }, [currentTargetId, editorRef.current?.getValue()]); diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index 36de3d98..580d7cdd 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -122,6 +122,16 @@ const getAwsResources = (tfFile: string) => { } } +const getAssets = (files: CompilationItem[]) => { + const assets = files.filter((f) => f.name.startsWith(".wing/clients/")).map((file, index) => { + return { + name: `inflight${index + 1}.js`, + contents: file.contents, + } + }); + return assets; +} + export interface TfAwsTargetProps { files?: CompilationItem[]; downloadCompiledCode?: () => void; @@ -143,6 +153,14 @@ export const TfAwsTarget = ({ files, downloadCompiledCode, loading, disabled }: return newResources; }, [files]); + const assets = useMemo(() => { + if (!files) { + return []; + } + const newAssets = getAssets(files); + return newAssets; + }, [files]); + const options: monaco.editor.IStandaloneEditorConstructionOptions = { minimap: { enabled: false }, }; @@ -153,10 +171,10 @@ export const TfAwsTarget = ({ files, downloadCompiledCode, loading, disabled }: useEffect(() => { setSelectedFile({ - name: resources[0]?.path || files?.[0]?.name || "", - contents: resources[0]?.contents || files?.[0]?.contents || "", + name: resources[0]?.path || assets?.[0]?.name || "", + contents: resources[0]?.contents || assets?.[0]?.contents || "", }); - }, [files, resources]); + }, [assets, resources]); return ( @@ -206,10 +224,10 @@ export const TfAwsTarget = ({ files, downloadCompiledCode, loading, disabled }:
Assets - ({files?.length || 0}) + ({assets?.length || 0})
-
@@ -218,18 +236,18 @@ export const TfAwsTarget = ({ files, downloadCompiledCode, loading, disabled }:
- {files?.length === 0 && !loading && ( + {assets?.length === 0 && !loading && (
No assets found
)} - {files?.map((file) => { + {assets?.map((asset) => { return ( setSelectedFile(file)} + key={asset.name} + title={asset.name} + selected={selectedFile?.name === asset.name} + onClick={() => setSelectedFile(asset)} /> ) })} From 5f0b4eca43398ca3230a161b7cccfeb90c8e09a9 Mon Sep 17 00:00:00 2001 From: polamoros Date: Wed, 24 May 2023 12:27:30 +0200 Subject: [PATCH 35/52] wip --- .../tour/public/aws/aws_lambda_permission.svg | 3 ++ apps/tour/public/aws/aws_sns_topic.svg | 3 ++ apps/tour/src/TfAwsTarget.tsx | 34 +++++++++++-------- 3 files changed, 26 insertions(+), 14 deletions(-) create mode 100644 apps/tour/public/aws/aws_lambda_permission.svg create mode 100644 apps/tour/public/aws/aws_sns_topic.svg diff --git a/apps/tour/public/aws/aws_lambda_permission.svg b/apps/tour/public/aws/aws_lambda_permission.svg new file mode 100644 index 00000000..b025b9da --- /dev/null +++ b/apps/tour/public/aws/aws_lambda_permission.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/tour/public/aws/aws_sns_topic.svg b/apps/tour/public/aws/aws_sns_topic.svg new file mode 100644 index 00000000..da75e882 --- /dev/null +++ b/apps/tour/public/aws/aws_sns_topic.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index 580d7cdd..5844cb26 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -31,21 +31,22 @@ const FileRow = ({title, description, icon, selected, onClick}: { return (
- + */}
From 1006331ca93fe47db950597a19175a9b6682b742 Mon Sep 17 00:00:00 2001 From: polamoros Date: Wed, 24 May 2023 13:51:44 +0200 Subject: [PATCH 38/52] cleanup code --- apps/tour/src/TfAwsTarget.tsx | 271 +++++++++++++++++++--------------- packages/shared/src/Tabs.tsx | 8 +- 2 files changed, 153 insertions(+), 126 deletions(-) diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index f1fdd63c..2062be62 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -21,40 +21,6 @@ import { CompilationItem } from "@wing-playground/shared/src/compiler/compiler"; import { Loading } from "@wing-playground/shared/src/Loading"; import { ArrowDownTrayIcon } from "@heroicons/react/24/solid"; -const FileRow = ({title, description, icon, selected, onClick}: { - title: string, - description?: string, - icon?: React.ReactNode, - selected: boolean, - onClick: () => void -}) => { - return ( -
- -
- ) -} - const getResourceName = (type: string) => { switch (type) { case "aws_sqs_queue": @@ -95,13 +61,6 @@ const ResourceIcon = ({type}: {type: string}) => { return } -export type Resource = { - path: string; - name: string; - type: string; - contents: string; -} - const getAwsResources = (tfFile: string) => { try { const json = JSON.parse(tfFile); @@ -138,6 +97,105 @@ const getAssets = (files: CompilationItem[]) => { return assets; } +interface Item { + id: string; + name: string; + description?: string; + type?: string; + contents: string; +} + +const FileRow = ({title, description, icon, selected, onClick}: { + title: string, + description?: string, + icon?: React.ReactNode, + selected: boolean, + onClick: () => void +}) => { + return ( +
+ +
+ ) +} + +const ItemsList = ({ + title, + items, + selectedItem, + loading, + placeholder, + onClick, + actions, +}:{ + title: string; + items: Item[]; + selectedItem?: Item; + loading: boolean; + placeholder?: string; + onClick: (item: Item) => void; + actions?: React.ReactNode; +}) => { + return ( + <> +
+
+
+ {title} + ({items?.length || 0}) +
+
+ {actions} +
+
+
+
+
+
+ {items.length === 0 && !loading && ( +
+ {placeholder} +
+ )} + {items.map((item) => { + return ( + } + selected={selectedItem?.id === item.id} + onClick={() => onClick(item)} + /> + ) + })} +
+
+
+ + ) +}; + export interface TfAwsTargetProps { files?: CompilationItem[]; downloadCompiledCode?: () => void; @@ -145,26 +203,45 @@ export interface TfAwsTargetProps { disabled?: boolean; } -export const TfAwsTarget = ({ files, downloadCompiledCode, loading, disabled }: TfAwsTargetProps) => { +export const TfAwsTarget = ({ + files, + downloadCompiledCode, + loading = false, + disabled = false +}: TfAwsTargetProps) => { const compileEditorRef = useRef(); - const [selectedFile, setSelectedFile] = useState(files?.[0]); + const [selectedItem, setSelectedItem] = useState(); - const resources = useMemo(() => { + const resources: Item[] = useMemo(() => { if (!files) { return []; } const newResources = getAwsResources( - files?.find((f) => f.name === "main.tf.json")?.contents || "" + files?.find((file) => file.name === "main.tf.json")?.contents || "" ); - return newResources; + return newResources.map((resource) => { + return { + id: resource.path, + name: getResourceName(resource.type), + description: resource.name, + type: resource.type, + contents: resource.contents, + } + }); }, [files]); - const assets = useMemo(() => { + const assets: Item[] = useMemo(() => { if (!files) { return []; } const newAssets = getAssets(files); - return newAssets; + return newAssets.map((asset) => { + return { + id: asset.name, + name: asset.name, + contents: asset.contents, + } + }); }, [files]); const options: monaco.editor.IStandaloneEditorConstructionOptions = { @@ -176,10 +253,7 @@ export const TfAwsTarget = ({ files, downloadCompiledCode, loading, disabled }: } useEffect(() => { - setSelectedFile({ - name: resources[0]?.path || assets?.[0]?.name || "", - contents: resources[0]?.contents || assets?.[0]?.contents || "", - }); + setSelectedItem(resources[0] || assets[0]); }, [assets, resources]); @@ -191,86 +265,39 @@ export const TfAwsTarget = ({ files, downloadCompiledCode, loading, disabled }:
)}
-
-
-
- Terraform - ({resources.length || 0}) -
-
-
-
-
-
- {resources?.length === 0 && !loading && ( -
- No resources found -
- )} - {resources?.map((resource) => { - return ( - } - selected={selectedFile?.name === resource.path} - onClick={() => setSelectedFile({ - name: resource.path, - contents: resource.contents, - })} - /> - ) - })} -
-
-
+ -
-
-
- Assets - ({assets?.length || 0}) -
-
- {/* */} -
-
-
-
-
-
- {assets?.length === 0 && !loading && ( -
- No assets found -
- )} - {assets?.map((asset) => { - return ( - setSelectedFile(asset)} - /> - ) - })} -
-
-
+ + // + // + // } + items={assets} + selectedItem={selectedItem} + loading={loading} + placeholder="No assets found" + onClick={setSelectedItem} + />
diff --git a/packages/shared/src/Tabs.tsx b/packages/shared/src/Tabs.tsx index 0234169b..f31634ed 100644 --- a/packages/shared/src/Tabs.tsx +++ b/packages/shared/src/Tabs.tsx @@ -55,8 +55,8 @@ export const Tabs = (props: TabsProps) => { className={classNames( "relative flex items-center cursor-pointer group", "px-4 py-1 h-full", - isCurrent && "bg-slate-700", - !isCurrent && ["bg-transparent", "hover:bg-slate-700"], + isCurrent && "bg-gray-700", + !isCurrent && ["bg-transparent", "hover:bg-gray-700"], tab.tabClassName, )} onClick={() => setCurrentTabId(tab.id)} @@ -75,13 +75,13 @@ export const Tabs = (props: TabsProps) => { From 3b2e48b1e1f9b7b9ea0db63635a076bb2eab6ef3 Mon Sep 17 00:00:00 2001 From: polamoros Date: Wed, 24 May 2023 13:55:18 +0200 Subject: [PATCH 39/52] cleanup code --- apps/tour/src/TfAwsTarget.tsx | 81 ++++++++++++++--------------------- 1 file changed, 33 insertions(+), 48 deletions(-) diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index 2062be62..807766e8 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -61,42 +61,6 @@ const ResourceIcon = ({type}: {type: string}) => { return } -const getAwsResources = (tfFile: string) => { - try { - const json = JSON.parse(tfFile); - if (!json.resource) { - return []; - } - - const resources: Resource[] = []; - for (const [key, value] of Object.entries(json.resource)) { - for (const [key2, value2] of Object.entries(value as object)) { - const path = value2["//"]["metadata"]["path"] || key2; - const resourceName = path.split("/").slice(-2, -1)[0]; - resources.push({ - path: path, - name: resourceName, - type: key, - contents: JSON.stringify(value2, null, 2) - }); - } - } - return resources; - } catch (e) { - return []; - } -} - -const getAssets = (files: CompilationItem[]) => { - const assets = files.filter((f) => f.name.startsWith(".wing/clients/")).map((file, index) => { - return { - name: `inflight${index + 1}.js`, - contents: file.contents, - } - }); - return assets; -} - interface Item { id: string; name: string; @@ -216,25 +180,46 @@ export const TfAwsTarget = ({ if (!files) { return []; } - const newResources = getAwsResources( - files?.find((file) => file.name === "main.tf.json")?.contents || "" - ); - return newResources.map((resource) => { - return { - id: resource.path, - name: getResourceName(resource.type), - description: resource.name, - type: resource.type, - contents: resource.contents, + + const tfFile = files?.find((file) => file.name === "main.tf.json")?.contents; + if (!tfFile) { + return []; + } + try { + const json = JSON.parse(tfFile); + if (!json.resource) { + return []; } - }); + const resources: Item[] = []; + for (const [key, value] of Object.entries(json.resource)) { + for (const [key2, value2] of Object.entries(value as object)) { + const path = value2["//"]["metadata"]["path"] || key2; + const resourceName = path.split("/").slice(-2, -1)[0]; + resources.push({ + id: path, + name: getResourceName(key), + description: resourceName, + type: key, + contents: JSON.stringify(value2, null, 2) + }); + } + } + return resources; + } catch (e) { + return []; + } }, [files]); const assets: Item[] = useMemo(() => { if (!files) { return []; } - const newAssets = getAssets(files); + const newAssets = files.filter((f) => f.name.startsWith(".wing/clients/")).map((file, index) => { + return { + name: `inflight${index + 1}.js`, + contents: file.contents, + } + }); return newAssets.map((asset) => { return { id: asset.name, From 78f8930da635d75746115c503b9cb1dca0170890 Mon Sep 17 00:00:00 2001 From: polamoros Date: Wed, 24 May 2023 15:02:56 +0200 Subject: [PATCH 40/52] wip --- apps/tour/src/Editor.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index de12b036..67ad86b2 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -254,6 +254,11 @@ export const ReactMonacoEditor: React.FC = ({ const targetViews: TargetView[] = useMemo(() => { const views: TargetView[] = []; + + if (!outputTargets || outputTargets.length === 0) { + return [simulatorTarget]; + } + outputTargets.forEach(target => { if (target === "simulator") { views.push(simulatorTarget); From d3f4a7a1e786f100822c500042bb5e74f9219141 Mon Sep 17 00:00:00 2001 From: Eyal Keren Date: Wed, 24 May 2023 16:05:43 +0300 Subject: [PATCH 41/52] tour v2 --- apps/tour/src/tutorials/02-solution.w | 7 +++++++ apps/tour/src/tutorials/02-tutorial.md | 14 ++++++++++---- apps/tour/src/tutorials/03-code.w | 8 +++++++- apps/tour/src/tutorials/03-solution.w | 9 ++++++--- apps/tour/src/tutorials/04-solution.w | 17 ----------------- apps/tour/src/tutorials/04-tutorial.md | 12 +++++++----- apps/tour/src/tutorials/05-code.w | 6 +++--- apps/tour/src/tutorials/05-solution.w | 8 ++++---- apps/tour/src/tutorials/05-tutorial.md | 2 ++ apps/tour/src/tutorials/index.ts | 15 +++++++-------- 10 files changed, 53 insertions(+), 45 deletions(-) create mode 100644 apps/tour/src/tutorials/02-solution.w delete mode 100644 apps/tour/src/tutorials/04-solution.w diff --git a/apps/tour/src/tutorials/02-solution.w b/apps/tour/src/tutorials/02-solution.w new file mode 100644 index 00000000..1e35dd1d --- /dev/null +++ b/apps/tour/src/tutorials/02-solution.w @@ -0,0 +1,7 @@ +bring cloud; + +let q = new cloud.Queue(); + +let handler = inflight (s: str) => { + log("Cloud Function was called with ${s}"); +}; diff --git a/apps/tour/src/tutorials/02-tutorial.md b/apps/tour/src/tutorials/02-tutorial.md index 438b7b6d..e3a86e2b 100644 --- a/apps/tour/src/tutorials/02-tutorial.md +++ b/apps/tour/src/tutorials/02-tutorial.md @@ -1,6 +1,12 @@ -# Push a message to the queue +# Inflight function compiles to javascript code -1. In the Wing Simulator, **click on the resource in the center named "cloud.Queue"**. An interaction panel will appear on the right hand side. -2. Under **Push Message**, type in a message and click **Send**. +inflight functions are functions that are going to run on the cloud + +1. Paste this inflight function in line 4: +```ts +let handler = inflight (s: str) => { + log("inflight function was called with ${s}"); +}; +``` +2. Notice the Inflight1 javascript code under assets -🔍 Notice how the **Approx size** of the queue has changed. diff --git a/apps/tour/src/tutorials/03-code.w b/apps/tour/src/tutorials/03-code.w index 3b6b3503..e602d83c 100644 --- a/apps/tour/src/tutorials/03-code.w +++ b/apps/tour/src/tutorials/03-code.w @@ -1,3 +1,9 @@ bring cloud; -let q = new cloud.Queue(); \ No newline at end of file +let q = new cloud.Queue(); + +let handler = inflight (s: str) => { + log("Cloud Function was called with ${s}"); + // Type 'q.' to see the available methods + +}; diff --git a/apps/tour/src/tutorials/03-solution.w b/apps/tour/src/tutorials/03-solution.w index 880477cf..68ed22f9 100644 --- a/apps/tour/src/tutorials/03-solution.w +++ b/apps/tour/src/tutorials/03-solution.w @@ -2,6 +2,9 @@ bring cloud; let q = new cloud.Queue(); -new cloud.Function(inflight (s: str) => { - log("Cloud Function was called with ${s}"); -}); \ No newline at end of file +let handler = inflight (s: str) => { + log("inflight function was called with ${s}"); + q.push(s); +}; + +new cloud.Function(handler); diff --git a/apps/tour/src/tutorials/04-solution.w b/apps/tour/src/tutorials/04-solution.w deleted file mode 100644 index 2b2cd586..00000000 --- a/apps/tour/src/tutorials/04-solution.w +++ /dev/null @@ -1,17 +0,0 @@ -bring cloud; - -let q = new cloud.Queue(); - -new cloud.Function(inflight (s: str) => { - log("Cloud Function was called with ${s}"); - q.push(s); -}); - -// Type 'q.' to see the available methods here. -// Notice how they are different from the ones -// suggested within the Cloud Function in line 7. -// It's because even though it's the same queue, -// lines 7 & 10 are in different execution phases. -// preflight - for infrastructure definitions, executed at compile time. -// inflight - for business logic, executed at runtime. -// We'll learn more about these concepts in the next tutorial. \ No newline at end of file diff --git a/apps/tour/src/tutorials/04-tutorial.md b/apps/tour/src/tutorials/04-tutorial.md index ed91e1ea..1264672e 100644 --- a/apps/tour/src/tutorials/04-tutorial.md +++ b/apps/tour/src/tutorials/04-tutorial.md @@ -1,7 +1,9 @@ -# Push a message to the queue programmatically +# Wing Simulator -1. Add code to push the function's payload to the queue in line 7. (Hint: look at how the payload is added to the log in line 6). -2. Invoke the cloud.Function in the simulator (notice it's connected to the queue now). -3. Explore what happens in the cloud.Queue in the simulator. + +1. In the Wing Simulator, click on the resource in the center named "cloud.Function". +2. An interaction panel will appear on the right hand side. +3. Under Invoke, type in a message and click Send. +4. In the Wing Simulator, click on the resource in the center named "cloud.Queue" +5. Notice how the **Approx size** increases every time you call it -🏆 **Bonus:** Look at the code comment in line 10. \ No newline at end of file diff --git a/apps/tour/src/tutorials/05-code.w b/apps/tour/src/tutorials/05-code.w index 834be567..deb69a97 100644 --- a/apps/tour/src/tutorials/05-code.w +++ b/apps/tour/src/tutorials/05-code.w @@ -4,6 +4,6 @@ let q = new cloud.Queue(); // Paste here new cloud.Function(inflight (s: str) => { - log("Cloud Function was called with ${s}"); - q.push(s); -}); \ No newline at end of file + log("inflight function was called with ${s}"); + q.push(s); +}); diff --git a/apps/tour/src/tutorials/05-solution.w b/apps/tour/src/tutorials/05-solution.w index 5e839b82..b72627d5 100644 --- a/apps/tour/src/tutorials/05-solution.w +++ b/apps/tour/src/tutorials/05-solution.w @@ -4,10 +4,10 @@ let q = new cloud.Queue(); let b = new cloud.Bucket() as "Bucket: Last Message"; q.addConsumer(inflight (m: str) => { - b.put("latest.txt", m); + b.put("latest.txt", m); }); new cloud.Function(inflight (s: str) => { - log("Cloud Function was called with ${s}"); - q.push(s); -}); \ No newline at end of file + log("inflight function was called with ${s}"); + q.push(s); +}); diff --git a/apps/tour/src/tutorials/05-tutorial.md b/apps/tour/src/tutorials/05-tutorial.md index 4a826332..97f57136 100644 --- a/apps/tour/src/tutorials/05-tutorial.md +++ b/apps/tour/src/tutorials/05-tutorial.md @@ -1,5 +1,7 @@ # Add a Bucket to store the latest message sent to our queue. +To make things shorter we've inlined the inflight handler + 1. Paste this code in line 4. ```ts let b = new cloud.Bucket() as "Bucket: Last Message"; diff --git a/apps/tour/src/tutorials/index.ts b/apps/tour/src/tutorials/index.ts index ce33ef23..3adf6d14 100644 --- a/apps/tour/src/tutorials/index.ts +++ b/apps/tour/src/tutorials/index.ts @@ -39,29 +39,28 @@ export const tutorials = [ code: code01, solution: solution01, tutorial: tutorial01, - targets: ["simulator", Target.TFAWS], + targets: [Target.TFAWS], }, { id: "2", - name: "Push Message", + name: "Inflight Code", code: code02, - // solution: solution02, + solution: solution02, tutorial: tutorial02, - targets: ["simulator", Target.TFAWS], + targets: [Target.TFAWS], }, { id: "3", - name: "Logs", + name: "cloud.Function", code: code03, solution: solution03, tutorial: tutorial03, - targets: ["simulator", Target.TFAWS], + targets: [Target.TFAWS], }, { id: "4", - name: "Push Programmatically", + name: "Simulator", code: code04, - solution: solution04, tutorial: tutorial04, targets: ["simulator", Target.TFAWS], }, From 196d847824029788a142c71f27190eee52277e80 Mon Sep 17 00:00:00 2001 From: Eyal Keren Date: Wed, 24 May 2023 16:08:13 +0300 Subject: [PATCH 42/52] tour v2 --- apps/tour/src/tutorials/01-tutorial.md | 10 ++++++---- apps/tour/src/tutorials/02-solution.w | 2 +- apps/tour/src/tutorials/03-code.w | 3 +-- apps/tour/src/tutorials/03-tutorial.md | 16 +++++++++------- apps/tour/src/tutorials/04-code.w | 17 +++++------------ apps/tour/src/tutorials/06-code.w | 2 +- 6 files changed, 23 insertions(+), 27 deletions(-) diff --git a/apps/tour/src/tutorials/01-tutorial.md b/apps/tour/src/tutorials/01-tutorial.md index bd0cf72b..3cf3c3cb 100644 --- a/apps/tour/src/tutorials/01-tutorial.md +++ b/apps/tour/src/tutorials/01-tutorial.md @@ -1,7 +1,9 @@ -# Let's add the first cloud service to our app +# Cloud.Queue resource Below is an empty Wing source code file. -The first line, "bring cloud", lets us access resources from the Wing standard library. -1. **Uncomment line 3**. A **queue** will appear in the simulator to the right. -2. Click **Next** to continue +1. Uncomment line 3 +2. The code compiles into terraform, see generate SQS queue on the right +3. Click **Next** to continue + + diff --git a/apps/tour/src/tutorials/02-solution.w b/apps/tour/src/tutorials/02-solution.w index 1e35dd1d..942df34d 100644 --- a/apps/tour/src/tutorials/02-solution.w +++ b/apps/tour/src/tutorials/02-solution.w @@ -3,5 +3,5 @@ bring cloud; let q = new cloud.Queue(); let handler = inflight (s: str) => { - log("Cloud Function was called with ${s}"); + log("inflight function was called with ${s}"); }; diff --git a/apps/tour/src/tutorials/03-code.w b/apps/tour/src/tutorials/03-code.w index e602d83c..5e90ac17 100644 --- a/apps/tour/src/tutorials/03-code.w +++ b/apps/tour/src/tutorials/03-code.w @@ -3,7 +3,6 @@ bring cloud; let q = new cloud.Queue(); let handler = inflight (s: str) => { - log("Cloud Function was called with ${s}"); + log("inflight function was called with ${s}"); // Type 'q.' to see the available methods - }; diff --git a/apps/tour/src/tutorials/03-tutorial.md b/apps/tour/src/tutorials/03-tutorial.md index ff5428ea..2a3cf56e 100644 --- a/apps/tour/src/tutorials/03-tutorial.md +++ b/apps/tour/src/tutorials/03-tutorial.md @@ -1,11 +1,13 @@ -# Invoke a function and explore the Logs Panel +# Use cloud.Function for invoking the handler -1. Paste this code in line 4: +Let's wrap the inflight code with a cloud.Function + +1. Add code to push string s into `q` in line 7 +2. Add a cloud.Function resource that will use the handler ```ts -new cloud.Function(inflight (s: str) => { - log("Cloud Function was called with ${s}"); -}); +new cloud.Function(handler); ``` -2. Find the **cloud.Function** in the simulator and **invoke** it with a payload. +3. Notice that there are a lot of new resources, including IAM permissions +4. + -🔍 Notice the resulting log at the bottom of the simulator. diff --git a/apps/tour/src/tutorials/04-code.w b/apps/tour/src/tutorials/04-code.w index d91c1411..aaaa7359 100644 --- a/apps/tour/src/tutorials/04-code.w +++ b/apps/tour/src/tutorials/04-code.w @@ -2,16 +2,9 @@ bring cloud; let q = new cloud.Queue(); -new cloud.Function(inflight (s: str) => { - log("Cloud Function was called with ${s}"); - // Type 'q.' to see the available methods -}); +let handler = inflight (s: str) => { + log("inflight function was called with ${s}"); + q.push(s); +}; -// Type 'q.' to see the available methods here. -// Notice how they are different from the ones -// suggested within the Cloud Function in line 7. -// It's because even though it's the same queue, -// lines 7 & 10 are in different execution phases. -// preflight - for infrastructure definitions, executed at compile time. -// inflight - for business logic, executed at runtime. -// We'll learn more about these concepts in the next tutorial. \ No newline at end of file +new cloud.Function(handler); diff --git a/apps/tour/src/tutorials/06-code.w b/apps/tour/src/tutorials/06-code.w index 5e839b82..8e579a3c 100644 --- a/apps/tour/src/tutorials/06-code.w +++ b/apps/tour/src/tutorials/06-code.w @@ -10,4 +10,4 @@ q.addConsumer(inflight (m: str) => { new cloud.Function(inflight (s: str) => { log("Cloud Function was called with ${s}"); q.push(s); -}); \ No newline at end of file +}); From fed8c05465ce33e402b32848e931d41f4f0181ea Mon Sep 17 00:00:00 2001 From: Eyal Keren Date: Wed, 24 May 2023 16:15:47 +0300 Subject: [PATCH 43/52] tour v2 --- apps/tour/src/tutorials/02-solution.w | 2 +- apps/tour/src/tutorials/03-code.w | 4 ++-- apps/tour/src/tutorials/04-code.w | 4 ++-- apps/tour/src/tutorials/06-code.w | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/tour/src/tutorials/02-solution.w b/apps/tour/src/tutorials/02-solution.w index 942df34d..62a83268 100644 --- a/apps/tour/src/tutorials/02-solution.w +++ b/apps/tour/src/tutorials/02-solution.w @@ -3,5 +3,5 @@ bring cloud; let q = new cloud.Queue(); let handler = inflight (s: str) => { - log("inflight function was called with ${s}"); + log("inflight function was called with ${s}"); }; diff --git a/apps/tour/src/tutorials/03-code.w b/apps/tour/src/tutorials/03-code.w index 5e90ac17..c225a38a 100644 --- a/apps/tour/src/tutorials/03-code.w +++ b/apps/tour/src/tutorials/03-code.w @@ -3,6 +3,6 @@ bring cloud; let q = new cloud.Queue(); let handler = inflight (s: str) => { - log("inflight function was called with ${s}"); - // Type 'q.' to see the available methods + log("inflight function was called with ${s}"); + // Type 'q.' to see the available methods }; diff --git a/apps/tour/src/tutorials/04-code.w b/apps/tour/src/tutorials/04-code.w index aaaa7359..68ed22f9 100644 --- a/apps/tour/src/tutorials/04-code.w +++ b/apps/tour/src/tutorials/04-code.w @@ -3,8 +3,8 @@ bring cloud; let q = new cloud.Queue(); let handler = inflight (s: str) => { - log("inflight function was called with ${s}"); - q.push(s); + log("inflight function was called with ${s}"); + q.push(s); }; new cloud.Function(handler); diff --git a/apps/tour/src/tutorials/06-code.w b/apps/tour/src/tutorials/06-code.w index 8e579a3c..3b83433c 100644 --- a/apps/tour/src/tutorials/06-code.w +++ b/apps/tour/src/tutorials/06-code.w @@ -4,10 +4,10 @@ let q = new cloud.Queue(); let b = new cloud.Bucket() as "Bucket: Last Message"; q.addConsumer(inflight (m: str) => { - b.put("latest.txt", m); + b.put("latest.txt", m); }); new cloud.Function(inflight (s: str) => { - log("Cloud Function was called with ${s}"); - q.push(s); + log("Cloud Function was called with ${s}"); + q.push(s); }); From 7c61ef7dfd2224d739df3e975021751b40cf3afe Mon Sep 17 00:00:00 2001 From: Eyal Keren Date: Wed, 24 May 2023 16:17:37 +0300 Subject: [PATCH 44/52] tour v2 --- apps/tour/src/tutorials/02-tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/tour/src/tutorials/02-tutorial.md b/apps/tour/src/tutorials/02-tutorial.md index e3a86e2b..7a3ee205 100644 --- a/apps/tour/src/tutorials/02-tutorial.md +++ b/apps/tour/src/tutorials/02-tutorial.md @@ -8,5 +8,5 @@ let handler = inflight (s: str) => { log("inflight function was called with ${s}"); }; ``` -2. Notice the Inflight1 javascript code under assets +2. The inflight code compiled into JS, Look for the code under assets From e46538316253d44400ca6bf6a287fb0b8687bfa8 Mon Sep 17 00:00:00 2001 From: Eyal Keren Date: Wed, 24 May 2023 16:19:35 +0300 Subject: [PATCH 45/52] tour v2 --- apps/tour/src/WelcomeModal.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/tour/src/WelcomeModal.tsx b/apps/tour/src/WelcomeModal.tsx index 85507234..02ffcd8f 100644 --- a/apps/tour/src/WelcomeModal.tsx +++ b/apps/tour/src/WelcomeModal.tsx @@ -8,18 +8,18 @@ export const WelcomeModal = ({visible, onClose}: {visible: boolean, onClose: ()

Welcome to the Winglang Tutorial!

- Let's quickly build a smart queue that prints its messages and stores the latest one in a bucket. + Let's quickly learn about Winglang
- You'll interact with it in the embedded Wing Simulator, and then compile to AWS. + You'll create resources, explore the terraform output, interact with the Simulator and have fune
) -} \ No newline at end of file +} From a83db5a975f81d0716985fd1f928cac6e4e01ba1 Mon Sep 17 00:00:00 2001 From: polamoros Date: Wed, 24 May 2023 15:26:00 +0200 Subject: [PATCH 46/52] wip --- apps/tour/src/Editor.tsx | 20 +++++++++++--------- packages/shared/src/editor/use-editor.tsx | 8 ++++++-- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/apps/tour/src/Editor.tsx b/apps/tour/src/Editor.tsx index 67ad86b2..5cff8c09 100644 --- a/apps/tour/src/Editor.tsx +++ b/apps/tour/src/Editor.tsx @@ -97,10 +97,12 @@ export const ReactMonacoEditor: React.FC = ({ }); } - const [outputTargets, setOutputTarget] = useState(tutorials[0].targets); - const targets: Target[] = useMemo(() => { - return outputTargets.filter(t => t !== "simulator") as Target[]; - }, [outputTargets]); + const [targets, setTargets] = useState(["simulator"]); + const compilerTargets = useMemo(() => { + return targets.filter((target) => { + return target !== "simulator"; + }).map((target) => target as Target); + }, [targets]); const { evaluateCode, @@ -114,7 +116,7 @@ export const ReactMonacoEditor: React.FC = ({ languageContext, code: tutorials[0].code, compiler, - targets, + targets: compilerTargets, editorOptions, shouldInitContainer: true, }); @@ -192,7 +194,7 @@ export const ReactMonacoEditor: React.FC = ({ analytics.track(`tutorial: step: ${currentStepId}: changed`, { step: currentStep }) - setOutputTarget(currentStep.targets); + setTargets(currentStep.targets); setCurrentTargetId(targetViews[0]?.title); }, [currentStep]); @@ -255,11 +257,11 @@ export const ReactMonacoEditor: React.FC = ({ const targetViews: TargetView[] = useMemo(() => { const views: TargetView[] = []; - if (!outputTargets || outputTargets.length === 0) { + if (!targets || targets.length === 0) { return [simulatorTarget]; } - outputTargets.forEach(target => { + targets.forEach(target => { if (target === "simulator") { views.push(simulatorTarget); } @@ -268,7 +270,7 @@ export const ReactMonacoEditor: React.FC = ({ } }); return views; - }, [outputTargets, simulatorTarget, tfAwsTarget]); + }, [targets, simulatorTarget, tfAwsTarget]); const [currentTargetId, setCurrentTargetId] = useState(targetViews[0]?.id); diff --git a/packages/shared/src/editor/use-editor.tsx b/packages/shared/src/editor/use-editor.tsx index 100da5be..c12c0510 100644 --- a/packages/shared/src/editor/use-editor.tsx +++ b/packages/shared/src/editor/use-editor.tsx @@ -42,7 +42,7 @@ export const useEditor = ({ code, languageContext, compiler, - targets, + targets = [], installConsole, editorTheme, shouldInitContainer @@ -111,13 +111,17 @@ export const useEditor = ({ let compileValue = editorRef.current?.getValue() await prepareForEvaluation(containerRef.current, compileValue, languageContext.file) - targets?.forEach(async (target, index) => { + targets.forEach(async (target, index) => { compiler.submit(new CompilationRequest(compileValue!, target)); if (index === targets.length - 1) { onLoadingStatusChange(LoadingStatus.Completed) setIsCompiling(false) } }); + if (targets.length === 0) { + onLoadingStatusChange(LoadingStatus.Completed) + setIsCompiling(false) + } } catch (error) { console.error(error); onLoadingStatusChange(LoadingStatus.CompileError) From 35060d65004ea7b5bfefd219f1dc569ba4a98f47 Mon Sep 17 00:00:00 2001 From: Eyal Keren Date: Wed, 24 May 2023 16:34:51 +0300 Subject: [PATCH 47/52] tour v2 --- apps/tour/src/tutorials/03-tutorial.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/tour/src/tutorials/03-tutorial.md b/apps/tour/src/tutorials/03-tutorial.md index 2a3cf56e..0f8b4c8d 100644 --- a/apps/tour/src/tutorials/03-tutorial.md +++ b/apps/tour/src/tutorials/03-tutorial.md @@ -8,6 +8,6 @@ Let's wrap the inflight code with a cloud.Function new cloud.Function(handler); ``` 3. Notice that there are a lot of new resources, including IAM permissions -4. - +4. In IAM policy, find the `sqs:SendMessage` permission generated for the cloud.Function +Next, lets build this code for a different target, Wing Simulator From 3fe447d1a400a56048632e4eeadaaba33759f8b0 Mon Sep 17 00:00:00 2001 From: polamoros Date: Wed, 24 May 2023 15:34:52 +0200 Subject: [PATCH 48/52] expand json policy --- apps/tour/src/TfAwsTarget.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index 807766e8..6c9ce819 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -195,6 +195,9 @@ export const TfAwsTarget = ({ for (const [key2, value2] of Object.entries(value as object)) { const path = value2["//"]["metadata"]["path"] || key2; const resourceName = path.split("/").slice(-2, -1)[0]; + if (value2.policy) { + value2.policy = JSON.parse(value2.policy); + } resources.push({ id: path, name: getResourceName(key), From 4120f0ce67c86dbd51173e0c5d781f7b6f05185c Mon Sep 17 00:00:00 2001 From: Eyal Keren Date: Wed, 24 May 2023 16:41:24 +0300 Subject: [PATCH 49/52] tour v2 --- apps/tour/src/tutorials/02-solution.w | 1 + apps/tour/src/tutorials/02-tutorial.md | 1 + apps/tour/src/tutorials/03-code.w | 2 +- apps/tour/src/tutorials/03-tutorial.md | 7 +++---- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/tour/src/tutorials/02-solution.w b/apps/tour/src/tutorials/02-solution.w index 62a83268..74f72a29 100644 --- a/apps/tour/src/tutorials/02-solution.w +++ b/apps/tour/src/tutorials/02-solution.w @@ -4,4 +4,5 @@ let q = new cloud.Queue(); let handler = inflight (s: str) => { log("inflight function was called with ${s}"); + q.push(s); }; diff --git a/apps/tour/src/tutorials/02-tutorial.md b/apps/tour/src/tutorials/02-tutorial.md index 7a3ee205..b0203e25 100644 --- a/apps/tour/src/tutorials/02-tutorial.md +++ b/apps/tour/src/tutorials/02-tutorial.md @@ -6,6 +6,7 @@ inflight functions are functions that are going to run on the cloud ```ts let handler = inflight (s: str) => { log("inflight function was called with ${s}"); + // Type 'q.' to see the available methods }; ``` 2. The inflight code compiled into JS, Look for the code under assets diff --git a/apps/tour/src/tutorials/03-code.w b/apps/tour/src/tutorials/03-code.w index c225a38a..74f72a29 100644 --- a/apps/tour/src/tutorials/03-code.w +++ b/apps/tour/src/tutorials/03-code.w @@ -4,5 +4,5 @@ let q = new cloud.Queue(); let handler = inflight (s: str) => { log("inflight function was called with ${s}"); - // Type 'q.' to see the available methods + q.push(s); }; diff --git a/apps/tour/src/tutorials/03-tutorial.md b/apps/tour/src/tutorials/03-tutorial.md index 0f8b4c8d..f738a30f 100644 --- a/apps/tour/src/tutorials/03-tutorial.md +++ b/apps/tour/src/tutorials/03-tutorial.md @@ -2,12 +2,11 @@ Let's wrap the inflight code with a cloud.Function -1. Add code to push string s into `q` in line 7 -2. Add a cloud.Function resource that will use the handler +1. Add a cloud.Function resource that will use the handler ```ts new cloud.Function(handler); ``` -3. Notice that there are a lot of new resources, including IAM permissions -4. In IAM policy, find the `sqs:SendMessage` permission generated for the cloud.Function +2. Notice that there are a lot of new resources, including IAM permissions +3. In IAM policy, find the `sqs:SendMessage` permission generated for the cloud.Function Next, lets build this code for a different target, Wing Simulator From 8360b72f15933ec4b0f0b46fb384ca2951d7134e Mon Sep 17 00:00:00 2001 From: Eyal Keren Date: Wed, 24 May 2023 16:49:03 +0300 Subject: [PATCH 50/52] tour v2 --- apps/tour/src/tutorials/02-tutorial.md | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/tour/src/tutorials/02-tutorial.md b/apps/tour/src/tutorials/02-tutorial.md index b0203e25..e58d275d 100644 --- a/apps/tour/src/tutorials/02-tutorial.md +++ b/apps/tour/src/tutorials/02-tutorial.md @@ -10,4 +10,5 @@ let handler = inflight (s: str) => { }; ``` 2. The inflight code compiled into JS, Look for the code under assets +3. Add code to push string s into `q` in line 7 From 3406c0c54df516e385ba536ff4c89783a362d721 Mon Sep 17 00:00:00 2001 From: Eyal Keren Date: Wed, 24 May 2023 17:07:32 +0300 Subject: [PATCH 51/52] tour v2 --- apps/tour/src/TfAwsTarget.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index 6c9ce819..e2d151cf 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -1,4 +1,4 @@ -import {useEffect, useMemo, useRef, useState} from "react"; +iLet’s get started!mport {useEffect, useMemo, useRef, useState} from "react"; import Editor from "@monaco-editor/react"; import "monaco-editor/esm/vs/editor/editor.all.js"; @@ -198,6 +198,9 @@ export const TfAwsTarget = ({ if (value2.policy) { value2.policy = JSON.parse(value2.policy); } + if (value2.assume_role_policy) { + value2.assume_role_policy = JSON.parse(value2.assume_role_policy); + } resources.push({ id: path, name: getResourceName(key), From 4191768d1e511d791108e8a31b1341db1e4fc191 Mon Sep 17 00:00:00 2001 From: Eyal Keren Date: Wed, 24 May 2023 17:23:50 +0300 Subject: [PATCH 52/52] tour v2 --- apps/tour/src/TfAwsTarget.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/tour/src/TfAwsTarget.tsx b/apps/tour/src/TfAwsTarget.tsx index e2d151cf..619c9df6 100644 --- a/apps/tour/src/TfAwsTarget.tsx +++ b/apps/tour/src/TfAwsTarget.tsx @@ -1,4 +1,4 @@ -iLet’s get started!mport {useEffect, useMemo, useRef, useState} from "react"; +import {useEffect, useMemo, useRef, useState} from "react"; import Editor from "@monaco-editor/react"; import "monaco-editor/esm/vs/editor/editor.all.js";