github.com/oam-dev/kubevela@v1.9.11/references/cli/top/view/resource_view.go (about)

     1  /*
     2  Copyright 2022 The KubeVela Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package view
    18  
    19  import (
    20  	"context"
    21  	"time"
    22  
    23  	"github.com/gdamore/tcell/v2"
    24  	"github.com/rivo/tview"
    25  
    26  	"github.com/oam-dev/kubevela/references/cli/top/component"
    27  	"github.com/oam-dev/kubevela/references/cli/top/model"
    28  )
    29  
    30  const (
    31  	// RefreshDelay is refresh delay
    32  	RefreshDelay       = 10
    33  	resourceReqTimeout = 3
    34  )
    35  
    36  // ResourceView is the interface to abstract resource view
    37  type ResourceView interface {
    38  	model.View
    39  	InitView(ctx context.Context, app *App)
    40  	Refresh(event *tcell.EventKey) *tcell.EventKey
    41  	Update(timeoutCancel func())
    42  	BuildHeader()
    43  	BuildBody()
    44  }
    45  
    46  // ResourceViewMap is a map from resource name to resource view
    47  var ResourceViewMap = map[string]ResourceView{
    48  	"app":       new(ApplicationView),
    49  	"cluster":   new(ClusterView),
    50  	"resource":  new(ManagedResourceView),
    51  	"ns":        new(NamespaceView),
    52  	"cns":       new(ClusterNamespaceView),
    53  	"pod":       new(PodView),
    54  	"container": new(ContainerView),
    55  }
    56  
    57  // CommonResourceView is an abstract of resource view
    58  type CommonResourceView struct {
    59  	*component.Table
    60  	app        *App
    61  	cancelFunc func()
    62  }
    63  
    64  // NewCommonView return a new common view
    65  func NewCommonView(app *App) *CommonResourceView {
    66  	resourceView := &CommonResourceView{
    67  		Table:      component.NewTable(app.config.Theme),
    68  		app:        app,
    69  		cancelFunc: func() {},
    70  	}
    71  	return resourceView
    72  }
    73  
    74  // Init the common resource view
    75  func (v *CommonResourceView) Init() {
    76  	v.Table.Init()
    77  	v.SetBorder(true)
    78  	v.SetTitleColor(v.app.config.Theme.Table.Title.Color())
    79  	v.SetSelectable(true, false)
    80  	v.bindKeys()
    81  	v.app.SetFocus(v)
    82  }
    83  
    84  // Name return the name of common view
    85  func (v *CommonResourceView) Name() string {
    86  	return "Resource"
    87  }
    88  
    89  // BuildHeader render the header of table
    90  func (v *CommonResourceView) BuildHeader(header []string) {
    91  	for i := 0; i < len(header); i++ {
    92  		c := tview.NewTableCell(header[i])
    93  		c.SetTextColor(v.app.config.Theme.Table.Header.Color())
    94  		c.SetExpansion(3)
    95  		v.SetCell(0, i, c)
    96  	}
    97  }
    98  
    99  // BuildBody render the body of table
   100  func (v *CommonResourceView) BuildBody(body [][]string) {
   101  	rowNum := len(body)
   102  	for i := 0; i < rowNum; i++ {
   103  		columnNum := len(body[i])
   104  		for j := 0; j < columnNum; j++ {
   105  			c := tview.NewTableCell(body[i][j])
   106  			c.SetTextColor(v.app.config.Theme.Table.Body.Color())
   107  			c.SetExpansion(3)
   108  			v.SetCell(i+1, j, c)
   109  		}
   110  	}
   111  }
   112  
   113  // Stop the refresh goroutine and clear the table content
   114  func (v *CommonResourceView) Stop() {
   115  	v.Table.Stop()
   116  	v.cancelFunc()
   117  }
   118  
   119  // Refresh the base resource view
   120  func (v *CommonResourceView) Refresh(clear bool, update func(timeoutCancel func())) {
   121  	if clear {
   122  		v.Clear()
   123  	}
   124  	updateWithTimeout := func() {
   125  		ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*resourceReqTimeout)
   126  		defer cancelFunc()
   127  		go update(cancelFunc)
   128  
   129  		select {
   130  		case <-time.After(time.Second * resourceReqTimeout): // timeout
   131  		case <-ctx.Done(): // success
   132  		}
   133  	}
   134  
   135  	v.app.QueueUpdateDraw(updateWithTimeout)
   136  }
   137  
   138  // AutoRefresh will refresh the view in every RefreshDelay delay
   139  func (v *CommonResourceView) AutoRefresh(update func(timeoutCancel func())) {
   140  	var ctx context.Context
   141  	ctx, v.cancelFunc = context.WithCancel(context.Background())
   142  	go func() {
   143  		for {
   144  			time.Sleep(RefreshDelay * time.Second)
   145  			select {
   146  			case <-ctx.Done():
   147  				return
   148  			default:
   149  				v.Refresh(true, update)
   150  			}
   151  		}
   152  	}()
   153  }
   154  
   155  func (v *CommonResourceView) bindKeys() {
   156  	v.Actions().Delete([]tcell.Key{tcell.KeyESC})
   157  	v.Actions().Add(model.KeyActions{
   158  		component.KeyQ:    model.KeyAction{Description: "Back", Action: v.app.Back, Visible: true, Shared: true},
   159  		component.KeyHelp: model.KeyAction{Description: "Help", Action: v.app.helpView, Visible: true, Shared: true},
   160  		tcell.KeyCtrlT:    model.KeyAction{Description: "Switch Theme", Action: v.app.SwitchTheme, Visible: true, Shared: true},
   161  	})
   162  }