Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7c238f1

Browse files
presleypf0ssel
andauthored
feat: paginate workspaces page (#4647)
* Start - still needs api call changes* Some xservice changes* Finish adding count to xservice* Mock out api call on frontend* Handle errors* Doctor getWorkspaces* Add types, start writing count function* Hook up route* Use empty page struct* Write interface and database fake* SQL query* Fix params type* Missed a spot* Space after alert banner* Fix model queries* Unpack query correctly* Fix filter-page interaction* Make mobile friendly* Format* Test backend* Fix key* Delete unnecessary conditional* Add test helpers* Use limit constant* Show widget with no count* Add test* Format* make gen from garretts workspace idk why* fix authorize test'* Hide widget with 0 records* Fix tests* Format* Fix types generated* Fix story* Add alert banner story* Format* Fix import* Format* Try removing story* Revert "Fix story"This reverts commitc06765b.* Add counts to page view story* Revert "Try removing story"This reverts commit476019b.Co-authored-by: Garrett <garrett@coder.com>
1 parent423ac04 commit7c238f1

File tree

24 files changed

+1073
-186
lines changed

24 files changed

+1073
-186
lines changed

‎coderd/coderd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@ func New(options *Options) *API {
503503
apiKeyMiddleware,
504504
)
505505
r.Get("/",api.workspaces)
506+
r.Get("/count",api.workspaceCount)
506507
r.Route("/{workspace}",func(r chi.Router) {
507508
r.Use(
508509
httpmw.ExtractWorkspaceParam(options.Database),

‎coderd/coderdtest/authorize.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,8 @@ func AGPLRoutes(a *AuthTester) (map[string]string, map[string]RouteCheck) {
243243
"POST:/api/v2/organizations/{organization}/templateversions": {StatusCode:http.StatusBadRequest,NoAuthorize:true},
244244

245245
// Endpoints that use the SQLQuery filter.
246-
"GET:/api/v2/workspaces/": {StatusCode:http.StatusOK,NoAuthorize:true},
246+
"GET:/api/v2/workspaces/": {StatusCode:http.StatusOK,NoAuthorize:true},
247+
"GET:/api/v2/workspaces/count": {StatusCode:http.StatusOK,NoAuthorize:true},
247248
}
248249

249250
// Routes like proxy routes support all HTTP methods. A helper func to expand

‎coderd/database/databasefake/databasefake.go

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,156 @@ func (q *fakeQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg database.
788788
returnworkspaces,nil
789789
}
790790

791+
func (q*fakeQuerier)GetWorkspaceCount(ctx context.Context,arg database.GetWorkspaceCountParams) (int64,error) {
792+
count,err:=q.GetAuthorizedWorkspaceCount(ctx,arg,nil)
793+
returncount,err
794+
}
795+
796+
//nolint:gocyclo
797+
func (q*fakeQuerier)GetAuthorizedWorkspaceCount(ctx context.Context,arg database.GetWorkspaceCountParams,authorizedFilter rbac.AuthorizeFilter) (int64,error) {
798+
q.mutex.RLock()
799+
deferq.mutex.RUnlock()
800+
801+
workspaces:=make([]database.Workspace,0)
802+
for_,workspace:=rangeq.workspaces {
803+
ifarg.OwnerID!=uuid.Nil&&workspace.OwnerID!=arg.OwnerID {
804+
continue
805+
}
806+
807+
ifarg.OwnerUsername!="" {
808+
owner,err:=q.GetUserByID(ctx,workspace.OwnerID)
809+
iferr==nil&&!strings.EqualFold(arg.OwnerUsername,owner.Username) {
810+
continue
811+
}
812+
}
813+
814+
ifarg.TemplateName!="" {
815+
template,err:=q.GetTemplateByID(ctx,workspace.TemplateID)
816+
iferr==nil&&!strings.EqualFold(arg.TemplateName,template.Name) {
817+
continue
818+
}
819+
}
820+
821+
if!arg.Deleted&&workspace.Deleted {
822+
continue
823+
}
824+
825+
ifarg.Name!=""&&!strings.Contains(strings.ToLower(workspace.Name),strings.ToLower(arg.Name)) {
826+
continue
827+
}
828+
829+
ifarg.Status!="" {
830+
build,err:=q.GetLatestWorkspaceBuildByWorkspaceID(ctx,workspace.ID)
831+
iferr!=nil {
832+
return0,xerrors.Errorf("get latest build: %w",err)
833+
}
834+
835+
job,err:=q.GetProvisionerJobByID(ctx,build.JobID)
836+
iferr!=nil {
837+
return0,xerrors.Errorf("get provisioner job: %w",err)
838+
}
839+
840+
switcharg.Status {
841+
case"pending":
842+
if!job.StartedAt.Valid {
843+
continue
844+
}
845+
846+
case"starting":
847+
if!job.StartedAt.Valid&&
848+
!job.CanceledAt.Valid&&
849+
job.CompletedAt.Valid&&
850+
time.Since(job.UpdatedAt)>30*time.Second||
851+
build.Transition!=database.WorkspaceTransitionStart {
852+
continue
853+
}
854+
855+
case"running":
856+
if!job.CompletedAt.Valid&&
857+
job.CanceledAt.Valid&&
858+
job.Error.Valid||
859+
build.Transition!=database.WorkspaceTransitionStart {
860+
continue
861+
}
862+
863+
case"stopping":
864+
if!job.StartedAt.Valid&&
865+
!job.CanceledAt.Valid&&
866+
job.CompletedAt.Valid&&
867+
time.Since(job.UpdatedAt)>30*time.Second||
868+
build.Transition!=database.WorkspaceTransitionStop {
869+
continue
870+
}
871+
872+
case"stopped":
873+
if!job.CompletedAt.Valid&&
874+
job.CanceledAt.Valid&&
875+
job.Error.Valid||
876+
build.Transition!=database.WorkspaceTransitionStop {
877+
continue
878+
}
879+
880+
case"failed":
881+
if (!job.CanceledAt.Valid&&!job.Error.Valid)||
882+
(!job.CompletedAt.Valid&&!job.Error.Valid) {
883+
continue
884+
}
885+
886+
case"canceling":
887+
if!job.CanceledAt.Valid&&job.CompletedAt.Valid {
888+
continue
889+
}
890+
891+
case"canceled":
892+
if!job.CanceledAt.Valid&&!job.CompletedAt.Valid {
893+
continue
894+
}
895+
896+
case"deleted":
897+
if!job.StartedAt.Valid&&
898+
job.CanceledAt.Valid&&
899+
!job.CompletedAt.Valid&&
900+
time.Since(job.UpdatedAt)>30*time.Second||
901+
build.Transition!=database.WorkspaceTransitionDelete {
902+
continue
903+
}
904+
905+
case"deleting":
906+
if!job.CompletedAt.Valid&&
907+
job.CanceledAt.Valid&&
908+
job.Error.Valid&&
909+
build.Transition!=database.WorkspaceTransitionDelete {
910+
continue
911+
}
912+
913+
default:
914+
return0,xerrors.Errorf("unknown workspace status in filter: %q",arg.Status)
915+
}
916+
}
917+
918+
iflen(arg.TemplateIds)>0 {
919+
match:=false
920+
for_,id:=rangearg.TemplateIds {
921+
ifworkspace.TemplateID==id {
922+
match=true
923+
break
924+
}
925+
}
926+
if!match {
927+
continue
928+
}
929+
}
930+
931+
// If the filter exists, ensure the object is authorized.
932+
ifauthorizedFilter!=nil&&!authorizedFilter.Eval(workspace.RBACObject()) {
933+
continue
934+
}
935+
workspaces=append(workspaces,workspace)
936+
}
937+
938+
returnint64(len(workspaces)),nil
939+
}
940+
791941
func (q*fakeQuerier)GetWorkspaceByID(_ context.Context,id uuid.UUID) (database.Workspace,error) {
792942
q.mutex.RLock()
793943
deferq.mutex.RUnlock()

‎coderd/database/modelqueries.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ func (q *sqlQuerier) GetTemplateGroupRoles(ctx context.Context, id uuid.UUID) ([
112112

113113
typeworkspaceQuerierinterface {
114114
GetAuthorizedWorkspaces(ctx context.Context,argGetWorkspacesParams,authorizedFilter rbac.AuthorizeFilter) ([]Workspace,error)
115+
GetAuthorizedWorkspaceCount(ctx context.Context,argGetWorkspaceCountParams,authorizedFilter rbac.AuthorizeFilter) (int64,error)
115116
}
116117

117118
// GetAuthorizedWorkspaces returns all workspaces that the user is authorized to access.
@@ -166,3 +167,23 @@ func (q *sqlQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg GetWorkspa
166167
}
167168
returnitems,nil
168169
}
170+
171+
func (q*sqlQuerier)GetAuthorizedWorkspaceCount(ctx context.Context,argGetWorkspaceCountParams,authorizedFilter rbac.AuthorizeFilter) (int64,error) {
172+
// In order to properly use ORDER BY, OFFSET, and LIMIT, we need to inject the
173+
// authorizedFilter between the end of the where clause and those statements.
174+
filter:=strings.Replace(getWorkspaceCount,"-- @authorize_filter",fmt.Sprintf(" AND %s",authorizedFilter.SQLString(rbac.NoACLConfig())),1)
175+
// The name comment is for metric tracking
176+
query:=fmt.Sprintf("-- name: GetAuthorizedWorkspaceCount :one\n%s",filter)
177+
row:=q.db.QueryRowContext(ctx,query,
178+
arg.Deleted,
179+
arg.Status,
180+
arg.OwnerID,
181+
arg.OwnerUsername,
182+
arg.TemplateName,
183+
pq.Array(arg.TemplateIds),
184+
arg.Name,
185+
)
186+
varcountint64
187+
err:=row.Scan(&count)
188+
returncount,err
189+
}

‎coderd/database/querier.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/queries.sql.go

Lines changed: 154 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp