Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Interactive mode to render different user interfaces based on the environment it's running in #182

Merged
merged 7 commits into from
Mar 7, 2024
Merged
17 changes: 16 additions & 1 deletion internal/engine/engine.go
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package engine

import (
"fmt"
"strings"

"github.com/Azure/InnovationEngine/internal/az"
"github.com/Azure/InnovationEngine/internal/engine/environments"
@@ -78,7 +79,21 @@ func (e *Engine) InteractWithScenario(scenario *Scenario) error {
}

program = tea.NewProgram(model, tea.WithAltScreen(), tea.WithMouseCellMotion())
_, err = program.Run()

var finalModel tea.Model
var ok bool
finalModel, err = program.Run()

model, ok = finalModel.(InteractiveModeModel)

if environments.EnvironmentsAzure == e.Configuration.Environment {
if !ok {
return fmt.Errorf("failed to cast tea.Model to InteractiveModeModel")
}

logging.GlobalLogger.Info("Writing session output to stdout")
fmt.Println(strings.Join(model.commandLines, "\n"))
}

switch e.Configuration.Environment {
case environments.EnvironmentsAzure, environments.EnvironmentsOCD:
2 changes: 1 addition & 1 deletion internal/engine/environments/azure.go
Original file line number Diff line number Diff line change
@@ -79,7 +79,7 @@ func ReportAzureStatus(status AzureDeploymentStatus, environment string) {
} else {
// We add these strings to the output so that the portal can find and parse
// the JSON status.
ocdStatus := fmt.Sprintf("ie_us%sie_ue\n", statusJson)
ocdStatus := fmt.Sprintf("ie_us%sie_ue", statusJson)
fmt.Println(ui.OcdStatusUpdateStyle.Render(ocdStatus))
}
}
84 changes: 50 additions & 34 deletions internal/engine/interactive.go
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package engine

import (
"fmt"
"strings"
"time"

"github.com/Azure/InnovationEngine/internal/az"
@@ -41,9 +42,10 @@ type CodeBlockState struct {
}

type interactiveModeComponents struct {
paginator paginator.Model
stepViewport viewport.Model
outputViewport viewport.Model
paginator paginator.Model
stepViewport viewport.Model
outputViewport viewport.Model
azureCLIViewport viewport.Model
}

type InteractiveModeModel struct {
@@ -62,6 +64,7 @@ type InteractiveModeModel struct {
scenarioCompleted bool
components interactiveModeComponents
ready bool
commandLines []string
}

// Initialize the intractive mode model
@@ -91,11 +94,13 @@ func initializeComponents(model InteractiveModeModel, width, height int) interac

stepViewport := viewport.New(width, 4)
outputViewport := viewport.New(width, 2)
azureCLIViewport := viewport.New(width, height)

components := interactiveModeComponents{
paginator: p,
stepViewport: stepViewport,
outputViewport: outputViewport,
paginator: p,
stepViewport: stepViewport,
outputViewport: outputViewport,
azureCLIViewport: azureCLIViewport,
}

components.updateViewportHeight(height)
@@ -207,6 +212,7 @@ func (components *interactiveModeComponents) updateViewportHeight(terminalHeight

components.stepViewport.Height = stepViewportHeight
components.outputViewport.Height = outputViewportHeight
components.azureCLIViewport.Height = terminalHeight - 1
}

// Updates the intractive mode model
@@ -225,6 +231,7 @@ func (model InteractiveModeModel) Update(message tea.Msg) (tea.Model, tea.Cmd) {
} else {
model.components.stepViewport.Width = message.Width
model.components.outputViewport.Width = message.Width
model.components.azureCLIViewport.Width = message.Width
model.components.updateViewportHeight(message.Height)
}

@@ -255,10 +262,18 @@ func (model InteractiveModeModel) Update(message tea.Msg) (tea.Model, tea.Cmd) {
model.resourceGroupName = tmpResourceGroup
}
}
model.commandLines = append(model.commandLines, codeBlockState.StdOut)

// Increment the codeblock and update the viewport content.
model.currentCodeBlock++

if model.currentCodeBlock < len(model.codeBlockState) {
nextCommand := model.codeBlockState[model.currentCodeBlock].CodeBlock.Content
nextLanguage := model.codeBlockState[model.currentCodeBlock].CodeBlock.Language

model.commandLines = append(model.commandLines, ui.CommandPrompt(nextLanguage)+nextCommand)
}

// Only increment the step for azure if the step name has changed.
nextCodeBlockState := model.codeBlockState[model.currentCodeBlock]

@@ -301,6 +316,7 @@ func (model InteractiveModeModel) Update(message tea.Msg) (tea.Model, tea.Cmd) {
codeBlockState.Success = false

model.codeBlockState[step] = codeBlockState
model.commandLines = append(model.commandLines, codeBlockState.StdErr)

// Report the error
model.executingCommand = false
@@ -381,6 +397,8 @@ func (model InteractiveModeModel) Update(message tea.Msg) (tea.Model, tea.Cmd) {
model.components.outputViewport.SetContent(block.StdErr)
}

model.components.azureCLIViewport.SetContent(strings.Join(model.commandLines, "\n"))

// Update all the viewports and append resulting commands.
var command tea.Cmd

@@ -392,6 +410,9 @@ func (model InteractiveModeModel) Update(message tea.Msg) (tea.Model, tea.Cmd) {
model.components.outputViewport, command = model.components.outputViewport.Update(message)
commands = append(commands, command)

model.components.azureCLIViewport, command = model.components.azureCLIViewport.Update(message)
commands = append(commands, command)

return model, tea.Batch(commands...)
}

@@ -419,44 +440,33 @@ func (model InteractiveModeModel) helpView() string {

// Renders the interactive mode model.
func (model InteractiveModeModel) View() string {
// When running in the portal, we only want to show the Azure CLI viewport
// which mimics a command line interface during execution.
if model.environment == "azure" {
return model.components.azureCLIViewport.View()
}

scenarioTitle := ui.ScenarioTitleStyle.Width(model.width).
Align(lipgloss.Center).
Render(model.scenarioTitle)
var stepTitle string
var stepView string
var stepSection string
stepTitle = ui.StepTitleStyle.Render(

border := lipgloss.NewStyle().
Width(model.components.stepViewport.Width - 2).
Border(lipgloss.NormalBorder())

stepTitle := ui.StepTitleStyle.Render(
fmt.Sprintf(
"Step %d - %s",
model.currentCodeBlock+1,
model.codeBlockState[model.currentCodeBlock].StepName,
),
)
stepView := border.Render(model.components.stepViewport.View())
stepSection := fmt.Sprintf("%s\n%s\n\n", stepTitle, stepView)

border := lipgloss.NewStyle().
Width(model.components.stepViewport.Width - 2)
// Border(lipgloss.NormalBorder())

stepView = border.Render(model.components.stepViewport.View())

if model.environment != "azure" {
stepSection = fmt.Sprintf("%s\n%s\n\n", stepTitle, stepView)
} else {
stepSection = fmt.Sprintf("%s\n%s\n", stepTitle, stepView)
}

var outputTitle string
var outputView string
var outputSection string
if model.environment != "azure" {
outputTitle = ui.StepTitleStyle.Render("Output")
outputView = border.Render(model.components.outputViewport.View())
outputSection = fmt.Sprintf("%s\n%s\n\n", outputTitle, outputView)
} else {
outputTitle = ""
outputView = ""
outputSection = ""
}
outputTitle := ui.StepTitleStyle.Render("Output")
outputView := border.Render(model.components.outputViewport.View())
outputSection := fmt.Sprintf("%s\n%s\n\n", outputTitle, outputView)

paginator := lipgloss.NewStyle().
Width(model.width).
@@ -532,6 +542,11 @@ func NewInteractiveModeModel(
azureStatus.AddStep(fmt.Sprintf("%d. %s", stepNumber+1, step.Name), azureCodeBlocks)
}

language := codeBlockState[0].CodeBlock.Language
commandLines := []string{
ui.CommandPrompt(language) + codeBlockState[0].CodeBlock.Content,
}

return InteractiveModeModel{
scenarioTitle: title,
commands: InteractiveModeCommands{
@@ -562,5 +577,6 @@ func NewInteractiveModeModel(
environment: engine.Configuration.Environment,
scenarioCompleted: false,
ready: false,
commandLines: commandLines,
}, nil
}
11 changes: 10 additions & 1 deletion internal/ui/text.go
Original file line number Diff line number Diff line change
@@ -44,8 +44,18 @@ var (
b.Left = "┤"
return InteractiveModeStepTitleStyle.Copy().BorderStyle(b)
}().Foreground(lipgloss.Color("#fff"))

promptTextStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#6CB6FF"))
promptDollarStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#32CD32"))
)

// Command prompt for interactive environments
func CommandPrompt(language string) string {
promptText := promptTextStyle.Render(language)
promptDollar := promptDollarStyle.Render("$")
return promptText + ":" + promptDollar + " "
}

// Indents a multi-line command to be nested under the first line of the
// command.
func IndentMultiLineCommand(content string, indentation int) string {
@@ -56,7 +66,6 @@ func IndentMultiLineCommand(content string, indentation int) string {
} else if strings.TrimSpace(lines[i]) != "" {
lines[i] = strings.Repeat(" ", indentation) + lines[i]
}

}
return strings.Join(lines, "\n")
}