github.com/GoogleCloudPlatform/deploystack@v1.12.8/tui/page.go (about) 1 // Copyright 2023 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package tui 16 17 import ( 18 "os" 19 "strings" 20 21 "github.com/charmbracelet/bubbles/spinner" 22 tea "github.com/charmbracelet/bubbletea" 23 ) 24 25 type dynamicPage struct { 26 queue *Queue 27 spinner spinner.Model 28 spinnerLabel string 29 key string 30 value string 31 err error 32 state string 33 content []component 34 preProcessor tea.Cmd 35 postProcessor func(string, *Queue) tea.Cmd 36 preViewFunc func(*Queue) 37 showProgress bool 38 omitFromSettings bool 39 querySlowText string 40 } 41 42 func (p *dynamicPage) getKey() string { 43 return p.key 44 } 45 46 func (p *dynamicPage) setValue(s string) { 47 p.value = s 48 } 49 50 func (p *dynamicPage) getValue() string { 51 return p.value 52 } 53 54 func (p *dynamicPage) clear() { 55 p.value = "" 56 } 57 58 func (p *dynamicPage) clearContent() { 59 p.content = []component{} 60 } 61 62 func (p *dynamicPage) addPostProcessor(f func(string, *Queue) tea.Cmd) { 63 p.postProcessor = f 64 } 65 66 func (p *dynamicPage) addPreProcessor(f tea.Cmd) { 67 p.preProcessor = f 68 } 69 70 func (p *dynamicPage) addQueue(q *Queue) { 71 p.queue = q 72 } 73 74 func (p *dynamicPage) addContent(s ...string) { 75 for _, v := range s { 76 p.content = append(p.content, textBlock(v)) 77 } 78 } 79 80 func (p *dynamicPage) addPreView(f func(*Queue)) { 81 p.preViewFunc = f 82 } 83 84 type page struct { 85 dynamicPage 86 } 87 88 func newPage(key string, content []component) page { 89 p := page{} 90 p.key = key 91 p.content = content 92 p.showProgress = true 93 return p 94 } 95 96 func (p page) Init() tea.Cmd { 97 return p.preProcessor 98 } 99 100 func (p page) View() string { 101 if p.preViewFunc != nil { 102 p.preViewFunc(p.queue) 103 } 104 doc := strings.Builder{} 105 doc.WriteString(p.queue.header.render()) 106 if p.showProgress { 107 doc.WriteString(drawProgress(p.queue.calcPercent())) 108 doc.WriteString("\n\n") 109 } 110 111 for _, v := range p.content { 112 doc.WriteString(bodyStyle.Render(v.render())) 113 doc.WriteString("\n") 114 } 115 116 doc.WriteString("\n") 117 doc.WriteString(bodyStyle.Render(promptStyle.Render(" Press the Enter Key to continue "))) 118 119 test := docStyle.Render(doc.String()) 120 121 return test 122 } 123 124 // TODO: a test for this is pretty straight forward 125 func (p page) Update(msg tea.Msg) (tea.Model, tea.Cmd) { 126 switch msg.(type) { 127 case successMsg: 128 return p.queue.next() 129 case tea.KeyMsg: 130 switch msg.(tea.KeyMsg).String() { 131 132 case "alt+b", "ctrl+b": 133 return p.queue.prev() 134 case "ctrl+c", "q": 135 if p.queue.Get("halted") != nil { 136 os.Exit(1) 137 } 138 return p.queue.exitPage() 139 case "enter": 140 if p.postProcessor != nil { 141 if p.state != "querying" { 142 p.state = "querying" 143 p.err = nil 144 return p, p.postProcessor(p.value, p.queue) 145 } 146 147 return p, nil 148 } 149 150 return p.queue.next() 151 } 152 153 } 154 return p, nil 155 }