package handler import ( "strings" "sync" "github.com/jumpserver/koko/pkg/model" ) type DatabasePaginator interface { Paginator RetrievePageData(pageIndex int) []model.Database SearchAsset(key string) []model.Database SearchAgain(key string) []model.Database Name() string SearchKeys() []string } func NewLocalDatabasePaginator(data [] model.Database, pageSize int) DatabasePaginator { p := localDatabasePaginator{ allData: data, currentData: data, pageSize: pageSize, currentOffset: 0, currentPage: 1, search: make([]string, 0, 4), lock: new(sync.RWMutex), } return &p } type localDatabasePaginator struct { allData []model.Database currentData []model.Database currentPage int pageSize int totalPage int currentOffset int search []string lock *sync.RWMutex currentResult []model.Database } func (l *localDatabasePaginator) Name() string { return "local" } func (l *localDatabasePaginator) SearchKeys() []string { return l.search } func (l *localDatabasePaginator) HasPrev() bool { l.lock.RLock() defer l.lock.RUnlock() return l.currentPage > 1 } func (l *localDatabasePaginator) HasNext() bool { l.lock.RLock() defer l.lock.RUnlock() return l.currentPage < l.totalPage } func (l *localDatabasePaginator) CurrentPage() int { l.lock.RLock() defer l.lock.RUnlock() return l.currentPage } func (l *localDatabasePaginator) TotalCount() int { l.lock.RLock() defer l.lock.RUnlock() return len(l.currentData) } func (l *localDatabasePaginator) TotalPage() int { l.lock.RLock() defer l.lock.RUnlock() return l.totalPage } func (l *localDatabasePaginator) PageSize() int { l.lock.RLock() defer l.lock.RUnlock() return l.pageSize } func (l *localDatabasePaginator) SetPageSize(size int) { if size <= 0 { size = len(l.currentData) } l.lock.Lock() defer l.lock.Unlock() if l.pageSize == size { return } l.pageSize = size } func (l *localDatabasePaginator) RetrievePageData(pageIndex int) []model.Database { l.lock.Lock() defer l.lock.Unlock() return l.retrievePageData(pageIndex) } func (l *localDatabasePaginator) SearchAsset(key string) []model.Database { l.lock.Lock() defer l.lock.Unlock() l.search = l.search[:0] l.search = append(l.search, key) l.currentData = searchFromLocalDBs(l.allData, key) l.currentPage = 1 l.currentOffset = 0 return l.retrievePageData(1) } func (l *localDatabasePaginator) SearchAgain(key string) []model.Database { l.lock.Lock() defer l.lock.Unlock() l.currentData = searchFromLocalDBs(l.currentData, key) l.search = append(l.search, key) l.currentPage = 1 l.currentOffset = 0 return l.retrievePageData(1) } func (l *localDatabasePaginator) retrievePageData(pageIndex int) []model.Database { offsetPage := pageIndex - l.currentPage totalOffset := offsetPage * l.pageSize l.currentOffset += totalOffset switch { case l.currentOffset <= 0: l.currentOffset = 0 case l.currentOffset >= len(l.currentData): l.currentOffset = len(l.currentData) case l.pageSize >= len(l.currentData): l.currentOffset = 0 } end := l.currentOffset + l.pageSize if end >= len(l.currentData) { end = len(l.currentData) } l.currentResult = l.currentData[l.currentOffset:end] l.updatePageInfo() return l.currentResult } func (l *localDatabasePaginator) updatePageInfo() { pageSize := l.pageSize totalCount := len(l.currentData) switch totalCount % pageSize { case 0: l.totalPage = totalCount / pageSize default: l.totalPage = (totalCount / pageSize) + 1 } offset := l.currentOffset + len(l.currentResult) switch offset % pageSize { case 0: l.currentPage = offset / pageSize default: l.currentPage = (offset / pageSize) + 1 } } func searchFromLocalDBs(dbs []model.Database, key string) []model.Database { displayDBs := make([]model.Database, 0, len(dbs)) key = strings.ToLower(key) for _, db := range dbs { contents := []string{strings.ToLower(db.Name),strings.ToLower(db.DBName), strings.ToLower(db.Host), strings.ToLower(db.Comment)} if isSubstring(contents, key) { displayDBs = append(displayDBs, db) } } return displayDBs }