diff --git a/internal/daemon/daemon.go b/internal/daemon/daemon.go index 5866f6cda..e60aac1af 100644 --- a/internal/daemon/daemon.go +++ b/internal/daemon/daemon.go @@ -401,6 +401,7 @@ func New(ctx context.Context, logger logr.Logger, cfg Config) (*Daemon, error) { Runners: runnerService, GithubApp: githubAppService, EngineService: engineService, + Configs: configService, HostnameService: hostnameService, Tokens: tokensService, Authorizer: authorizer, diff --git a/internal/http/html/components/layout.templ b/internal/http/html/components/layout.templ index c316b6452..a3db3df7f 100644 --- a/internal/http/html/components/layout.templ +++ b/internal/http/html/components/layout.templ @@ -111,10 +111,11 @@ templ BareLayout(props BareLayoutProps) { + - +
@navbar(props.Organization)
diff --git a/internal/http/html/components/layout_templ.go b/internal/http/html/components/layout_templ.go index a8e95fcce..07f96c41c 100644 --- a/internal/http/html/components/layout_templ.go +++ b/internal/http/html/components/layout_templ.go @@ -342,14 +342,14 @@ func BareLayout(props BareLayoutProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\">") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/internal/http/html/components/websocket.go b/internal/http/html/components/websocket.go deleted file mode 100644 index 40ea5b558..000000000 --- a/internal/http/html/components/websocket.go +++ /dev/null @@ -1,122 +0,0 @@ -package components - -import ( - "context" - "errors" - "fmt" - "net" - "net/http" - "net/url" - "strings" - - "github.com/a-h/templ" - "github.com/go-logr/logr" - "github.com/gorilla/websocket" - "github.com/leg100/otf/internal/http/html" - "github.com/leg100/otf/internal/resource" -) - -var upgrader = websocket.Upgrader{ - ReadBufferSize: 1024, - WriteBufferSize: 1024, -} - -// Websocket is an inbound websocket connection, on which snippets of HTML are -// sent from the server to the client. -type Websocket[Resource any] struct { - *websocket.Conn - r *http.Request - client websocketClient[Resource] - component func(Resource) templ.Component - logger logr.Logger -} - -type websocketClient[Resource any] interface { - Get(ctx context.Context, id resource.TfeID) (Resource, error) -} - -func NewWebsocket[Resource any]( - logger logr.Logger, - w http.ResponseWriter, - r *http.Request, - client websocketClient[Resource], - component func(Resource) templ.Component, -) (*Websocket[Resource], error) { - conn, err := upgrader.Upgrade(w, r, nil) - if err != nil { - return nil, err - } - return &Websocket[Resource]{ - Conn: conn, - client: client, - component: component, - r: r, - logger: logger, - }, nil -} - -// Send an HTML fragment to the client rendered from a template populated with a -// resource corresponding to the given id. True is returned if it succeeded, -// otherwise it returns false, in which case the connection should be closed. -func (s *Websocket[Resource]) Send(id resource.TfeID) bool { - if err := s.doSend(id); err != nil { - // Ignore errors to do with the client closing the connection. - var opError *net.OpError - if !errors.As(err, &opError) { - s.logger.Error(err, "sending websocket message", "resource_id", id) - } - return false - } - return true -} - -func (s *Websocket[Resource]) doSend(id resource.TfeID) error { - resource, err := s.client.Get(s.r.Context(), id) - if err != nil { - return fmt.Errorf("fetching resource: %w", err) - } - - w, err := s.NextWriter(websocket.TextMessage) - if err != nil { - return err - } - defer w.Close() - - if err := html.RenderSnippet(s.component(resource), w, s.r); err != nil { - return fmt.Errorf("rendering html: %w", err) - } - return nil -} - -// SetAllowedOrigins sets the allowed origins for inbound websocket connections. -// If origins is empty, all origins are allowed. Otherwise origins is expected -// to be a comma separated list of origins and if the origin on an inbound -// websocket connection does not match one of those origins then the connection -// is rejected. -func SetAllowedOrigins(origins string) { - if len(origins) == 0 { - return - } - sl := strings.Split(strings.ToLower(origins), ",") - sm := map[string]bool{} - for _, o := range sl { - o = strings.TrimPrefix(o, "https://") - o = strings.TrimPrefix(o, "http://") - sm[o] = true - } - if len(sm) > 0 { - upgrader.CheckOrigin = func(r *http.Request) bool { - origins := r.Header["Origin"] - if len(origins) == 0 { - return true - } - u, err := url.Parse(origins[0]) - if err != nil { - return false - } - origin := strings.ToLower(u.Host) - _, ok := sm[origin] - return ok - } - } -} diff --git a/internal/http/html/components/websocket_list_handler.go b/internal/http/html/components/websocket_list_handler.go deleted file mode 100644 index 4fa765692..000000000 --- a/internal/http/html/components/websocket_list_handler.go +++ /dev/null @@ -1,162 +0,0 @@ -package components - -import ( - "context" - "errors" - "fmt" - "net/http" - "net/url" - "sync" - "time" - - "github.com/go-logr/logr" - "github.com/gorilla/websocket" - "github.com/leg100/otf/internal/http/decode" - "github.com/leg100/otf/internal/http/html" - "github.com/leg100/otf/internal/pubsub" - "github.com/leg100/otf/internal/resource" - "golang.org/x/sync/errgroup" -) - -// WebsocketListHandler handles dynamically updating lists of resources via -// a websocket. -type WebsocketListHandler[Resource, ResourceEvent, Options any] struct { - logr.Logger - Client websocketListHandlerClient[Resource, ResourceEvent, Options] - Populator TablePopulator[Resource] - ID string -} - -type websocketListHandlerClient[Resource, ResourceEvent, Options any] interface { - Watch(ctx context.Context) (<-chan pubsub.Event[ResourceEvent], func()) - List(ctx context.Context, opts Options) (*resource.Page[Resource], error) -} - -func (h *WebsocketListHandler[Resource, ResourceEvent, Options]) Handler(w http.ResponseWriter, r *http.Request) { - var opts Options - if err := decode.All(&opts, r); err != nil { - html.Error(r, w, err.Error(), html.WithStatus(http.StatusUnprocessableEntity)) - return - } - - conn, err := upgrader.Upgrade(w, r, nil) - if err != nil { - h.Error(err, "upgrading websocket connection") - return - } - defer conn.Close() - - sub, unsub := h.Client.Watch(r.Context()) - defer unsub() - - // Mutex serializes go routine access to the list options and to the - // websocket writer. - var mu sync.Mutex - - sendList := func() error { - mu.Lock() - defer mu.Unlock() - - page, err := h.Client.List(r.Context(), opts) - if err != nil { - return fmt.Errorf("fetching list of resources: %w", err) - } - - w, err := conn.NextWriter(websocket.TextMessage) - if err != nil { - return err - } - defer w.Close() - - comp := Table(h.Populator, page, h.ID) - if err := html.RenderSnippet(comp, w, r); err != nil { - return fmt.Errorf("rendering html: %w", err) - } - return nil - } - - // Send an initial list to client on startup. - if err := sendList(); err != nil { - h.Error(err, "handling websocket connection") - return - } - - // Two go-routines: - // 1) Watch server events and upon receiving an event send a new list to the - // client. This is necesary because the event can be a notification that a - // resource has been created, updated or deleted, any of which alters the - // list of resources on the client. - // 2) Receive messages from the client altering the list of resources to - // retrieve (e.g. next page, filtering by status, etc), and send new list to - // the client. - g, ctx := errgroup.WithContext(r.Context()) - g.Go(func() error { - // To avoid overwhelming the client, do not send a list more than once a - // second. - for { - // Block on receiving an event. - select { - case _, ok := <-sub: - if !ok { - return nil - } - case <-ctx.Done(): - return nil - } - // Then consume any remaining events. - for { - select { - case _, ok := <-sub: - if !ok { - goto done - } - default: - goto done - } - } - done: - // Send list to client - if err := sendList(); err != nil { - return err - } - // Wait a second before sending anything more to client. - select { - case <-time.After(time.Second): - case <-ctx.Done(): - return nil - } - } - }) - g.Go(func() error { - for { - _, p, err := conn.ReadMessage() - if err != nil { - return fmt.Errorf("reading websocket message: %w", err) - } - - values, err := url.ParseQuery(string(p)) - if err != nil { - return fmt.Errorf("parsing query: %w", err) - } - - // Serialize access to opts, which is read by the other go - // routine. - mu.Lock() - if err := decode.Decode(&opts, values); err != nil { - return fmt.Errorf("decoding query: %w", err) - } - mu.Unlock() - - if err := sendList(); err != nil { - return err - } - } - }) - if err := g.Wait(); err != nil { - // Don't log errors resulting from the client closing the connection. - closeError := &websocket.CloseError{} - if !errors.As(err, &closeError) { - h.Error(err, "terminated websocket connection") - } - } -} diff --git a/internal/http/html/paths/funcmap.go b/internal/http/html/paths/funcmap.go index 2e3896203..1a57fc522 100644 --- a/internal/http/html/paths/funcmap.go +++ b/internal/http/html/paths/funcmap.go @@ -82,7 +82,6 @@ func init() { funcmap["forceCancelRunPath"] = ForceCancelRun funcmap["retryRunPath"] = RetryRun funcmap["tailRunPath"] = TailRun - funcmap["widgetRunPath"] = WidgetRun funcmap["watchRunPath"] = WatchRun funcmap["watchLatestRunPath"] = WatchLatestRun diff --git a/internal/http/html/paths/paths.yaml b/internal/http/html/paths/paths.yaml index c4f848c66..f7293c528 100644 --- a/internal/http/html/paths/paths.yaml +++ b/internal/http/html/paths/paths.yaml @@ -42,7 +42,6 @@ - name: force-cancel - name: retry - name: tail - - name: widget - name: watch - name: watch-latest collection: true diff --git a/internal/http/html/paths/run_paths.go b/internal/http/html/paths/run_paths.go index 8b9cd1fe7..191a24193 100644 --- a/internal/http/html/paths/run_paths.go +++ b/internal/http/html/paths/run_paths.go @@ -56,10 +56,6 @@ func TailRun(run fmt.Stringer) string { return fmt.Sprintf("/app/runs/%s/tail", run) } -func WidgetRun(run fmt.Stringer) string { - return fmt.Sprintf("/app/runs/%s/widget", run) -} - func WatchRun(run fmt.Stringer) string { return fmt.Sprintf("/app/runs/%s/watch", run) } diff --git a/internal/http/html/render.go b/internal/http/html/render.go index a6669b203..cad21e278 100644 --- a/internal/http/html/render.go +++ b/internal/http/html/render.go @@ -16,12 +16,18 @@ func Render(c templ.Component, w http.ResponseWriter, r *http.Request) { // add response to context for templates to access ctx = context.WithValue(ctx, responseKey{}, w) // handle errors - errHandler := templ.WithErrorHandler(func(r *http.Request, err error) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - Error(r, w, err.Error()) - }) - }) - templ.Handler(c, errHandler).ServeHTTP(w, r.WithContext(ctx)) + opts := []func(*templ.ComponentHandler){ + templ.WithErrorHandler(func(r *http.Request, err error) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + Error(r, w, err.Error()) + }) + }), + } + // render only a fragment if ajax request. + if r.Header.Get("HX-Target") != "" { + opts = append(opts, templ.WithFragments(r.Header.Get("Hx-Target"))) + } + templ.Handler(c, opts...).ServeHTTP(w, r.WithContext(ctx)) } func RenderSnippet(c templ.Component, w io.Writer, r *http.Request) error { diff --git a/internal/http/server.go b/internal/http/server.go index 18b483b5c..fa115d419 100644 --- a/internal/http/server.go +++ b/internal/http/server.go @@ -16,7 +16,6 @@ import ( "github.com/go-logr/logr" "github.com/leg100/otf/internal" "github.com/leg100/otf/internal/http/html" - "github.com/leg100/otf/internal/http/html/components" "github.com/leg100/otf/internal/http/html/paths" "github.com/leg100/otf/internal/json" ) @@ -137,8 +136,6 @@ func NewServer(logger logr.Logger, cfg ServerConfig) (*Server, error) { prefix: paths.UIPrefix, }).middleware) - components.SetAllowedOrigins(cfg.AllowedOrigins) - return &Server{ Logger: logger, ServerConfig: cfg, diff --git a/internal/integration/organization_ui_test.go b/internal/integration/organization_ui_test.go index cdc9c19b4..212de28bb 100644 --- a/internal/integration/organization_ui_test.go +++ b/internal/integration/organization_ui_test.go @@ -42,7 +42,7 @@ func TestIntegration_OrganizationUI(t *testing.T) { require.NoError(t, err) // there should be one organization listed - err = expect.Locator(page.Locator(`//*[@id='organization-table']//tbody/tr`)).ToHaveCount(1) + err = expect.Locator(page.Locator(`//table/tbody/tr`)).ToHaveCount(1) require.NoError(t, err) // go to organization diff --git a/internal/integration/pagination_ui_test.go b/internal/integration/pagination_ui_test.go index c4ab72a2b..0bcdaa75a 100644 --- a/internal/integration/pagination_ui_test.go +++ b/internal/integration/pagination_ui_test.go @@ -24,7 +24,7 @@ func TestIntegration_PaginationUI(t *testing.T) { require.NoError(t, err) // should be 20 orgs listed on page one - err = expect.Locator(page.Locator(`//*[@id='organization-table']//tbody/tr`)).ToHaveCount(20) + err = expect.Locator(page.Locator(`//table/tbody/tr`)).ToHaveCount(20) require.NoError(t, err) // expect accurate page info diff --git a/internal/run/db.go b/internal/run/db.go index 6bff05205..2565fe805 100644 --- a/internal/run/db.go +++ b/internal/run/db.go @@ -23,8 +23,7 @@ import ( // pgdb is a database of runs on postgres type pgdb struct { - *sql.DB // provides access to generated SQL queries - configService *configversion.Service + *sql.DB // provides access to generated SQL queries } // CreateRun persists a Run to the DB. @@ -842,7 +841,6 @@ func (db *pgdb) scan(row pgx.CollectableRow) (*Run, error) { AutoApply: m.AutoApply, PlanOnly: m.PlanOnly, Source: m.Source, - SourceIcon: db.configService.GetSourceIcon(m.Source), Status: m.Status, WorkspaceID: m.WorkspaceID, ConfigurationVersionID: m.ConfigurationVersionID, diff --git a/internal/run/factory.go b/internal/run/factory.go index 67747f781..2d98ac7e9 100644 --- a/internal/run/factory.go +++ b/internal/run/factory.go @@ -6,13 +6,11 @@ import ( "time" "github.com/a-h/templ" - "github.com/leg100/otf/internal" "github.com/leg100/otf/internal/configversion" "github.com/leg100/otf/internal/configversion/source" "github.com/leg100/otf/internal/engine" "github.com/leg100/otf/internal/organization" "github.com/leg100/otf/internal/resource" - "github.com/leg100/otf/internal/runstatus" "github.com/leg100/otf/internal/user" "github.com/leg100/otf/internal/vcs" "github.com/leg100/otf/internal/workspace" @@ -63,6 +61,7 @@ func (f *factory) NewRun(ctx context.Context, workspaceID resource.TfeID, opts C if err != nil { return nil, err } + opts.costEstimationEnabled = org.CostEstimationEnabled // retrieve or create config: if a config version ID is specified then // retrieve that; otherwise if the workspace is connected then the latest @@ -80,68 +79,21 @@ func (f *factory) NewRun(ctx context.Context, workspaceID resource.TfeID, opts C return nil, fmt.Errorf("fetching configuration: %w", err) } - run := Run{ - ID: resource.NewTfeID(resource.RunKind), - CreatedAt: internal.CurrentTimestamp(opts.now), - Refresh: defaultRefresh, - Organization: ws.Organization, - ConfigurationVersionID: cv.ID, - WorkspaceID: ws.ID, - PlanOnly: cv.Speculative, - ReplaceAddrs: opts.ReplaceAddrs, - TargetAddrs: opts.TargetAddrs, - ExecutionMode: ws.ExecutionMode, - AutoApply: ws.AutoApply, - IngressAttributes: cv.IngressAttributes, - CostEstimationEnabled: org.CostEstimationEnabled, - Source: opts.Source, - Engine: ws.Engine, - Variables: opts.Variables, - } // If workspace tracks the latest version then fetch it from db. if ws.EngineVersion.Latest { - run.EngineVersion, _, err = f.releases.GetLatest(ctx, ws.Engine) + opts.EngineVersion, _, err = f.releases.GetLatest(ctx, ws.Engine) if err != nil { return nil, err } } else { - run.EngineVersion = ws.EngineVersion.String() - } - - run.Plan = newPhase(run.ID, PlanPhase) - run.Apply = newPhase(run.ID, ApplyPhase) - run.updateStatus(runstatus.Pending, opts.now) - - if run.Source == "" { - run.Source = source.API + opts.EngineVersion = ws.EngineVersion.String() } - run.SourceIcon = f.configs.GetSourceIcon(run.Source) - if opts.TerraformVersion != nil { - run.EngineVersion = *opts.TerraformVersion - } - if opts.AllowEmptyApply != nil { - run.AllowEmptyApply = *opts.AllowEmptyApply - } if creator, _ := user.UserFromContext(ctx); creator != nil { - run.CreatedBy = &creator.Username + opts.CreatedBy = &creator.Username } - if opts.IsDestroy != nil { - run.IsDestroy = *opts.IsDestroy - } - if opts.Message != nil { - run.Message = *opts.Message - } - if opts.Refresh != nil { - run.Refresh = *opts.Refresh - } - if opts.AutoApply != nil { - run.AutoApply = *opts.AutoApply - } - if opts.PlanOnly != nil { - run.PlanOnly = *opts.PlanOnly - } - return &run, nil + + return NewRun(ws, cv, opts) } // createConfigVersionFromVCS creates a config version from the vcs repo diff --git a/internal/run/factory_test.go b/internal/run/factory_test.go index c4e2806d4..d9dcfb623 100644 --- a/internal/run/factory_test.go +++ b/internal/run/factory_test.go @@ -130,7 +130,7 @@ func TestFactory(t *testing.T) { assert.Equal(t, ws.ID, got.ConfigurationVersionID) }) - t.Run("get latest version", func(t *testing.T) { + t.Run("get latest engine version", func(t *testing.T) { f := newTestFactory( &organization.Organization{}, workspace.NewTestWorkspace(t, &workspace.CreateOptions{ diff --git a/internal/run/helpers_test.go b/internal/run/helpers_test.go index 588a4d7ce..d1979f26f 100644 --- a/internal/run/helpers_test.go +++ b/internal/run/helpers_test.go @@ -11,13 +11,17 @@ import ( "github.com/stretchr/testify/require" ) -func newTestRun(t *testing.T, ctx context.Context, opts CreateOptions) *Run { +func NewTestRun(t *testing.T, ctx context.Context, opts CreateOptions) *Run { org, err := organization.NewOrganization(organization.CreateOptions{Name: internal.Ptr("acme-corp")}) require.NoError(t, err) + ws := workspace.NewTestWorkspace(t, nil) cv := configversion.NewConfigurationVersion(ws.ID, configversion.CreateOptions{}) + factory := newTestFactory(org, ws, cv) + run, err := factory.NewRun(ctx, ws.ID, opts) require.NoError(t, err) + return run } diff --git a/internal/run/run.go b/internal/run/run.go index 350ee256b..9fc1c2544 100644 --- a/internal/run/run.go +++ b/internal/run/run.go @@ -7,7 +7,6 @@ import ( "fmt" "time" - "github.com/a-h/templ" "github.com/leg100/otf/internal" "github.com/leg100/otf/internal/configversion" "github.com/leg100/otf/internal/configversion/source" @@ -60,7 +59,6 @@ type ( AutoApply bool `jsonapi:"attribute" json:"auto_apply"` PlanOnly bool `jsonapi:"attribute" json:"plan_only"` Source source.Source `jsonapi:"attribute" json:"source"` - SourceIcon templ.Component `json:"-"` Status runstatus.Status `jsonapi:"attribute" json:"status"` WorkspaceID resource.TfeID `jsonapi:"attribute" json:"workspace_id"` ConfigurationVersionID resource.TfeID `jsonapi:"attribute" json:"configuration_version_id"` @@ -118,8 +116,12 @@ type ( // PlanOnly specifies if this is a speculative, plan-only run that // Terraform cannot apply. Takes precedence over whether the // configuration version is marked as speculative or not. - PlanOnly *bool - Variables []Variable + PlanOnly *bool + Variables []Variable + CreatedBy *user.Username + EngineVersion string + + costEstimationEnabled bool // testing purposes now *time.Time @@ -153,6 +155,64 @@ type ( } ) +func NewRun( + ws *workspace.Workspace, + cv *configversion.ConfigurationVersion, + opts CreateOptions, +) (*Run, error) { + run := Run{ + ID: resource.NewTfeID(resource.RunKind), + CreatedAt: internal.CurrentTimestamp(opts.now), + Refresh: defaultRefresh, + Organization: ws.Organization, + ConfigurationVersionID: cv.ID, + WorkspaceID: ws.ID, + PlanOnly: cv.Speculative, + ReplaceAddrs: opts.ReplaceAddrs, + TargetAddrs: opts.TargetAddrs, + ExecutionMode: ws.ExecutionMode, + AutoApply: ws.AutoApply, + IngressAttributes: cv.IngressAttributes, + Source: opts.Source, + Engine: ws.Engine, + EngineVersion: opts.EngineVersion, + Variables: opts.Variables, + CreatedBy: opts.CreatedBy, + CostEstimationEnabled: opts.costEstimationEnabled, + } + + run.Plan = newPhase(run.ID, PlanPhase) + run.Apply = newPhase(run.ID, ApplyPhase) + run.updateStatus(runstatus.Pending, opts.now) + + if run.Source == "" { + run.Source = source.API + } + + if opts.TerraformVersion != nil { + run.EngineVersion = *opts.TerraformVersion + } + if opts.AllowEmptyApply != nil { + run.AllowEmptyApply = *opts.AllowEmptyApply + } + if opts.IsDestroy != nil { + run.IsDestroy = *opts.IsDestroy + } + if opts.Message != nil { + run.Message = *opts.Message + } + if opts.Refresh != nil { + run.Refresh = *opts.Refresh + } + if opts.AutoApply != nil { + run.AutoApply = *opts.AutoApply + } + if opts.PlanOnly != nil { + run.PlanOnly = *opts.PlanOnly + } + return &run, nil +} + func (r *Run) Queued() bool { return runstatus.Queued(r.Status) } diff --git a/internal/run/run_test.go b/internal/run/run_test.go index 1eb59d818..26565dc06 100644 --- a/internal/run/run_test.go +++ b/internal/run/run_test.go @@ -17,7 +17,7 @@ func TestRun_New_CreatedBy(t *testing.T) { ctx := context.Background() user := user.NewTestUser(t) ctx = authz.AddSubjectToContext(ctx, user) - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) assert.NotNil(t, run.CreatedBy) assert.Equal(t, user.Username, *run.CreatedBy) } @@ -26,7 +26,7 @@ func TestRun_States(t *testing.T) { ctx := context.Background() t.Run("pending", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) require.Equal(t, runstatus.Pending, run.Status) require.Equal(t, PhasePending, run.Plan.Status) @@ -34,7 +34,7 @@ func TestRun_States(t *testing.T) { }) t.Run("enqueue plan", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) require.NoError(t, run.EnqueuePlan()) @@ -44,7 +44,7 @@ func TestRun_States(t *testing.T) { }) t.Run("start plan", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) run.Status = runstatus.PlanQueued require.NoError(t, run.Start()) @@ -55,7 +55,7 @@ func TestRun_States(t *testing.T) { }) t.Run("finish plan", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) run.Status = runstatus.Planning _, err := run.Finish(PlanPhase, PhaseFinishOptions{}) @@ -67,7 +67,7 @@ func TestRun_States(t *testing.T) { }) t.Run("finish plan with errors", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) run.Status = runstatus.Planning _, err := run.Finish(PlanPhase, PhaseFinishOptions{Errored: true}) @@ -79,7 +79,7 @@ func TestRun_States(t *testing.T) { }) t.Run("finish plan with resource changes", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) run.Status = runstatus.Planning run.Plan.ResourceReport = &Report{Additions: 1} @@ -93,7 +93,7 @@ func TestRun_States(t *testing.T) { }) t.Run("finish plan with output changes", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) run.Status = runstatus.Planning run.Plan.OutputReport = &Report{Additions: 1} @@ -107,7 +107,7 @@ func TestRun_States(t *testing.T) { }) t.Run("finish plan with changes on run with autoapply enabled", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{AutoApply: internal.Ptr(true)}) + run := NewTestRun(t, ctx, CreateOptions{AutoApply: internal.Ptr(true)}) run.Status = runstatus.Planning run.Plan.ResourceReport = &Report{Additions: 1} @@ -122,7 +122,7 @@ func TestRun_States(t *testing.T) { }) t.Run("finish plan with cost estimation enabled", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) run.CostEstimationEnabled = true run.Status = runstatus.Planning @@ -137,7 +137,7 @@ func TestRun_States(t *testing.T) { }) t.Run("enqueue apply", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) run.Status = runstatus.Planned require.NoError(t, run.EnqueueApply()) @@ -147,7 +147,7 @@ func TestRun_States(t *testing.T) { }) t.Run("start apply", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) run.Status = runstatus.ApplyQueued require.NoError(t, run.Start()) @@ -157,7 +157,7 @@ func TestRun_States(t *testing.T) { }) t.Run("finish apply", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) run.Status = runstatus.Applying _, err := run.Finish(ApplyPhase, PhaseFinishOptions{}) @@ -168,7 +168,7 @@ func TestRun_States(t *testing.T) { }) t.Run("finish apply with errors", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) run.Status = runstatus.Applying _, err := run.Finish(ApplyPhase, PhaseFinishOptions{Errored: true}) @@ -179,7 +179,7 @@ func TestRun_States(t *testing.T) { }) t.Run("cancel pending run", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) err := run.Cancel(true, false) require.NoError(t, err) // no signal should be sent @@ -189,7 +189,7 @@ func TestRun_States(t *testing.T) { }) t.Run("cancel planning run should indicate signal be sent", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) run.Status = runstatus.Planning err := run.Cancel(true, false) require.NoError(t, err) @@ -198,7 +198,7 @@ func TestRun_States(t *testing.T) { }) t.Run("when non-user cancels a planning run, it should be placed into canceled state", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) run.Status = runstatus.Planning err := run.Cancel(false, false) require.NoError(t, err) @@ -208,7 +208,7 @@ func TestRun_States(t *testing.T) { }) t.Run("user cannot cancel a run twice", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) run.Status = runstatus.Planning err := run.Cancel(true, false) require.NoError(t, err) @@ -217,14 +217,14 @@ func TestRun_States(t *testing.T) { }) t.Run("cannot force cancel a run when no previous attempt has been made to cancel run gracefully", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) run.Status = runstatus.Planning err := run.Cancel(true, true) assert.Equal(t, ErrRunForceCancelNotAllowed, err) }) t.Run("force cancel run when graceful cancel has already been attempted and cool off period has elapsed", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) run.Status = runstatus.Planning // gracefully canceled 11 seconds ago run.CancelSignaledAt = internal.Ptr(time.Now().Add(-11 * time.Second)) @@ -235,7 +235,7 @@ func TestRun_States(t *testing.T) { }) t.Run("non-user cannot force cancel a run", func(t *testing.T) { - run := newTestRun(t, ctx, CreateOptions{}) + run := NewTestRun(t, ctx, CreateOptions{}) run.Status = runstatus.Planning err := run.Cancel(false, true) assert.Equal(t, ErrRunForceCancelNotAllowed, err) @@ -249,7 +249,7 @@ func TestRun_StatusReport(t *testing.T) { return now.Add(time.Duration(seconds) * -time.Second) } createRun = func(created time.Time) *Run { - return newTestRun(t, t.Context(), CreateOptions{ + return NewTestRun(t, t.Context(), CreateOptions{ now: &created, }) } diff --git a/internal/run/service.go b/internal/run/service.go index f333b6029..e21524b94 100644 --- a/internal/run/service.go +++ b/internal/run/service.go @@ -71,7 +71,7 @@ type ( ) func NewService(opts Options) *Service { - db := &pgdb{opts.DB, opts.ConfigVersionService} + db := &pgdb{opts.DB} svc := Service{ Logger: opts.Logger, workspaces: opts.WorkspaceService, diff --git a/internal/ui/github_view.templ b/internal/ui/github_view.templ index 526a75ede..2d6e0ba40 100644 --- a/internal/ui/github_view.templ +++ b/internal/ui/github_view.templ @@ -62,7 +62,6 @@ templ getApps(props getAppsProps) { @components.UnpaginatedTable( &appTable{githubHostname: props.githubHostname, canDeleteApp: props.canDeleteApp}, []*github.App{props.app}, - "app-table", )

Installations

@@ -78,7 +77,6 @@ templ getApps(props getAppsProps) { @components.UnpaginatedTable( &installsTable{}, props.installations, - "installs-table", ) } else { diff --git a/internal/ui/github_view_templ.go b/internal/ui/github_view_templ.go index 91023f4a6..1063a16ed 100644 --- a/internal/ui/github_view_templ.go +++ b/internal/ui/github_view_templ.go @@ -145,7 +145,6 @@ func getApps(props getAppsProps) templ.Component { templ_7745c5c3_Err = components.UnpaginatedTable( &appTable{githubHostname: props.githubHostname, canDeleteApp: props.canDeleteApp}, []*github.App{props.app}, - "app-table", ).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err @@ -157,7 +156,7 @@ func getApps(props getAppsProps) templ.Component { var templ_7745c5c3_Var7 templ.SafeURL templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(props.app.NewInstallURL(props.githubHostname))) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 69, Col: 78} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 68, Col: 78} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { @@ -178,7 +177,6 @@ func getApps(props getAppsProps) templ.Component { templ_7745c5c3_Err = components.UnpaginatedTable( &installsTable{}, props.installations, - "installs-table", ).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err @@ -200,7 +198,7 @@ func getApps(props getAppsProps) templ.Component { var templ_7745c5c3_Var8 templ.SafeURL templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(paths.NewGithubApp()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 88, Col: 92} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 86, Col: 92} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { @@ -298,7 +296,7 @@ func (t appTable) Row(app *github.App) templ.Component { var templ_7745c5c3_Var11 templ.SafeURL templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(app.URL(t.githubHostname))) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 111, Col: 95} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 109, Col: 95} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { @@ -311,7 +309,7 @@ func (t appTable) Row(app *github.App) templ.Component { var templ_7745c5c3_Var12 string templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(app.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 112, Col: 24} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 110, Col: 24} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) if templ_7745c5c3_Err != nil { @@ -344,7 +342,7 @@ func (t appTable) Row(app *github.App) templ.Component { var templ_7745c5c3_Var14 string templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(int(app.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 119, Col: 18} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 117, Col: 18} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) if templ_7745c5c3_Err != nil { @@ -368,7 +366,7 @@ func (t appTable) Row(app *github.App) templ.Component { var templ_7745c5c3_Var15 templ.SafeURL templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinURLErrs(paths.DeleteGithubApp(app.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 125, Col: 48} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 123, Col: 48} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) if templ_7745c5c3_Err != nil { @@ -389,7 +387,7 @@ func (t appTable) Row(app *github.App) templ.Component { var templ_7745c5c3_Var16 string templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(int(app.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 127, Col: 55} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 125, Col: 55} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) if templ_7745c5c3_Err != nil { @@ -467,7 +465,7 @@ func (t installsTable) Row(install vcs.Installation) templ.Component { var templ_7745c5c3_Var19 templ.SafeURL templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(install.HTMLURL)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 148, Col: 42} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 146, Col: 42} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) if templ_7745c5c3_Err != nil { @@ -480,7 +478,7 @@ func (t installsTable) Row(install vcs.Installation) templ.Component { var templ_7745c5c3_Var20 string templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(install.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 152, Col: 24} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 150, Col: 24} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) if templ_7745c5c3_Err != nil { @@ -513,7 +511,7 @@ func (t installsTable) Row(install vcs.Installation) templ.Component { var templ_7745c5c3_Var22 string templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(install.ID) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 161, Col: 17} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 159, Col: 17} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) if templ_7745c5c3_Err != nil { @@ -532,7 +530,7 @@ func (t installsTable) Row(install vcs.Installation) templ.Component { var templ_7745c5c3_Var23 templ.SafeURL templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinURLErrs(paths.DeleteInstallGithubApp(internal.ToStringer(strconv.Itoa(int(install.ID))))) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 166, Col: 98} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 164, Col: 98} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) if templ_7745c5c3_Err != nil { @@ -553,7 +551,7 @@ func (t installsTable) Row(install vcs.Installation) templ.Component { var templ_7745c5c3_Var24 string templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(install.ID) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 168, Col: 61} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 166, Col: 61} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) if templ_7745c5c3_Err != nil { @@ -595,7 +593,7 @@ func deleteMessage(app *github.App) templ.Component { var templ_7745c5c3_Var26 string templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(app.Slug) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 175, Col: 54} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 173, Col: 54} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) if templ_7745c5c3_Err != nil { @@ -608,7 +606,7 @@ func deleteMessage(app *github.App) templ.Component { var templ_7745c5c3_Var27 templ.SafeURL templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinURLErrs(app.AdvancedURL()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 175, Col: 150} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/github_view.templ`, Line: 173, Col: 150} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) if templ_7745c5c3_Err != nil { diff --git a/internal/ui/handlers.go b/internal/ui/handlers.go index 95269bd17..851dadf90 100644 --- a/internal/ui/handlers.go +++ b/internal/ui/handlers.go @@ -8,6 +8,7 @@ import ( "github.com/leg100/otf/internal" "github.com/leg100/otf/internal/authenticator" "github.com/leg100/otf/internal/authz" + "github.com/leg100/otf/internal/configversion" "github.com/leg100/otf/internal/engine" "github.com/leg100/otf/internal/github" "github.com/leg100/otf/internal/http/html/paths" @@ -38,6 +39,7 @@ type Handlers struct { Runners *runner.Service GithubApp *github.Service EngineService *engine.Service + Configs *configversion.Service HostnameService *internal.HostnameService Tokens *tokens.Service Authorizer *authz.Authorizer @@ -59,10 +61,10 @@ func (h *Handlers) AddHandlers(r *mux.Router) { // the request is authenticated. r = r.PathPrefix(paths.UIPrefix).Subrouter() - addRunHandlers(r, h.Logger, h.Runs, h.Workspaces, h.Users, h.Runs) + addRunHandlers(r, h.Logger, h.Runs, h.Workspaces, h.Users, h.Configs, h.Authorizer) addTeamHandlers(r, h.Teams, h.Users, h.Tokens, h.Authorizer) addUserHandlers(r, h.Users, h.Authorizer) - addWorkspaceHandlers(r, h.Logger, h.Workspaces, h.Teams, h.VCSProviders, h.Authorizer, h.EngineService) + addWorkspaceHandlers(r, h.Logger, h.Workspaces, h.Teams, h.VCSProviders, h.Authorizer, h.EngineService, h.Runs, h.Users) addOrganizationHandlers(r, h.Organizations, h.RestrictOrganizationCreation) addModuleHandlers(r, h.Modules, h.VCSProviders, h.HostnameService, h.Authorizer) addVariableHandlers(r, h.VariablesService, h.Workspaces, h.Authorizer) diff --git a/internal/ui/module_view.templ b/internal/ui/module_view.templ index 571a0da74..a7becd0fa 100644 --- a/internal/ui/module_view.templ +++ b/internal/ui/module_view.templ @@ -34,7 +34,6 @@ templ newView(props newViewProps) { @components.UnpaginatedTable( &vcsTable{Actions: selectVCSProviderAction}, props.providers, - "providers", ) } } @@ -77,7 +76,6 @@ templ connect(props connectProps) { }.action, }, props.repos, - "repos-table", ) } } @@ -126,7 +124,7 @@ templ moduleList(props moduleListProps) { }, }) - @components.Table(&moduleTable{}, props.page, "page-results") + @components.Table(&moduleTable{}, props.page) } } diff --git a/internal/ui/module_view_templ.go b/internal/ui/module_view_templ.go index 09f1513f8..e56a84485 100644 --- a/internal/ui/module_view_templ.go +++ b/internal/ui/module_view_templ.go @@ -69,7 +69,6 @@ func newView(props newViewProps) templ.Component { templ_7745c5c3_Err = components.UnpaginatedTable( &vcsTable{Actions: selectVCSProviderAction}, props.providers, - "providers", ).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err @@ -119,7 +118,7 @@ func selectVCSProviderAction(vcsProviderID resource.TfeID) templ.Component { var templ_7745c5c3_Var4 templ.SafeURL templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(paths.ConnectModule(vcsProviderID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 43, Col: 50} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 42, Col: 50} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { @@ -132,7 +131,7 @@ func selectVCSProviderAction(vcsProviderID resource.TfeID) templ.Component { var templ_7745c5c3_Var5 string templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(vcsProviderID.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 44, Col: 76} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 43, Col: 76} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) if templ_7745c5c3_Err != nil { @@ -195,7 +194,7 @@ func connect(props connectProps) templ.Component { var templ_7745c5c3_Var8 string templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs("terraform--") if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 66, Col: 177} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 65, Col: 177} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { @@ -208,7 +207,7 @@ func connect(props connectProps) templ.Component { var templ_7745c5c3_Var9 templ.SafeURL templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinURLErrs(paths.CreateModule(props.provider.Organization)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 68, Col: 64} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 67, Col: 64} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { @@ -221,7 +220,7 @@ func connect(props connectProps) templ.Component { var templ_7745c5c3_Var10 string templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(props.provider.ID.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 69, Col: 102} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 68, Col: 102} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) if templ_7745c5c3_Err != nil { @@ -238,7 +237,6 @@ func connect(props connectProps) templ.Component { }.action, }, props.repos, - "repos-table", ).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err @@ -292,7 +290,7 @@ func (s moduleRepoSelector) action(repo vcs.Repo) templ.Component { var templ_7745c5c3_Var12 templ.SafeURL templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinURLErrs(paths.CreateModule(s.provider.Organization)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 90, Col: 59} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 88, Col: 59} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) if templ_7745c5c3_Err != nil { @@ -305,7 +303,7 @@ func (s moduleRepoSelector) action(repo vcs.Repo) templ.Component { var templ_7745c5c3_Var13 string templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(s.provider.ID.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 91, Col: 76} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 89, Col: 76} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) if templ_7745c5c3_Err != nil { @@ -318,7 +316,7 @@ func (s moduleRepoSelector) action(repo vcs.Repo) templ.Component { var templ_7745c5c3_Var14 string templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(repo.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 92, Col: 78} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 90, Col: 78} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) if templ_7745c5c3_Err != nil { @@ -381,7 +379,7 @@ func moduleList(props moduleListProps) templ.Component { var templ_7745c5c3_Var17 templ.SafeURL templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(components.CurrentURL(ctx))) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 115, Col: 58} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 113, Col: 58} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) if templ_7745c5c3_Err != nil { @@ -410,7 +408,7 @@ func moduleList(props moduleListProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = components.Table(&moduleTable{}, props.page, "page-results").Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.Table(&moduleTable{}, props.page).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -459,7 +457,7 @@ func providerFilterLabel(provider string) templ.Component { var templ_7745c5c3_Var19 string templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs("provider-" + provider) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 134, Col: 34} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 132, Col: 34} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) if templ_7745c5c3_Err != nil { @@ -472,7 +470,7 @@ func providerFilterLabel(provider string) templ.Component { var templ_7745c5c3_Var20 string templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(provider) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 135, Col: 12} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 133, Col: 12} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) if templ_7745c5c3_Err != nil { @@ -515,7 +513,7 @@ func moduleListActions(props moduleListProps) templ.Component { var templ_7745c5c3_Var22 templ.SafeURL templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinURLErrs(paths.NewModule(props.organization)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 141, Col: 52} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 139, Col: 52} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) if templ_7745c5c3_Err != nil { @@ -589,7 +587,7 @@ func (t moduleTable) Row(mod *module.Module) templ.Component { var templ_7745c5c3_Var25 string templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs("mod-item-" + mod.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 156, Col: 32} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 154, Col: 32} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) if templ_7745c5c3_Err != nil { @@ -602,7 +600,7 @@ func (t moduleTable) Row(mod *module.Module) templ.Component { var templ_7745c5c3_Var26 templ.SafeURL templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinURLErrs(paths.Module(mod.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 158, Col: 46} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 156, Col: 46} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) if templ_7745c5c3_Err != nil { @@ -615,7 +613,7 @@ func (t moduleTable) Row(mod *module.Module) templ.Component { var templ_7745c5c3_Var27 string templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(mod.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 159, Col: 14} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 157, Col: 14} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) if templ_7745c5c3_Err != nil { @@ -628,7 +626,7 @@ func (t moduleTable) Row(mod *module.Module) templ.Component { var templ_7745c5c3_Var28 string templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(mod.Provider) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 163, Col: 17} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 161, Col: 17} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28)) if templ_7745c5c3_Err != nil { @@ -720,7 +718,7 @@ func moduleGet(props moduleGetProps) templ.Component { var templ_7745c5c3_Var31 templ.SafeURL templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinURLErrs(paths.Module(props.module.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 199, Col: 82} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 197, Col: 82} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31)) if templ_7745c5c3_Err != nil { @@ -740,7 +738,7 @@ func moduleGet(props moduleGetProps) templ.Component { var templ_7745c5c3_Var32 string templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(mv.Version) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 205, Col: 36} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 203, Col: 36} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32)) if templ_7745c5c3_Err != nil { @@ -763,7 +761,7 @@ func moduleGet(props moduleGetProps) templ.Component { var templ_7745c5c3_Var33 string templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(mv.Version) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 205, Col: 108} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 203, Col: 108} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33)) if templ_7745c5c3_Err != nil { @@ -787,7 +785,7 @@ func moduleGet(props moduleGetProps) templ.Component { var templ_7745c5c3_Var34 string templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(props.module.Connection.Repo.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 212, Col: 94} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 210, Col: 94} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34)) if templ_7745c5c3_Err != nil { @@ -808,7 +806,7 @@ func moduleGet(props moduleGetProps) templ.Component { version = "` + props.currentVersion.Version + `" }`) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 225, Col: 2} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 223, Col: 2} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35)) if templ_7745c5c3_Err != nil { @@ -834,7 +832,7 @@ func moduleGet(props moduleGetProps) templ.Component { var templ_7745c5c3_Var36 string templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(resource) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 237, Col: 44} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 235, Col: 44} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36)) if templ_7745c5c3_Err != nil { @@ -857,7 +855,7 @@ func moduleGet(props moduleGetProps) templ.Component { var templ_7745c5c3_Var37 string templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.JoinStringErrs(v) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 245, Col: 37} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 243, Col: 37} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var37)) if templ_7745c5c3_Err != nil { @@ -880,7 +878,7 @@ func moduleGet(props moduleGetProps) templ.Component { var templ_7745c5c3_Var38 string templ_7745c5c3_Var38, templ_7745c5c3_Err = templ.JoinStringErrs(output) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 253, Col: 42} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 251, Col: 42} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var38)) if templ_7745c5c3_Err != nil { @@ -903,7 +901,7 @@ func moduleGet(props moduleGetProps) templ.Component { var templ_7745c5c3_Var39 templ.SafeURL templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.JoinURLErrs(paths.DeleteModule(props.module.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 258, Col: 79} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/module_view.templ`, Line: 256, Col: 79} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var39)) if templ_7745c5c3_Err != nil { diff --git a/internal/ui/organization_view.templ b/internal/ui/organization_view.templ index 91cfb512d..52deb8d4c 100644 --- a/internal/ui/organization_view.templ +++ b/internal/ui/organization_view.templ @@ -36,16 +36,16 @@ type organizationListProps struct { templ organizationList(props organizationListProps) { {{ - layoutProps := components.LayoutProps{ - Title: "organizations", - Breadcrumbs: []components.Breadcrumb{ - {Name: "organizations"}, - }, - ContentActions: organizationListActions(props.CanCreate), - } + layoutProps := components.LayoutProps{ + Title: "organizations", + Breadcrumbs: []components.Breadcrumb{ + {Name: "organizations"}, + }, + ContentActions: organizationListActions(props.CanCreate), + } }} @components.Layout(layoutProps) { - @components.Table(&organizationTable{}, props.Page, "organization-table") + @components.Table(&organizationTable{}, props.Page) } } @@ -129,7 +129,6 @@ templ getToken(org organization.Name, token *organization.OrganizationToken) { @components.UnpaginatedTable( &organizationTokenTable{}, []*organization.OrganizationToken{token}, - "org-token-table", ) } else {
diff --git a/internal/ui/organization_view_templ.go b/internal/ui/organization_view_templ.go index a775dee82..64c63d690 100644 --- a/internal/ui/organization_view_templ.go +++ b/internal/ui/organization_view_templ.go @@ -129,7 +129,7 @@ func organizationList(props organizationListProps) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = components.Table(&organizationTable{}, props.Page, "organization-table").Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.Table(&organizationTable{}, props.Page).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -459,7 +459,6 @@ func getToken(org organization.Name, token *organization.OrganizationToken) temp templ_7745c5c3_Err = components.UnpaginatedTable( &organizationTokenTable{}, []*organization.OrganizationToken{token}, - "org-token-table", ).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err @@ -472,7 +471,7 @@ func getToken(org organization.Name, token *organization.OrganizationToken) temp var templ_7745c5c3_Var21 templ.SafeURL templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinURLErrs(paths.CreateOrganizationToken(org)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/organization_view.templ`, Line: 135, Col: 65} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/organization_view.templ`, Line: 134, Col: 65} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) if templ_7745c5c3_Err != nil { @@ -566,7 +565,7 @@ func (t organizationTokenTable) Row(token *organization.OrganizationToken) templ var templ_7745c5c3_Var24 string templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(internal.Ago(time.Now(), token.CreatedAt)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/organization_view.templ`, Line: 156, Col: 52} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/organization_view.templ`, Line: 155, Col: 52} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) if templ_7745c5c3_Err != nil { @@ -579,7 +578,7 @@ func (t organizationTokenTable) Row(token *organization.OrganizationToken) templ var templ_7745c5c3_Var25 templ.SafeURL templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinURLErrs(paths.CreateOrganizationToken(token.Organization)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/organization_view.templ`, Line: 160, Col: 68} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/organization_view.templ`, Line: 159, Col: 68} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) if templ_7745c5c3_Err != nil { @@ -592,7 +591,7 @@ func (t organizationTokenTable) Row(token *organization.OrganizationToken) templ var templ_7745c5c3_Var26 templ.SafeURL templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinURLErrs(paths.DeleteOrganizationToken(token.Organization)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/organization_view.templ`, Line: 163, Col: 68} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/organization_view.templ`, Line: 162, Col: 68} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) if templ_7745c5c3_Err != nil { diff --git a/internal/ui/run.go b/internal/ui/run.go index d95c20a1c..bf3f65e22 100644 --- a/internal/ui/run.go +++ b/internal/ui/run.go @@ -4,12 +4,10 @@ import ( "context" "encoding/json" "net/http" - "time" "github.com/a-h/templ" "github.com/go-logr/logr" "github.com/gorilla/mux" - "github.com/gorilla/websocket" "github.com/leg100/otf/internal" "github.com/leg100/otf/internal/authz" "github.com/leg100/otf/internal/configversion/source" @@ -19,7 +17,7 @@ import ( "github.com/leg100/otf/internal/http/html/paths" "github.com/leg100/otf/internal/pubsub" "github.com/leg100/otf/internal/resource" - "github.com/leg100/otf/internal/run" + runpkg "github.com/leg100/otf/internal/run" "github.com/leg100/otf/internal/user" "github.com/leg100/otf/internal/workspace" ) @@ -30,21 +28,22 @@ type ( runs runClient workspaces runWorkspaceClient users runUsersClient + configs runConfigsClient authorizer runAuthorizer } runClient interface { - Create(ctx context.Context, workspaceID resource.TfeID, opts run.CreateOptions) (*run.Run, error) - List(ctx context.Context, opts run.ListOptions) (*resource.Page[*run.Run], error) - Get(ctx context.Context, id resource.TfeID) (*run.Run, error) + Create(ctx context.Context, workspaceID resource.TfeID, opts runpkg.CreateOptions) (*runpkg.Run, error) + List(ctx context.Context, opts runpkg.ListOptions) (*resource.Page[*runpkg.Run], error) + Get(ctx context.Context, id resource.TfeID) (*runpkg.Run, error) Delete(ctx context.Context, runID resource.TfeID) error Cancel(ctx context.Context, runID resource.TfeID) error ForceCancel(ctx context.Context, runID resource.TfeID) error Apply(ctx context.Context, runID resource.TfeID) error Discard(ctx context.Context, runID resource.TfeID) error - Watch(ctx context.Context) (<-chan pubsub.Event[*run.Event], func()) - Tail(ctx context.Context, opts run.TailOptions) (<-chan run.Chunk, error) - GetChunk(ctx context.Context, opts run.GetChunkOptions) (run.Chunk, error) + Watch(ctx context.Context) (<-chan pubsub.Event[*runpkg.Event], func()) + Tail(ctx context.Context, opts runpkg.TailOptions) (<-chan runpkg.Chunk, error) + GetChunk(ctx context.Context, opts runpkg.GetChunkOptions) (runpkg.Chunk, error) } runWorkspaceClient interface { @@ -63,24 +62,28 @@ type ( runAuthorizer interface { CanAccess(context.Context, authz.Action, resource.ID) bool } + + runConfigsClient interface { + GetSourceIcon(source source.Source) templ.Component + } ) // addRunHandlers registers run UI handlers with the router -func addRunHandlers(r *mux.Router, logger logr.Logger, runs runClient, workspaces runWorkspaceClient, users runUsersClient, authorizer runAuthorizer) { +func addRunHandlers(r *mux.Router, logger logr.Logger, runs runClient, workspaces runWorkspaceClient, users runUsersClient, configs runConfigsClient, authorizer runAuthorizer) { h := &runHandlers{ authorizer: authorizer, logger: logger, runs: runs, workspaces: workspaces, users: users, + configs: configs, } - r.HandleFunc("/organizations/{organization_name}/runs", h.listByOrganization).Methods("GET") - r.HandleFunc("/workspaces/{workspace_id}/runs", h.listByWorkspace).Methods("GET") + r.HandleFunc("/organizations/{organization_name}/runs", h.list).Methods("GET") + r.HandleFunc("/workspaces/{workspace_id}/runs", h.list).Methods("GET") r.HandleFunc("/workspaces/{workspace_id}/start-run", h.createRun).Methods("POST") r.HandleFunc("/workspaces/{workspace_id}/runs/watch-latest", h.watchLatest).Methods("GET") r.HandleFunc("/runs/{run_id}", h.get).Methods("GET") - r.HandleFunc("/runs/{run_id}/widget", h.getWidget).Methods("GET") r.HandleFunc("/runs/{run_id}/delete", h.delete).Methods("POST") r.HandleFunc("/runs/{run_id}/cancel", h.cancel).Methods("POST") r.HandleFunc("/runs/{run_id}/force-cancel", h.forceCancel).Methods("POST") @@ -96,17 +99,17 @@ func addRunHandlers(r *mux.Router, logger logr.Logger, runs runClient, workspace func (h *runHandlers) createRun(w http.ResponseWriter, r *http.Request) { var params struct { - WorkspaceID resource.TfeID `schema:"workspace_id,required"` - Operation run.Operation `schema:"operation,required"` + WorkspaceID resource.TfeID `schema:"workspace_id,required"` + Operation runpkg.Operation `schema:"operation,required"` } if err := decode.All(¶ms, r); err != nil { html.Error(r, w, err.Error(), html.WithStatus(http.StatusUnprocessableEntity)) return } - createdRun, err := h.runs.Create(r.Context(), params.WorkspaceID, run.CreateOptions{ - IsDestroy: internal.Ptr(params.Operation == run.DestroyAllOperation), - PlanOnly: internal.Ptr(params.Operation == run.PlanOnlyOperation), + createdRun, err := h.runs.Create(r.Context(), params.WorkspaceID, runpkg.CreateOptions{ + IsDestroy: internal.Ptr(params.Operation == runpkg.DestroyAllOperation), + PlanOnly: internal.Ptr(params.Operation == runpkg.PlanOnlyOperation), Source: source.UI, }) if err != nil { @@ -117,42 +120,9 @@ func (h *runHandlers) createRun(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, paths.Run(createdRun.ID), http.StatusFound) } -func (h *runHandlers) listByOrganization(w http.ResponseWriter, r *http.Request) { - if websocket.IsWebSocketUpgrade(r) { - h := &components.WebsocketListHandler[*run.Run, *run.Event, run.ListOptions]{ - Logger: h.logger, - Client: h.runs, - Populator: runTable{ - workspaceGetClient: newWorkspaceCache(h.workspaces), - users: newUserCache(h.users), - }, - ID: "page-results", - } - h.Handler(w, r) - return - } - h.list(w, r) -} - -func (h *runHandlers) listByWorkspace(w http.ResponseWriter, r *http.Request) { - if websocket.IsWebSocketUpgrade(r) { - h := &components.WebsocketListHandler[*run.Run, *run.Event, run.ListOptions]{ - Logger: h.logger, - Client: h.runs, - Populator: runTable{ - users: newUserCache(h.users), - }, - ID: "page-results", - } - h.Handler(w, r) - return - } - h.list(w, r) -} - func (h *runHandlers) list(w http.ResponseWriter, r *http.Request) { var opts struct { - run.ListOptions + runpkg.ListOptions StatusFilterVisible bool `schema:"status_filter_visible"` } if err := decode.All(&opts, r); err != nil { @@ -164,6 +134,11 @@ func (h *runHandlers) list(w http.ResponseWriter, r *http.Request) { status: opts.Statuses, statusFilterVisible: opts.StatusFilterVisible, pageOptions: opts.PageOptions, + table: runsTable{ + workspaceGetClient: newWorkspaceCache(h.workspaces), + users: newUserCache(h.users), + configs: h.configs, + }, } if opts.ListOptions.WorkspaceID != nil { @@ -182,6 +157,13 @@ func (h *runHandlers) list(w http.ResponseWriter, r *http.Request) { return } + page, err := h.runs.List(r.Context(), opts.ListOptions) + if err != nil { + html.Error(r, w, err.Error()) + return + } + props.page = page + html.Render(runList(props), w, r) } @@ -192,67 +174,45 @@ func (h *runHandlers) get(w http.ResponseWriter, r *http.Request) { return } - runResult, err := h.runs.Get(r.Context(), runID) + run, err := h.runs.Get(r.Context(), runID) if err != nil { html.Error(r, w, "retrieving run: "+err.Error()) return } - ws, err := h.workspaces.Get(r.Context(), runResult.WorkspaceID) + ws, err := h.workspaces.Get(r.Context(), run.WorkspaceID) if err != nil { html.Error(r, w, "retrieving workspace: "+err.Error()) return } // Get existing logs thus far received for each phase. - planLogs, err := h.runs.GetChunk(r.Context(), run.GetChunkOptions{ - RunID: runResult.ID, - Phase: run.PlanPhase, + planLogs, err := h.runs.GetChunk(r.Context(), runpkg.GetChunkOptions{ + RunID: run.ID, + Phase: runpkg.PlanPhase, }) if err != nil { html.Error(r, w, "retrieving plan logs: "+err.Error()) return } - applyLogs, err := h.runs.GetChunk(r.Context(), run.GetChunkOptions{ - RunID: runResult.ID, - Phase: run.ApplyPhase, + applyLogs, err := h.runs.GetChunk(r.Context(), runpkg.GetChunkOptions{ + RunID: run.ID, + Phase: runpkg.ApplyPhase, }) if err != nil { html.Error(r, w, "retrieving apply logs: "+err.Error()) return } - props := runGetProps{ - run: runResult, - ws: ws, - planLogs: run.Chunk{Data: planLogs.Data}, - applyLogs: run.Chunk{Data: applyLogs.Data}, + props := getRunProps{ + run: run, + ws: ws, + planLogs: runpkg.Chunk{Data: planLogs.Data}, + applyLogs: runpkg.Chunk{Data: applyLogs.Data}, + users: h.users, + singleRowTable: h.singleRowTable(run), } - html.Render(runGet(props), w, r) -} - -// getWidget renders a run "widget", i.e. the container that -// contains info about a run. Intended for use with an ajax request. -func (h *runHandlers) getWidget(w http.ResponseWriter, r *http.Request) { - runID, err := decode.ID("run_id", r) - if err != nil { - html.Error(r, w, err.Error(), html.WithStatus(http.StatusUnprocessableEntity)) - return - } - - runItem, err := h.runs.Get(r.Context(), runID) - if err != nil { - html.Error(r, w, err.Error()) - return - } - - table := components.UnpaginatedTable( - runTable{users: h.users}, - []*run.Run{runItem}, - "run-item-"+runItem.ID.String(), - ) - - html.Render(table, w, r) + html.Render(getRun(props), w, r) } func (h *runHandlers) delete(w http.ResponseWriter, r *http.Request) { @@ -348,7 +308,7 @@ func (h *runHandlers) retry(w http.ResponseWriter, r *http.Request) { return } - newRun, err := h.runs.Create(r.Context(), existingRun.WorkspaceID, run.CreateOptions{ + newRun, err := h.runs.Create(r.Context(), existingRun.WorkspaceID, runpkg.CreateOptions{ ConfigurationVersionID: &existingRun.ConfigurationVersionID, IsDestroy: &existingRun.IsDestroy, PlanOnly: &existingRun.PlanOnly, @@ -362,93 +322,92 @@ func (h *runHandlers) retry(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, paths.Run(newRun.ID), http.StatusFound) } +const ( + periodReportUpdate sseEvent = "PeriodReportUpdate" + runWidgetUpdate sseEvent = "RunWidgetUpdate" + runTimeUpdate sseEvent = "RunTimeUpdate" + planTimeUpdate sseEvent = "PlanTimeUpdate" + applyTimeUpdate sseEvent = "ApplyTimeUpdate" + planStatusUpdate sseEvent = "PlanStatusUpdate" + applyStatusUpdate sseEvent = "ApplyStatusUpdate" +) + func (h *runHandlers) watchRun(w http.ResponseWriter, r *http.Request) { runID, err := decode.ID("run_id", r) if err != nil { html.Error(r, w, err.Error(), html.WithStatus(http.StatusUnprocessableEntity)) return } - if !websocket.IsWebSocketUpgrade(r) { - return - } - // Render a one-row table containing run each time a run event arrives. - conn, err := components.NewWebsocket(h.logger, w, r, h.runs, (&event{users: h.users}).view) - if err != nil { - h.logger.Error(err, "upgrading websocket connection") - return - } - defer conn.Close() + conn := newSSEConnection(w, false) sub, _ := h.runs.Watch(r.Context()) - if !conn.Send(runID) { - return + send := func() { + run, err := h.runs.Get(r.Context(), runID) + if err != nil { + // terminate conn on error + return + } + // Render multiple html fragments each time a run event occurs. Each + // fragment is sent down the SSE conn as separate SSE events. + if err := conn.Render(r.Context(), runningTime(run), runTimeUpdate); err != nil { + return + } + if err := conn.Render(r.Context(), runningTime(&run.Plan), planTimeUpdate); err != nil { + return + } + if err := conn.Render(r.Context(), runningTime(&run.Apply), applyTimeUpdate); err != nil { + return + } + if err := conn.Render(r.Context(), phaseStatus(run.Plan), planStatusUpdate); err != nil { + return + } + if err := conn.Render(r.Context(), phaseStatus(run.Apply), applyStatusUpdate); err != nil { + return + } + if err := conn.Render(r.Context(), periodReport(run), periodReportUpdate); err != nil { + return + } + + if err := conn.Render(r.Context(), h.singleRowTable(run), runWidgetUpdate); err != nil { + return + } } + // Immediately send fragments in case they've changed since the page was + // first rendered. + // + // TODO: add versions to run resources and send rendered run version in + // query param so that versions can be compared and this step can be + // skipped. + send() - ticker := time.NewTicker(time.Second) for { select { - case event := <-sub: - if event.Type == pubsub.DeletedEvent { + case ev := <-sub: + if ev.Type == pubsub.DeletedEvent { // TODO: run has been deleted: user should be alerted and // client should not reconnect. return } - if event.Payload.ID != runID { + if ev.Payload.ID != runID { continue } - case <-r.Context().Done(): - return - } - // all further run events currently waiting on the subscription - // channel are rendered redundant because the websocket client - // retrieves the latest version of the run before sending it. - for { - select { - case <-sub: - default: - goto done - } - } - done: - if !conn.Send(runID) { - return - } - // Wait before sending anything more to client to avoid sending too many - // messages. - select { - case <-ticker.C: + send() case <-r.Context().Done(): return } } } +const latestRunUpdate sseEvent = "LatestRunUpdate" + func (h *runHandlers) watchLatest(w http.ResponseWriter, r *http.Request) { workspaceID, err := decode.ID("workspace_id", r) if err != nil { html.Error(r, w, err.Error(), html.WithStatus(http.StatusUnprocessableEntity)) return } - if !websocket.IsWebSocketUpgrade(r) { - return - } - conn, err := components.NewWebsocket( - h.logger, w, r, - h.runs, - func(runItem *run.Run) templ.Component { - return components.UnpaginatedTable( - runTable{users: h.users}, - []*run.Run{runItem}, - "latest-run", - ) - }, - ) - if err != nil { - h.logger.Error(err, "upgrading websocket connection") - return - } - defer conn.Close() + // Setup event subscriptions first then retrieve workspace to ensure we // don't miss anything. workspacesSub, _ := h.workspaces.Watch(r.Context()) @@ -458,13 +417,36 @@ func (h *runHandlers) watchLatest(w http.ResponseWriter, r *http.Request) { html.Error(r, w, err.Error(), html.WithStatus(http.StatusUnprocessableEntity)) return } + + conn := newSSEConnection(w, false) + + // function for retrieving run, rendering fragment and sending to client. + send := func(runID resource.TfeID) { + run, err := h.runs.Get(r.Context(), runID) + if err != nil { + // terminate conn on error + return + } + if err := conn.Render(r.Context(), h.singleRowTable(run), latestRunUpdate); err != nil { + // terminate conn on error + return + } + } + + // maintain reference to ID of latest run for workspace. var latestRunID *resource.TfeID + if ws.LatestRun != nil { latestRunID = &ws.LatestRun.ID - if !conn.Send(*latestRunID) { - return - } + // Immediately send fragment in case it's changed since the page was + // first rendered. + // + // TODO: add versions to run resources and send rendered run version in + // query param so that versions can be compared and this step can be + // skipped. + send(*latestRunID) } + for { select { case event := <-workspacesSub: @@ -497,19 +479,17 @@ func (h *runHandlers) watchLatest(w http.ResponseWriter, r *http.Request) { case <-r.Context().Done(): return } - if !conn.Send(*latestRunID) { - return - } + send(*latestRunID) } } const ( - EventLogChunk string = "log_update" - EventLogFinished string = "log_finished" + EventLogChunk sseEvent = "log_update" + EventLogFinished sseEvent = "log_finished" ) func (h *runHandlers) tailRun(w http.ResponseWriter, r *http.Request) { - var params run.TailOptions + var params runpkg.TailOptions if err := decode.All(¶ms, r); err != nil { html.Error(r, w, err.Error(), html.WithStatus(http.StatusUnprocessableEntity)) return @@ -521,19 +501,14 @@ func (h *runHandlers) tailRun(w http.ResponseWriter, r *http.Request) { return } - w.Header().Set("Content-Type", "text/event-stream") - w.Header().Set("Cache-Control", "no-cache") - w.Header().Set("Connection", "keep-alive") - w.WriteHeader(http.StatusOK) - rc := http.NewResponseController(w) - rc.Flush() + conn := newSSEConnection(w, false) for { select { case chunk, ok := <-ch: if !ok { // no more logs - pubsub.WriteSSEEvent(w, []byte("no more logs"), EventLogFinished, false) + conn.Send([]byte("no more logs"), EventLogFinished) return } html := chunk.ToHTML() @@ -552,10 +527,19 @@ func (h *runHandlers) tailRun(w http.ResponseWriter, r *http.Request) { h.logger.Error(err, "marshalling data") continue } - pubsub.WriteSSEEvent(w, js, EventLogChunk, false) - rc.Flush() + conn.Send(js, EventLogChunk) case <-r.Context().Done(): return } } } + +func (h *runHandlers) singleRowTable(run *runpkg.Run) templ.Component { + return components.UnpaginatedTable( + &runsTable{ + users: h.users, + configs: h.configs, + }, + []*runpkg.Run{run}, + ) +} diff --git a/internal/ui/run_test.go b/internal/ui/run_test.go new file mode 100644 index 000000000..d6fa590e9 --- /dev/null +++ b/internal/ui/run_test.go @@ -0,0 +1,173 @@ +package ui + +import ( + "context" + "net/http/httptest" + "testing" + + "github.com/a-h/templ" + "github.com/leg100/otf/internal/authz" + "github.com/leg100/otf/internal/configversion" + "github.com/leg100/otf/internal/configversion/source" + "github.com/leg100/otf/internal/http/html/paths" + "github.com/leg100/otf/internal/resource" + "github.com/leg100/otf/internal/run" + "github.com/leg100/otf/internal/testutils" + "github.com/leg100/otf/internal/user" + "github.com/leg100/otf/internal/workspace" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestListRunsHandler(t *testing.T) { + h := &runHandlers{ + workspaces: &fakeWorkspaceClient{ + ws: workspace.NewTestWorkspace(t, nil), + }, + runs: &fakeRunClient{ + run: &run.Run{}, + }, + configs: &fakeConfigsClient{}, + authorizer: authz.NewAllowAllAuthorizer(), + } + user := &user.User{ID: resource.NewTfeID(resource.UserKind)} + + r := httptest.NewRequest("GET", "/?workspace_id=ws-123&page=1", nil) + r = r.WithContext(authz.AddSubjectToContext(r.Context(), user)) + w := httptest.NewRecorder() + h.list(w, r) + assert.Equal(t, 200, w.Code) +} + +func TestWeb_GetHandler(t *testing.T) { + ws := workspace.NewTestWorkspace(t, nil) + cv := configversion.NewConfigurationVersion(ws.ID, configversion.CreateOptions{}) + run, err := run.NewRun(ws, cv, run.CreateOptions{}) + require.NoError(t, err) + + h := &runHandlers{ + workspaces: &fakeWorkspaceClient{ + ws: workspace.NewTestWorkspace(t, nil), + }, + runs: &fakeRunClient{ + run: run, + }, + configs: &fakeConfigsClient{}, + authorizer: authz.NewAllowAllAuthorizer(), + } + r := httptest.NewRequest("GET", "/?run_id=run-123", nil) + w := httptest.NewRecorder() + h.get(w, r) + assert.Equal(t, 200, w.Code, w.Body.String()) +} + +func TestRuns_CancelHandler(t *testing.T) { + run := &run.Run{ID: testutils.ParseID(t, "run-1")} + h := &runHandlers{ + runs: &fakeRunClient{}, + } + + r := httptest.NewRequest("POST", "/?run_id=run-1", nil) + w := httptest.NewRecorder() + h.cancel(w, r) + testutils.AssertRedirect(t, w, paths.Run(run.ID)) +} + +func TestWebHandlers_CreateRun_Connected(t *testing.T) { + run := &run.Run{ID: testutils.ParseID(t, "run-1")} + h := &runHandlers{ + runs: &fakeRunClient{run: run}, + } + + q := "/?workspace_id=run-123&operation=plan-only&connected=true" + r := httptest.NewRequest("POST", q, nil) + w := httptest.NewRecorder() + h.createRun(w, r) + testutils.AssertRedirect(t, w, paths.Run(run.ID)) +} + +func TestWebHandlers_CreateRun_Unconnected(t *testing.T) { + run := &run.Run{ID: testutils.ParseID(t, "run-1")} + h := &runHandlers{ + runs: &fakeRunClient{run: run}, + } + + q := "/?workspace_id=run-123&operation=plan-only&connected=false" + r := httptest.NewRequest("POST", q, nil) + w := httptest.NewRecorder() + h.createRun(w, r) + testutils.AssertRedirect(t, w, paths.Run(run.ID)) +} + +func TestTailLogs(t *testing.T) { + chunks := make(chan run.Chunk, 1) + h := &runHandlers{ + runs: &fakeRunClient{ + run: &run.Run{ID: testutils.ParseID(t, "run-1")}, + chunks: chunks, + }, + } + + r := httptest.NewRequest("", "/?offset=0&phase=plan&run_id=run-123", nil) + w := httptest.NewRecorder() + + // send one event and then close. + chunks <- run.Chunk{Data: []byte("some logs")} + close(chunks) + + done := make(chan struct{}) + go func() { + h.tailRun(w, r) + + want := "data: {\"html\":\"some logs\\u003cbr\\u003e\",\"offset\":9}\nevent: log_update\n\ndata: no more logs\nevent: log_finished\n\n" + assert.Equal(t, want, w.Body.String()) + + done <- struct{}{} + }() + <-done +} + +type fakeRunClient struct { + run *run.Run + runClient + chunks chan run.Chunk +} + +func (f *fakeRunClient) List(_ context.Context, opts run.ListOptions) (*resource.Page[*run.Run], error) { + return resource.NewPage([]*run.Run{f.run}, opts.PageOptions, nil), nil +} + +func (f *fakeRunClient) Get(ctx context.Context, id resource.TfeID) (*run.Run, error) { + return f.run, nil +} + +func (f *fakeRunClient) GetChunk(ctx context.Context, opts run.GetChunkOptions) (run.Chunk, error) { + return run.Chunk{}, nil +} + +func (f *fakeRunClient) Cancel(ctx context.Context, id resource.TfeID) error { + return nil +} + +func (f *fakeRunClient) Create(ctx context.Context, workspaceID resource.TfeID, opts run.CreateOptions) (*run.Run, error) { + return f.run, nil +} + +func (f *fakeRunClient) Tail(context.Context, run.TailOptions) (<-chan run.Chunk, error) { + return f.chunks, nil +} + +type fakeWorkspaceClient struct { + ws *workspace.Workspace + runWorkspaceClient +} + +func (f *fakeWorkspaceClient) Get(context.Context, resource.TfeID) (*workspace.Workspace, error) { + return f.ws, nil +} + +type fakeConfigsClient struct{} + +func (f *fakeConfigsClient) GetSourceIcon(source source.Source) templ.Component { + return templ.Raw("") +} diff --git a/internal/ui/run_view.templ b/internal/ui/run_view.templ index 0b65e4e41..60e4bbca3 100644 --- a/internal/ui/run_view.templ +++ b/internal/ui/run_view.templ @@ -21,44 +21,43 @@ type runListProps struct { status []runstatus.Status statusFilterVisible bool canUpdateWorkspace bool + table runsTable pageOptions resource.PageOptions + page *resource.Page[*run.Run] } templ runList(props runListProps) { {{ - layoutProps := components.LayoutProps{ - Title: "runs", - Organization: props.organization, - } - if props.ws != nil { - layoutProps.Breadcrumbs = []components.Breadcrumb{ - {Name: "Workspaces", Link: paths.Workspaces(props.organization)}, - {Name: props.ws.Name, Link: paths.Workspace(props.ws.ID)}, + layoutProps := components.LayoutProps{ + Title: "runs", + Organization: props.organization, } - layoutProps.ContentLinks = WorkspaceHeaderLinks(props.ws.ID, props.canUpdateWorkspace) - } - layoutProps.Breadcrumbs = append(layoutProps.Breadcrumbs, components.Breadcrumb{Name: "Runs"}) + if props.ws != nil { + layoutProps.Breadcrumbs = []components.Breadcrumb{ + {Name: "Workspaces", Link: paths.Workspaces(props.organization)}, + {Name: props.ws.Name, Link: paths.Workspace(props.ws.ID)}, + } + layoutProps.ContentLinks = WorkspaceHeaderLinks(props.ws.ID, props.canUpdateWorkspace) + } + layoutProps.Breadcrumbs = append(layoutProps.Breadcrumbs, components.Breadcrumb{Name: "Runs"}) }} @components.Layout(layoutProps) {
- + @runstatus.Filter(props.status, props.statusFilterVisible) -
+ @components.PollingTable(props.table, props.page)
} } -type runTable struct { +type runsTable struct { workspaceGetClient runWorkspaceGetClient users runUsersClient + configs runConfigsClient } -templ (t runTable) Header() { +templ (t runsTable) Header() { Run if t.workspaceGetClient != nil { @@ -70,7 +69,7 @@ templ (t runTable) Header() { Actions } -templ (t runTable) Row(run *run.Run) { +templ (t runsTable) Row(run *run.Run) { @@ -99,7 +98,7 @@ templ (t runTable) Row(run *run.Run) { }
- @run.SourceIcon + @t.configs.GetSourceIcon(run.Source) if run.IngressAttributes != nil {
} -func (t runTable) getWorkspaceName(ctx context.Context, run *run.Run) (string, error) { +func (t runsTable) getWorkspaceName(ctx context.Context, run *run.Run) (string, error) { ws, err := t.workspaceGetClient.Get(ctx, run.WorkspaceID) if err != nil { return "", err @@ -191,7 +190,7 @@ func (t runTable) getWorkspaceName(ctx context.Context, run *run.Run) (string, e return ws.Name, nil } -templ (t runTable) avatar(run *run.Run) { +templ (t runsTable) avatar(run *run.Run) {
if run.CreatedBy != nil { @@ -209,27 +208,29 @@ templ (t runTable) avatar(run *run.Run) {
} -type runGetProps struct { - run *run.Run - ws *workspace.Workspace - planLogs run.Chunk - applyLogs run.Chunk +type getRunProps struct { + run *run.Run + ws *workspace.Workspace + planLogs run.Chunk + applyLogs run.Chunk + users runUsersClient + singleRowTable templ.Component } -templ runGet(props runGetProps) { +templ getRun(props getRunProps) { {{ - layoutProps := components.LayoutProps{ - Title: props.run.ID.String(), - Organization: props.ws.Organization, - PreContent: getPreContent(), - PostContent: getPostContent(props), - Breadcrumbs: []components.Breadcrumb{ - {Name: "Workspaces", Link: paths.Workspaces(props.ws.Organization)}, - {Name: props.ws.Name, Link: paths.Workspace(props.ws.ID)}, - {Name: "Runs", Link: paths.Runs(props.ws.ID)}, - {Name: props.run.ID.String()}, - }, - } + layoutProps := components.LayoutProps{ + Title: props.run.ID.String(), + Organization: props.ws.Organization, + PreContent: getPreContent(), + PostContent: getPostContent(props), + Breadcrumbs: []components.Breadcrumb{ + {Name: "Workspaces", Link: paths.Workspaces(props.ws.Organization)}, + {Name: props.ws.Name, Link: paths.Workspace(props.ws.ID)}, + {Name: "Runs", Link: paths.Runs(props.ws.ID)}, + {Name: props.run.ID.String()}, + }, + } }} @components.Layout(layoutProps) {
@@ -248,21 +249,41 @@ templ runGet(props runGetProps) {
Elapsed time - + + @runningTime(props.run) +
@components.Identifier(props.run.ID)
-
+
+ @periodReport(props.run) +
-
+
+ @props.singleRowTable +
Plan - @phaseStatus(props.run.Plan) - @runningTime(&props.run.Plan) +
+ @phaseStatus(props.run.Plan) +
+
+ @runningTime(&props.run.Plan) +
@@ -274,10 +295,12 @@ templ runGet(props runGetProps) {
Apply - @phaseStatus(props.run.Apply) - +
+ @phaseStatus(props.run.Apply) +
+
@runningTime(&props.run.Apply) - +
@@ -295,7 +318,7 @@ templ getPreContent() { } -templ getPostContent(props runGetProps) { +templ getPostContent(props getRunProps) { if !props.planLogs.IsEnd() { @templ.JSFuncCall("setupTail", paths.TailRun(props.run.ID), "plan", props.planLogs.NextOffset()) } @@ -304,21 +327,6 @@ templ getPostContent(props runGetProps) { } } -type event struct { - users runUsersClient -} - -templ (e *event) view(runItem *run.Run) { - // render single-row table - @components.UnpaginatedTable(&runTable{users: e.users}, []*run.Run{runItem}, "run-item-"+runItem.ID.String()) - @phaseStatus(runItem.Plan) - @phaseStatus(runItem.Apply) - @periodReport(runItem) - @runningTime(runItem) - @runningTime(&runItem.Plan) - @runningTime(&runItem.Apply) -} - type task interface { ElapsedTime(time.Time) time.Duration HasStarted() bool @@ -345,7 +353,10 @@ templ runningTime(tsk task) { templ periodReport(run *run.Run) { {{ report := run.PeriodReport(time.Now()) }} -
+
for i, period := range report.Periods {
+ { phase.Status.String() } } diff --git a/internal/ui/run_view_templ.go b/internal/ui/run_view_templ.go index 0e90a8f0a..571991bea 100644 --- a/internal/ui/run_view_templ.go +++ b/internal/ui/run_view_templ.go @@ -29,7 +29,9 @@ type runListProps struct { status []runstatus.Status statusFilterVisible bool canUpdateWorkspace bool + table runsTable pageOptions resource.PageOptions + page *resource.Page[*run.Run] } func runList(props runListProps) templ.Component { @@ -78,41 +80,36 @@ func runList(props runListProps) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var4 templ.SafeURL - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(components.CurrentURL(ctx))) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 47, Col: 54} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) + templ_7745c5c3_Err = runstatus.Filter(props.status, props.statusFilterVisible).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\">") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = runstatus.Filter(props.status, props.statusFilterVisible).Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.PollingTable(props.table, props.page).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -126,12 +123,13 @@ func runList(props runListProps) templ.Component { }) } -type runTable struct { +type runsTable struct { workspaceGetClient runWorkspaceGetClient users runUsersClient + configs runConfigsClient } -func (t runTable) Header() templ.Component { +func (t runsTable) Header() templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -147,9 +145,9 @@ func (t runTable) Header() templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var5 := templ.GetChildren(ctx) - if templ_7745c5c3_Var5 == nil { - templ_7745c5c3_Var5 = templ.NopComponent + templ_7745c5c3_Var4 := templ.GetChildren(ctx) + if templ_7745c5c3_Var4 == nil { + templ_7745c5c3_Var4 = templ.NopComponent } ctx = templ.ClearChildren(ctx) templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "Run") @@ -170,7 +168,7 @@ func (t runTable) Header() templ.Component { }) } -func (t runTable) Row(run *run.Run) templ.Component { +func (t runsTable) Row(run *run.Run) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -186,21 +184,21 @@ func (t runTable) Row(run *run.Run) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var6 := templ.GetChildren(ctx) - if templ_7745c5c3_Var6 == nil { - templ_7745c5c3_Var6 = templ.NopComponent + templ_7745c5c3_Var5 := templ.GetChildren(ctx) + if templ_7745c5c3_Var5 == nil { + templ_7745c5c3_Var5 = templ.NopComponent } ctx = templ.ClearChildren(ctx) templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "
") @@ -689,12 +687,12 @@ func (t runTable) avatar(run *run.Run) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var30 string - templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(templ.SafeURL(run.IngressAttributes.SenderAvatarURL)) + var templ_7745c5c3_Var29 string + templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(templ.SafeURL(run.IngressAttributes.SenderAvatarURL)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 206, Col: 67} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 205, Col: 67} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -711,14 +709,16 @@ func (t runTable) avatar(run *run.Run) templ.Component { }) } -type runGetProps struct { - run *run.Run - ws *workspace.Workspace - planLogs run.Chunk - applyLogs run.Chunk +type getRunProps struct { + run *run.Run + ws *workspace.Workspace + planLogs run.Chunk + applyLogs run.Chunk + users runUsersClient + singleRowTable templ.Component } -func runGet(props runGetProps) templ.Component { +func getRun(props getRunProps) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -734,9 +734,9 @@ func runGet(props runGetProps) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var31 := templ.GetChildren(ctx) - if templ_7745c5c3_Var31 == nil { - templ_7745c5c3_Var31 = templ.NopComponent + templ_7745c5c3_Var30 := templ.GetChildren(ctx) + if templ_7745c5c3_Var30 == nil { + templ_7745c5c3_Var30 = templ.NopComponent } ctx = templ.ClearChildren(ctx) @@ -752,7 +752,7 @@ func runGet(props runGetProps) templ.Component { {Name: props.run.ID.String()}, }, } - templ_7745c5c3_Var32 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var31 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { @@ -768,55 +768,76 @@ func runGet(props runGetProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } + var templ_7745c5c3_Var32 string + templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(string(paths.WatchRun(props.run.ID))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 236, Col: 68} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "\">
Engine ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } var templ_7745c5c3_Var33 string - templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(string(paths.WatchRun(props.run.ID))) + templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(props.run.Engine.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 235, Col: 68} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 241, Col: 32} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "\">
Engine ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "
Engine version ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var34 string - templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(props.run.Engine.String()) + templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(props.run.EngineVersion) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 240, Col: 32} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 247, Col: 30} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "
Engine version ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "
Elapsed time
Elapsed time
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "\">") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = runningTime(props.run).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -824,20 +845,75 @@ func runGet(props runGetProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "
Plan") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "\">") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = periodReport(props.run).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = props.singleRowTable.Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 74, "
Plan
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -845,11 +921,28 @@ func runGet(props runGetProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } templ_7745c5c3_Err = runningTime(&props.run.Plan).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -857,7 +950,20 @@ func runGet(props runGetProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "
Apply") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "
Apply
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -865,7 +971,20 @@ func runGet(props runGetProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -873,7 +992,7 @@ func runGet(props runGetProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 83, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -881,13 +1000,13 @@ func runGet(props runGetProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 84, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } return nil }) - templ_7745c5c3_Err = components.Layout(layoutProps).Render(templ.WithChildren(ctx, templ_7745c5c3_Var32), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.Layout(layoutProps).Render(templ.WithChildren(ctx, templ_7745c5c3_Var31), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -911,51 +1030,51 @@ func getPreContent() templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var38 := templ.GetChildren(ctx) - if templ_7745c5c3_Var38 == nil { - templ_7745c5c3_Var38 = templ.NopComponent + templ_7745c5c3_Var44 := templ.GetChildren(ctx) + if templ_7745c5c3_Var44 == nil { + templ_7745c5c3_Var44 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 74, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 88, "\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -963,7 +1082,7 @@ func getPreContent() templ.Component { }) } -func getPostContent(props runGetProps) templ.Component { +func getPostContent(props getRunProps) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -979,9 +1098,9 @@ func getPostContent(props runGetProps) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var42 := templ.GetChildren(ctx) - if templ_7745c5c3_Var42 == nil { - templ_7745c5c3_Var42 = templ.NopComponent + templ_7745c5c3_Var48 := templ.GetChildren(ctx) + if templ_7745c5c3_Var48 == nil { + templ_7745c5c3_Var48 = templ.NopComponent } ctx = templ.ClearChildren(ctx) if !props.planLogs.IsEnd() { @@ -1000,63 +1119,6 @@ func getPostContent(props runGetProps) templ.Component { }) } -type event struct { - users runUsersClient -} - -func (e *event) view(runItem *run.Run) templ.Component { - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { - return templ_7745c5c3_CtxErr - } - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) - if !templ_7745c5c3_IsBuffer { - defer func() { - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) - if templ_7745c5c3_Err == nil { - templ_7745c5c3_Err = templ_7745c5c3_BufErr - } - }() - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var43 := templ.GetChildren(ctx) - if templ_7745c5c3_Var43 == nil { - templ_7745c5c3_Var43 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = components.UnpaginatedTable(&runTable{users: e.users}, []*run.Run{runItem}, "run-item-"+runItem.ID.String()).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = phaseStatus(runItem.Plan).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = phaseStatus(runItem.Apply).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = periodReport(runItem).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = runningTime(runItem).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = runningTime(&runItem.Plan).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = runningTime(&runItem.Apply).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - return nil - }) -} - type task interface { ElapsedTime(time.Time) time.Duration HasStarted() bool @@ -1081,71 +1143,71 @@ func runningTime(tsk task) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var44 := templ.GetChildren(ctx) - if templ_7745c5c3_Var44 == nil { - templ_7745c5c3_Var44 = templ.NopComponent + templ_7745c5c3_Var49 := templ.GetChildren(ctx) + if templ_7745c5c3_Var49 == nil { + templ_7745c5c3_Var49 = templ.NopComponent } ctx = templ.ClearChildren(ctx) if tsk.HasStarted() { elapsed := tsk.ElapsedTime(time.Now()) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 91, "\" x-text=\"formatDuration(elapsed)\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var47 string - templ_7745c5c3_Var47, templ_7745c5c3_Err = templ.JoinStringErrs(int(elapsed)) + var templ_7745c5c3_Var52 string + templ_7745c5c3_Var52, templ_7745c5c3_Err = templ.JoinStringErrs(int(elapsed)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 339, Col: 17} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 347, Col: 17} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var47)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var52)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 92, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 94, "\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1170,112 +1232,112 @@ func periodReport(run *run.Run) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var49 := templ.GetChildren(ctx) - if templ_7745c5c3_Var49 == nil { - templ_7745c5c3_Var49 = templ.NopComponent + templ_7745c5c3_Var54 := templ.GetChildren(ctx) + if templ_7745c5c3_Var54 == nil { + templ_7745c5c3_Var54 = templ.NopComponent } ctx = templ.ClearChildren(ctx) report := run.PeriodReport(time.Now()) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 84, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 95, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for i, period := range report.Periods { - var templ_7745c5c3_Var50 = []any{"inline-block", "h-full", "bg-" + period.Status.String()} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var50...) + var templ_7745c5c3_Var55 = []any{"inline-block", "h-full", "bg-" + period.Status.String()} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var55...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 85, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 98, "\">
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 88, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 105, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1299,51 +1361,51 @@ func resourceReport(report *run.Report) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var57 := templ.GetChildren(ctx) - if templ_7745c5c3_Var57 == nil { - templ_7745c5c3_Var57 = templ.NopComponent + templ_7745c5c3_Var62 := templ.GetChildren(ctx) + if templ_7745c5c3_Var62 == nil { + templ_7745c5c3_Var62 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 95, "
+") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 106, "
+") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var58 string - templ_7745c5c3_Var58, templ_7745c5c3_Err = templ.JoinStringErrs(report.Additions) + var templ_7745c5c3_Var63 string + templ_7745c5c3_Var63, templ_7745c5c3_Err = templ.JoinStringErrs(report.Additions) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 371, Col: 50} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 382, Col: 50} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var58)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var63)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 96, "~") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 107, "~") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var59 string - templ_7745c5c3_Var59, templ_7745c5c3_Err = templ.JoinStringErrs(report.Changes) + var templ_7745c5c3_Var64 string + templ_7745c5c3_Var64, templ_7745c5c3_Err = templ.JoinStringErrs(report.Changes) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 371, Col: 104} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 382, Col: 104} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var59)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var64)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 97, "-") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 108, "-") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var60 string - templ_7745c5c3_Var60, templ_7745c5c3_Err = templ.JoinStringErrs(report.Destructions) + var templ_7745c5c3_Var65 string + templ_7745c5c3_Var65, templ_7745c5c3_Err = templ.JoinStringErrs(report.Destructions) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 371, Col: 162} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 382, Col: 162} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var60)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var65)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 98, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 109, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1377,56 +1439,56 @@ func phaseStatus(phase run.Phase) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var61 := templ.GetChildren(ctx) - if templ_7745c5c3_Var61 == nil { - templ_7745c5c3_Var61 = templ.NopComponent + templ_7745c5c3_Var66 := templ.GetChildren(ctx) + if templ_7745c5c3_Var66 == nil { + templ_7745c5c3_Var66 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - var templ_7745c5c3_Var62 = []any{"badge", phaseBadges[phase.Status]} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var62...) + var templ_7745c5c3_Var67 = []any{"badge", phaseBadges[phase.Status]} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var67...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 99, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 112, "\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var65 string - templ_7745c5c3_Var65, templ_7745c5c3_Err = templ.JoinStringErrs(phase.Status.String()) + var templ_7745c5c3_Var70 string + templ_7745c5c3_Var70, templ_7745c5c3_Err = templ.JoinStringErrs(phase.Status.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 387, Col: 25} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/run_view.templ`, Line: 401, Col: 25} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var65)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var70)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 102, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 113, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/internal/ui/runner.go b/internal/ui/runner.go index 670dffac6..811fd9d22 100644 --- a/internal/ui/runner.go +++ b/internal/ui/runner.go @@ -8,7 +8,6 @@ import ( "slices" "github.com/gorilla/mux" - "github.com/gorilla/websocket" "github.com/leg100/otf/internal/authz" "github.com/leg100/otf/internal/http/decode" "github.com/leg100/otf/internal/http/html" @@ -27,11 +26,10 @@ const runnersTableID = "runners-table" // runnerHandlers provides handlers for the web UI for runners type runnerHandlers struct { - svc runnerClient - workspaces *workspace.Service - logger logr.Logger - authorizer authz.Interface - websocketListHandler *components.WebsocketListHandler[*runner.RunnerMeta, *runner.RunnerEvent, runner.ListOptions] + svc runnerClient + workspaces *workspace.Service + logger logr.Logger + authorizer authz.Interface } // runnerClient gives web handlers access to the agents service endpoints @@ -84,12 +82,6 @@ func addRunnerHandlers( logger: logger, svc: svc, workspaces: workspaces, - websocketListHandler: &components.WebsocketListHandler[*runner.RunnerMeta, *runner.RunnerEvent, runner.ListOptions]{ - Logger: logger, - Client: svc, - Populator: runnersTable{}, - ID: runnersTableID, - }, } // runners @@ -111,19 +103,21 @@ func addRunnerHandlers( // runner handlers func (h *runnerHandlers) listRunners(w http.ResponseWriter, r *http.Request) { - if websocket.IsWebSocketUpgrade(r) { - h.websocketListHandler.Handler(w, r) - return - } - var params runner.ListOptions if err := decode.All(¶ms, r); err != nil { html.Error(r, w, err.Error(), html.WithStatus(http.StatusUnprocessableEntity)) return } + runners, err := h.svc.ListRunners(r.Context(), params) + if err != nil { + html.Error(r, w, err.Error()) + return + } + props := listRunnersProps{ organization: *params.Organization, hideServerRunners: params.HideServerRunners, + page: resource.NewPage(runners, resource.PageOptions{}, nil), } html.Render(listRunners(props), w, r) } @@ -211,11 +205,6 @@ func (h *runnerHandlers) listAgentPools(w http.ResponseWriter, r *http.Request) } func (h *runnerHandlers) getAgentPool(w http.ResponseWriter, r *http.Request) { - if websocket.IsWebSocketUpgrade(r) { - h.websocketListHandler.Handler(w, r) - return - } - poolID, err := decode.ID("pool_id", r) if err != nil { html.Error(r, w, err.Error(), html.WithStatus(http.StatusUnprocessableEntity)) diff --git a/internal/ui/runner_view.templ b/internal/ui/runner_view.templ index 4309548a0..ed0b40a69 100644 --- a/internal/ui/runner_view.templ +++ b/internal/ui/runner_view.templ @@ -12,6 +12,7 @@ import ( type listRunnersProps struct { organization organization.Name hideServerRunners bool + page *resource.Page[*runner.RunnerMeta] } templ listRunners(props listRunnersProps) { @@ -34,8 +35,8 @@ templ listRunners(props listRunnersProps) { -
-
+
+ @components.PollingTable(runnersTable{}, props.page)
} } @@ -143,7 +144,7 @@ templ listAgentPools(props listAgentPoolProps) {
- @components.Table(&agentPoolsTable{}, props.pools, "page-results") + @components.Table(&agentPoolsTable{}, props.pools) } } @@ -296,12 +297,10 @@ templ getAgentPool(props getAgentPoolProps) {
- @components.UnpaginatedTable(agentTokensTable{}, props.tokens, "page-results") + @components.UnpaginatedTable(agentTokensTable{}, props.tokens)

Agents

-
-
-
+ @components.PollingTable(runnersTable{}, props.agents) if props.canDeleteAgentPool {

Advanced

diff --git a/internal/ui/runner_view_templ.go b/internal/ui/runner_view_templ.go index 777d14213..918ca3c10 100644 --- a/internal/ui/runner_view_templ.go +++ b/internal/ui/runner_view_templ.go @@ -20,6 +20,7 @@ import ( type listRunnersProps struct { organization organization.Name hideServerRunners bool + page *resource.Page[*runner.RunnerMeta] } func listRunners(props listRunnersProps) templ.Component { @@ -62,7 +63,7 @@ func listRunners(props listRunnersProps) templ.Component { var templ_7745c5c3_Var3 templ.SafeURL templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(paths.Runners(props.organization)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 28, Col: 50} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 29, Col: 50} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { @@ -78,33 +79,15 @@ func listRunners(props listRunnersProps) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "> Hide otfd runners
Hide otfd runners
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(components.CurrentURL(ctx)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 37, Col: 58} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -150,12 +133,12 @@ func (t runnersTable) Header() templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var6 := templ.GetChildren(ctx) - if templ_7745c5c3_Var6 == nil { - templ_7745c5c3_Var6 = templ.NopComponent + templ_7745c5c3_Var4 := templ.GetChildren(ctx) + if templ_7745c5c3_Var4 == nil { + templ_7745c5c3_Var4 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "NameStatusCapacityVersionProcessIP AddressLast seen") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "NameStatusCapacityVersionProcessIP AddressLast seen") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -179,45 +162,45 @@ func (t runnersTable) Row(runner *runner.RunnerMeta) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var7 := templ.GetChildren(ctx) - if templ_7745c5c3_Var7 == nil { - templ_7745c5c3_Var7 = templ.NopComponent + templ_7745c5c3_Var5 := templ.GetChildren(ctx) + if templ_7745c5c3_Var5 == nil { + templ_7745c5c3_Var5 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\">
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if runner.Name != "" { - var templ_7745c5c3_Var9 string - templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(runner.Name) + var templ_7745c5c3_Var7 string + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(runner.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 69, Col: 19} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 70, Col: 19} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "-") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "-") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -225,144 +208,144 @@ func (t runnersTable) Row(runner *runner.RunnerMeta) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var10 = []any{"status animate-ping", runnerStatusColors[runner.Status]} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var10...) + var templ_7745c5c3_Var8 = []any{"status animate-ping", runnerStatusColors[runner.Status]} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var8...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\">
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var12 = []any{"status", runnerStatusColors[runner.Status]} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var12...) + var templ_7745c5c3_Var10 = []any{"status", runnerStatusColors[runner.Status]} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var10...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\">
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var14 string - templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(string(runner.Status)) + var templ_7745c5c3_Var12 string + templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(string(runner.Status)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 84, Col: 28} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 85, Col: 28} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "
(") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\">(") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var16 string - templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d/%d", runner.CurrentJobs, runner.MaxJobs)) + var templ_7745c5c3_Var14 string + templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d/%d", runner.CurrentJobs, runner.MaxJobs)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 89, Col: 204} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 90, Col: 204} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, ")
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, ")") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var17 string - templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(runner.Version) + var templ_7745c5c3_Var15 string + templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(runner.Version) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 92, Col: 34} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 93, Col: 34} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if runner.IsAgent() { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "otf-agent") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "otf-agent") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "otfd") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "otfd") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var18 string - templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(runner.IPAddress.String()) + var templ_7745c5c3_Var16 string + templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(runner.IPAddress.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 104, Col: 45} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 105, Col: 45} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -370,7 +353,7 @@ func (t runnersTable) Row(runner *runner.RunnerMeta) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -399,12 +382,12 @@ func listAgentPools(props listAgentPoolProps) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var20 := templ.GetChildren(ctx) - if templ_7745c5c3_Var20 == nil { - templ_7745c5c3_Var20 = templ.NopComponent + templ_7745c5c3_Var18 := templ.GetChildren(ctx) + if templ_7745c5c3_Var18 == nil { + templ_7745c5c3_Var18 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var21 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var19 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { @@ -416,24 +399,24 @@ func listAgentPools(props listAgentPoolProps) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "
An agent pool is a group of otf-agent processes that can be used to communicate with isolated, private, or on-premises infrastructure. Each agent pool has its own set of tokens which are not shared across pools. When a workspace is configured to execute runs using the agent execution mode, any available agent in that workspace's associated agent pool is eligible to complete the run.
New agent pool
An agent pool is a group of otf-agent processes that can be used to communicate with isolated, private, or on-premises infrastructure. Each agent pool has its own set of tokens which are not shared across pools. When a workspace is configured to execute runs using the agent execution mode, any available agent in that workspace's associated agent pool is eligible to complete the run.
New agent pool
Enter a name to help identify the pool.

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "\" method=\"POST\">
Enter a name to help identify the pool.

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = components.Table(&agentPoolsTable{}, props.pools, "page-results").Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.Table(&agentPoolsTable{}, props.pools).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -445,7 +428,7 @@ func listAgentPools(props listAgentPoolProps) templ.Component { Breadcrumbs: []components.Breadcrumb{ {Name: "Agent Pools"}, }, - }).Render(templ.WithChildren(ctx, templ_7745c5c3_Var21), templ_7745c5c3_Buffer) + }).Render(templ.WithChildren(ctx, templ_7745c5c3_Var19), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -471,12 +454,12 @@ func (t agentPoolsTable) Header() templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var23 := templ.GetChildren(ctx) - if templ_7745c5c3_Var23 == nil { - templ_7745c5c3_Var23 = templ.NopComponent + templ_7745c5c3_Var21 := templ.GetChildren(ctx) + if templ_7745c5c3_Var21 == nil { + templ_7745c5c3_Var21 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "NameIDCreated") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "NameIDCreated") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -500,51 +483,51 @@ func (t agentPoolsTable) Row(pool *runner.Pool) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var24 := templ.GetChildren(ctx) - if templ_7745c5c3_Var24 == nil { - templ_7745c5c3_Var24 = templ.NopComponent + templ_7745c5c3_Var22 := templ.GetChildren(ctx) + if templ_7745c5c3_Var22 == nil { + templ_7745c5c3_Var22 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var27 string - templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(pool.Name) + var templ_7745c5c3_Var25 string + templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(pool.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 162, Col: 15} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 163, Col: 15} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -552,7 +535,7 @@ func (t agentPoolsTable) Row(pool *runner.Pool) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -560,7 +543,7 @@ func (t agentPoolsTable) Row(pool *runner.Pool) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -589,58 +572,58 @@ func agentPoolListAllowed(props agentPoolListAllowedProps) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var28 := templ.GetChildren(ctx) - if templ_7745c5c3_Var28 == nil { - templ_7745c5c3_Var28 = templ.NopComponent + templ_7745c5c3_Var26 := templ.GetChildren(ctx) + if templ_7745c5c3_Var26 == nil { + templ_7745c5c3_Var26 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, pool := range props.pools { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -674,12 +657,12 @@ func getAgentPool(props getAgentPoolProps) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var31 := templ.GetChildren(ctx) - if templ_7745c5c3_Var31 == nil { - templ_7745c5c3_Var31 = templ.NopComponent + templ_7745c5c3_Var29 := templ.GetChildren(ctx) + if templ_7745c5c3_Var29 == nil { + templ_7745c5c3_Var29 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var32 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var30 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { @@ -691,7 +674,7 @@ func getAgentPool(props getAgentPoolProps) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -699,249 +682,231 @@ func getAgentPool(props getAgentPoolProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "
Workspaces You can grant access to this agent pool globally to all current and future workspaces in this organization or grant access to specific workspaces.
Workspaces You can grant access to this agent pool globally to all current and future workspaces in this organization or grant access to specific workspaces.
A workspace must be granted access before it can be assigned. To revoke access from an assigned workspace, first unassign the workspace and then revoke.

Granted

Granted & Assigned

A workspace must be granted access before it can be assigned. To revoke access from an assigned workspace, first unassign the workspace and then revoke.

Granted

Granted & Assigned


Tokens

New token

Tokens

New token
Enter a description to help identify the token.
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "\" method=\"POST\">
Enter a description to help identify the token.
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = components.UnpaginatedTable(agentTokensTable{}, props.tokens, "page-results").Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.UnpaginatedTable(agentTokensTable{}, props.tokens).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "

Agents

Agents

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var41 string - templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.JoinStringErrs(components.CurrentURL(ctx)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 302, Col: 58} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var41)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "\">
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if props.canDeleteAgentPool { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "

Advanced

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "

Advanced

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if len(props.assignedWorkspaces) > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "Before deleting an agent pool you must unassign the pool from the following workspaces:") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, ">Delete agent pool") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -955,7 +920,7 @@ func getAgentPool(props getAgentPoolProps) templ.Component { {Name: "Agent Pools", Link: paths.AgentPools(props.pool.Organization)}, {Name: props.pool.Name}, }, - }).Render(templ.WithChildren(ctx, templ_7745c5c3_Var32), templ_7745c5c3_Buffer) + }).Render(templ.WithChildren(ctx, templ_7745c5c3_Var30), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -981,12 +946,12 @@ func (t agentTokensTable) Header() templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var46 := templ.GetChildren(ctx) - if templ_7745c5c3_Var46 == nil { - templ_7745c5c3_Var46 = templ.NopComponent + templ_7745c5c3_Var42 := templ.GetChildren(ctx) + if templ_7745c5c3_Var42 == nil { + templ_7745c5c3_Var42 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "NameIDCreatedActions") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "NameIDCreatedActions") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1010,25 +975,25 @@ func (t agentTokensTable) Row(token *runner.AgentToken) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var47 := templ.GetChildren(ctx) - if templ_7745c5c3_Var47 == nil { - templ_7745c5c3_Var47 = templ.NopComponent + templ_7745c5c3_Var43 := templ.GetChildren(ctx) + if templ_7745c5c3_Var43 == nil { + templ_7745c5c3_Var43 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var48 string - templ_7745c5c3_Var48, templ_7745c5c3_Err = templ.JoinStringErrs(token.Description) + var templ_7745c5c3_Var44 string + templ_7745c5c3_Var44, templ_7745c5c3_Err = templ.JoinStringErrs(token.Description) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 336, Col: 25} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/runner_view.templ`, Line: 335, Col: 25} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var48)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var44)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 74, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1036,7 +1001,7 @@ func (t agentTokensTable) Row(token *runner.AgentToken) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1044,20 +1009,20 @@ func (t agentTokensTable) Row(token *runner.AgentToken) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "\" method=\"POST\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1065,7 +1030,7 @@ func (t agentTokensTable) Row(token *runner.AgentToken) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/internal/ui/sse_connection.go b/internal/ui/sse_connection.go new file mode 100644 index 000000000..1e6986935 --- /dev/null +++ b/internal/ui/sse_connection.go @@ -0,0 +1,60 @@ +package ui + +import ( + "bytes" + "context" + "encoding/base64" + "fmt" + "net/http" + "strings" + + "github.com/a-h/templ" + "github.com/go-logr/logr" +) + +type sseConnection struct { + http.ResponseWriter + *http.ResponseController + base64 bool + logger logr.Logger +} + +type sseEvent string + +func newSSEConnection(w http.ResponseWriter, base64 bool) *sseConnection { + rc := http.NewResponseController(w) + w.Header().Set("Content-Type", "text/event-stream") + w.Header().Set("Cache-Control", "no-cache") + w.Header().Set("Connection", "keep-alive") + w.WriteHeader(http.StatusOK) + rc.Flush() + return &sseConnection{ + ResponseWriter: w, + ResponseController: rc, + base64: base64, + } +} + +// Send writes an server-side-event to w. The data is optionally base64 encoded +// before being written. +func (conn *sseConnection) Send(data []byte, event sseEvent) { + if conn.base64 { + output := make([]byte, base64.StdEncoding.EncodedLen(len(data))) + base64.StdEncoding.Encode(output, data) + data = output + } + fmt.Fprintf(conn, "data: %s\n", strings.ReplaceAll(string(data), "\n", " ")) + fmt.Fprintf(conn, "event: %s\n\n", event) + + conn.Flush() +} + +func (conn *sseConnection) Render(ctx context.Context, comp templ.Component, event sseEvent) error { + var buf bytes.Buffer + if err := comp.Render(ctx, &buf); err != nil { + conn.logger.Error(err, "rendering html fragment on sse connection") + return err + } + conn.Send(buf.Bytes(), event) + return nil +} diff --git a/internal/ui/team_view.templ b/internal/ui/team_view.templ index 2e00aa920..95a7b5826 100644 --- a/internal/ui/team_view.templ +++ b/internal/ui/team_view.templ @@ -47,7 +47,7 @@ templ listTeams(props listTeamsProps) { ContentActions: listTeamsActions(props), }) {
- @components.Table(&teamTable{}, props.teams, "page-results") + @components.Table(&teamTable{}, props.teams)
} } diff --git a/internal/ui/team_view_templ.go b/internal/ui/team_view_templ.go index ebdb1f91c..195209067 100644 --- a/internal/ui/team_view_templ.go +++ b/internal/ui/team_view_templ.go @@ -128,7 +128,7 @@ func listTeams(props listTeamsProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = components.Table(&teamTable{}, props.teams, "page-results").Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.Table(&teamTable{}, props.teams).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/internal/ui/user_view.templ b/internal/ui/user_view.templ index a73f0c9eb..dcb159cac 100644 --- a/internal/ui/user_view.templ +++ b/internal/ui/user_view.templ @@ -65,7 +65,7 @@ templ userList(props userListProps) { {Name: "Users"}, }, }) { - @components.Table(&userTable{}, props.users, "page-results") + @components.Table(&userTable{}, props.users) } } @@ -193,7 +193,6 @@ templ getTeam(props getTeamProps) { @components.UnpaginatedTable( &userTable{teamID: &props.team.ID, canRemoveMember: props.canRemoveMember}, props.members, - "team-members", ) if props.canAddMember { @@ -245,7 +244,6 @@ templ tokenList(tokens []*user.UserToken) { @components.UnpaginatedTable( &tokensTable{}, tokens, - "tokens-table", ) } } diff --git a/internal/ui/user_view_templ.go b/internal/ui/user_view_templ.go index e6839fc2e..c97a229a8 100644 --- a/internal/ui/user_view_templ.go +++ b/internal/ui/user_view_templ.go @@ -222,7 +222,7 @@ func userList(props userListProps) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = components.Table(&userTable{}, props.users, "page-results").Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.Table(&userTable{}, props.users).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -528,7 +528,6 @@ func getTeam(props getTeamProps) templ.Component { templ_7745c5c3_Err = components.UnpaginatedTable( &userTable{teamID: &props.team.ID, canRemoveMember: props.canRemoveMember}, props.members, - "team-members", ).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err @@ -563,7 +562,7 @@ func getTeam(props getTeamProps) templ.Component { var templ_7745c5c3_Var19 templ.SafeURL templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinURLErrs(paths.DeleteTeam(props.team.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/user_view.templ`, Line: 207, Col: 49} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/user_view.templ`, Line: 206, Col: 49} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) if templ_7745c5c3_Err != nil { @@ -576,7 +575,7 @@ func getTeam(props getTeamProps) templ.Component { var templ_7745c5c3_Var20 string templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(props.team.ID.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/user_view.templ`, Line: 211, Col: 65} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/user_view.templ`, Line: 210, Col: 65} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) if templ_7745c5c3_Err != nil { @@ -644,7 +643,7 @@ func newToken() templ.Component { var templ_7745c5c3_Var23 templ.SafeURL templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinURLErrs(paths.CreateToken()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/user_view.templ`, Line: 225, Col: 64} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/user_view.templ`, Line: 224, Col: 64} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) if templ_7745c5c3_Err != nil { @@ -706,7 +705,6 @@ func tokenList(tokens []*user.UserToken) templ.Component { templ_7745c5c3_Err = components.UnpaginatedTable( &tokensTable{}, tokens, - "tokens-table", ).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err @@ -755,7 +753,7 @@ func tokenListActions() templ.Component { var templ_7745c5c3_Var27 templ.SafeURL templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinURLErrs(paths.NewToken()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/user_view.templ`, Line: 254, Col: 32} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/user_view.templ`, Line: 252, Col: 32} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) if templ_7745c5c3_Err != nil { @@ -828,7 +826,7 @@ func (t tokensTable) Row(token *user.UserToken) templ.Component { var templ_7745c5c3_Var30 string templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(token.Description) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/user_view.templ`, Line: 271, Col: 28} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/user_view.templ`, Line: 269, Col: 28} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30)) if templ_7745c5c3_Err != nil { @@ -849,7 +847,7 @@ func (t tokensTable) Row(token *user.UserToken) templ.Component { var templ_7745c5c3_Var31 string templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(internal.Ago(time.Now(), token.CreatedAt)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/user_view.templ`, Line: 277, Col: 52} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/user_view.templ`, Line: 275, Col: 52} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31)) if templ_7745c5c3_Err != nil { @@ -862,7 +860,7 @@ func (t tokensTable) Row(token *user.UserToken) templ.Component { var templ_7745c5c3_Var32 templ.SafeURL templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinURLErrs(paths.DeleteToken()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/user_view.templ`, Line: 280, Col: 60} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/user_view.templ`, Line: 278, Col: 60} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32)) if templ_7745c5c3_Err != nil { @@ -883,7 +881,7 @@ func (t tokensTable) Row(token *user.UserToken) templ.Component { var templ_7745c5c3_Var33 string templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(token.ID.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/user_view.templ`, Line: 282, Col: 60} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/user_view.templ`, Line: 280, Col: 60} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33)) if templ_7745c5c3_Err != nil { diff --git a/internal/ui/variable_view.templ b/internal/ui/variable_view.templ index 98e557b2b..d47aff3fe 100644 --- a/internal/ui/variable_view.templ +++ b/internal/ui/variable_view.templ @@ -96,12 +96,11 @@ templ listWorkspaceVariables(props listWorkspaceVariablesProps) { }, }) { @components.UnpaginatedTable( - &table{ + &variablesTable{ canDeleteVariable: props.canCreateVariable, workspaceVariablesTable: true, }, props.rows, - "variables-table", ) if props.canCreateVariable {
@@ -127,7 +126,7 @@ templ listVariableSets(props listVariableSetsProps) { }, }) {
- @components.Table(&listVariableSetsTable{}, props.sets, "page-results") + @components.Table(&listVariableSetsTable{}, props.sets)
} } @@ -224,11 +223,10 @@ templ editVariableSet(props editVariableSetProps) {

Variables

@components.UnpaginatedTable( - &table{ + &variablesTable{ canDeleteVariable: props.canDeleteVariable, }, props.rows, - "variables-table", ) @@ -414,15 +412,14 @@ templ variableSetForm(props variableSetFormProps) {
} -// table of variables -type table struct { +type variablesTable struct { canDeleteVariable bool // workspaceVariablesTable is true if this is a table of variables for a // workspace, or false if this is a table of variables for a variable set. workspaceVariablesTable bool } -templ (t table) Header() { +templ (t variablesTable) Header() { if t.showVariableSetColumn() { Set } @@ -432,13 +429,13 @@ templ (t table) Header() { Actions } -func (t table) showVariableSetColumn() bool { +func (t variablesTable) showVariableSetColumn() bool { // Only show a column containing the name of the variable set on the // workspace variables table. return t.workspaceVariablesTable } -templ (t table) Row(v variableRow) { +templ (t variablesTable) Row(v variableRow) { if t.showVariableSetColumn() { @@ -483,14 +480,14 @@ templ (t table) Row(v variableRow) { } -func (t table) editPath(row variableRow) templ.SafeURL { +func (t variablesTable) editPath(row variableRow) templ.SafeURL { if row.set != nil { return paths.EditVariableSetVariable(row.ID) } return paths.EditVariable(row.ID) } -func (t table) deletePath(row variableRow) templ.SafeURL { +func (t variablesTable) deletePath(row variableRow) templ.SafeURL { if row.set != nil { return paths.DeleteVariableSetVariable(row.ID) } diff --git a/internal/ui/variable_view_templ.go b/internal/ui/variable_view_templ.go index b5f3f46fd..77ae57de5 100644 --- a/internal/ui/variable_view_templ.go +++ b/internal/ui/variable_view_templ.go @@ -258,12 +258,11 @@ func listWorkspaceVariables(props listWorkspaceVariablesProps) templ.Component { } ctx = templ.InitializeContext(ctx) templ_7745c5c3_Err = components.UnpaginatedTable( - &table{ + &variablesTable{ canDeleteVariable: props.canCreateVariable, workspaceVariablesTable: true, }, props.rows, - "variables-table", ).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err @@ -280,7 +279,7 @@ func listWorkspaceVariables(props listWorkspaceVariablesProps) templ.Component { var templ_7745c5c3_Var9 templ.SafeURL templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinURLErrs(paths.NewVariable(props.ws.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 107, Col: 61} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 106, Col: 61} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { @@ -353,7 +352,7 @@ func listVariableSets(props listVariableSetsProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = components.Table(&listVariableSetsTable{}, props.sets, "page-results").Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = components.Table(&listVariableSetsTable{}, props.sets).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -407,7 +406,7 @@ func listVariableSetsActions(props listVariableSetsProps) templ.Component { var templ_7745c5c3_Var13 templ.SafeURL templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinURLErrs(paths.NewVariableSet(props.organization)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 137, Col: 57} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 136, Col: 57} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) if templ_7745c5c3_Err != nil { @@ -481,7 +480,7 @@ func (t listVariableSetsTable) Row(vs *variable.VariableSet) templ.Component { var templ_7745c5c3_Var16 string templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs("item-variable-set-" + vs.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 154, Col: 40} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 153, Col: 40} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) if templ_7745c5c3_Err != nil { @@ -494,7 +493,7 @@ func (t listVariableSetsTable) Row(vs *variable.VariableSet) templ.Component { var templ_7745c5c3_Var17 templ.SafeURL templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinURLErrs(paths.EditVariableSet(vs.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 156, Col: 54} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 155, Col: 54} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) if templ_7745c5c3_Err != nil { @@ -507,7 +506,7 @@ func (t listVariableSetsTable) Row(vs *variable.VariableSet) templ.Component { var templ_7745c5c3_Var18 string templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(vs.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 157, Col: 13} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 156, Col: 13} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) if templ_7745c5c3_Err != nil { @@ -534,7 +533,7 @@ func (t listVariableSetsTable) Row(vs *variable.VariableSet) templ.Component { var templ_7745c5c3_Var19 string templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(len(vs.Workspaces)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 167, Col: 24} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 166, Col: 24} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) if templ_7745c5c3_Err != nil { @@ -682,11 +681,10 @@ func editVariableSet(props editVariableSetProps) templ.Component { return templ_7745c5c3_Err } templ_7745c5c3_Err = components.UnpaginatedTable( - &table{ + &variablesTable{ canDeleteVariable: props.canDeleteVariable, }, props.rows, - "variables-table", ).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err @@ -698,7 +696,7 @@ func editVariableSet(props editVariableSetProps) templ.Component { var templ_7745c5c3_Var24 templ.SafeURL templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinURLErrs(paths.NewVariableSetVariable(props.set.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 233, Col: 72} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 231, Col: 72} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) if templ_7745c5c3_Err != nil { @@ -831,7 +829,7 @@ func variableForm(props variableFormProps) templ.Component { var templ_7745c5c3_Var28 templ.SafeURL templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinURLErrs(props.action) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 273, Col: 56} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 271, Col: 56} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28)) if templ_7745c5c3_Err != nil { @@ -844,7 +842,7 @@ func variableForm(props variableFormProps) templ.Component { var templ_7745c5c3_Var29 string templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(props.variable.Key) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 276, Col: 82} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 274, Col: 82} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29)) if templ_7745c5c3_Err != nil { @@ -878,7 +876,7 @@ func variableForm(props variableFormProps) templ.Component { var templ_7745c5c3_Var30 string templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(props.variable.Value) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 290, Col: 27} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 288, Col: 27} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30)) if templ_7745c5c3_Err != nil { @@ -956,7 +954,7 @@ func variableForm(props variableFormProps) templ.Component { var templ_7745c5c3_Var31 string templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(props.variable.Description) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 319, Col: 123} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 317, Col: 123} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31)) if templ_7745c5c3_Err != nil { @@ -1006,7 +1004,7 @@ func variableSetForm(props variableSetFormProps) templ.Component { var templ_7745c5c3_Var33 templ.SafeURL templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinURLErrs(props.action) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 343, Col: 56} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 341, Col: 56} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33)) if templ_7745c5c3_Err != nil { @@ -1024,7 +1022,7 @@ func variableSetForm(props variableSetFormProps) templ.Component { var templ_7745c5c3_Var34 string templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(props.set.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 347, Col: 81} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 345, Col: 81} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34)) if templ_7745c5c3_Err != nil { @@ -1037,7 +1035,7 @@ func variableSetForm(props variableSetFormProps) templ.Component { var templ_7745c5c3_Var35 string templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.JoinStringErrs(props.set.Description) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 351, Col: 102} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 349, Col: 102} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35)) if templ_7745c5c3_Err != nil { @@ -1070,7 +1068,7 @@ func variableSetForm(props variableSetFormProps) templ.Component { var templ_7745c5c3_Var36 string templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(components.AssetPath(ctx, "/static/js/dropdown.js")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 364, Col: 70} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 362, Col: 70} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36)) if templ_7745c5c3_Err != nil { @@ -1083,7 +1081,7 @@ func variableSetForm(props variableSetFormProps) templ.Component { var templ_7745c5c3_Var37 string templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.JoinStringErrs("dropdown(" + toJSON(props.existingWorkspaces) + ", " + toJSON(props.availableWorkspaces) + ")") if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 367, Col: 110} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 365, Col: 110} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var37)) if templ_7745c5c3_Err != nil { @@ -1102,15 +1100,14 @@ func variableSetForm(props variableSetFormProps) templ.Component { }) } -// table of variables -type table struct { +type variablesTable struct { canDeleteVariable bool // workspaceVariablesTable is true if this is a table of variables for a // workspace, or false if this is a table of variables for a variable set. workspaceVariablesTable bool } -func (t table) Header() templ.Component { +func (t variablesTable) Header() templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -1145,13 +1142,13 @@ func (t table) Header() templ.Component { }) } -func (t table) showVariableSetColumn() bool { +func (t variablesTable) showVariableSetColumn() bool { // Only show a column containing the name of the variable set on the // workspace variables table. return t.workspaceVariablesTable } -func (t table) Row(v variableRow) templ.Component { +func (t variablesTable) Row(v variableRow) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -1179,7 +1176,7 @@ func (t table) Row(v variableRow) templ.Component { var templ_7745c5c3_Var40 string templ_7745c5c3_Var40, templ_7745c5c3_Err = templ.JoinStringErrs("item-variable-" + v.Key) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 442, Col: 34} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 439, Col: 34} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var40)) if templ_7745c5c3_Err != nil { @@ -1202,7 +1199,7 @@ func (t table) Row(v variableRow) templ.Component { var templ_7745c5c3_Var41 templ.SafeURL templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.JoinURLErrs(paths.EditVariableSet(v.set.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 446, Col: 59} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 443, Col: 59} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var41)) if templ_7745c5c3_Err != nil { @@ -1215,7 +1212,7 @@ func (t table) Row(v variableRow) templ.Component { var templ_7745c5c3_Var42 string templ_7745c5c3_Var42, templ_7745c5c3_Err = templ.JoinStringErrs(v.set.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 447, Col: 18} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 444, Col: 18} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var42)) if templ_7745c5c3_Err != nil { @@ -1261,7 +1258,7 @@ func (t table) Row(v variableRow) templ.Component { var templ_7745c5c3_Var44 string templ_7745c5c3_Var44, templ_7745c5c3_Err = templ.JoinStringErrs(v.Key) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 459, Col: 11} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 456, Col: 11} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var44)) if templ_7745c5c3_Err != nil { @@ -1286,7 +1283,7 @@ func (t table) Row(v variableRow) templ.Component { var templ_7745c5c3_Var45 string templ_7745c5c3_Var45, templ_7745c5c3_Err = templ.JoinStringErrs(v.Value) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 466, Col: 13} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 463, Col: 13} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var45)) if templ_7745c5c3_Err != nil { @@ -1300,7 +1297,7 @@ func (t table) Row(v variableRow) templ.Component { var templ_7745c5c3_Var46 string templ_7745c5c3_Var46, templ_7745c5c3_Err = templ.JoinStringErrs(string(v.Category)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 469, Col: 26} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 466, Col: 26} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var46)) if templ_7745c5c3_Err != nil { @@ -1313,7 +1310,7 @@ func (t table) Row(v variableRow) templ.Component { var templ_7745c5c3_Var47 templ.SafeURL templ_7745c5c3_Var47, templ_7745c5c3_Err = templ.JoinURLErrs(t.editPath(v)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 471, Col: 53} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 468, Col: 53} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var47)) if templ_7745c5c3_Err != nil { @@ -1339,7 +1336,7 @@ func (t table) Row(v variableRow) templ.Component { var templ_7745c5c3_Var48 templ.SafeURL templ_7745c5c3_Var48, templ_7745c5c3_Err = templ.JoinURLErrs(t.deletePath(v)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 478, Col: 58} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/variable_view.templ`, Line: 475, Col: 58} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var48)) if templ_7745c5c3_Err != nil { @@ -1366,14 +1363,14 @@ func (t table) Row(v variableRow) templ.Component { }) } -func (t table) editPath(row variableRow) templ.SafeURL { +func (t variablesTable) editPath(row variableRow) templ.SafeURL { if row.set != nil { return paths.EditVariableSetVariable(row.ID) } return paths.EditVariable(row.ID) } -func (t table) deletePath(row variableRow) templ.SafeURL { +func (t variablesTable) deletePath(row variableRow) templ.SafeURL { if row.set != nil { return paths.DeleteVariableSetVariable(row.ID) } diff --git a/internal/ui/vcs_view.templ b/internal/ui/vcs_view.templ index 5c6ff6695..6a497d376 100644 --- a/internal/ui/vcs_view.templ +++ b/internal/ui/vcs_view.templ @@ -43,7 +43,6 @@ templ list(props listProps) { @components.Table( &vcsTable{Actions: tableAction}, props.providers, - "page-results", ) } diff --git a/internal/ui/vcs_view_templ.go b/internal/ui/vcs_view_templ.go index 3ef2112db..824c271da 100644 --- a/internal/ui/vcs_view_templ.go +++ b/internal/ui/vcs_view_templ.go @@ -122,7 +122,6 @@ func list(props listProps) templ.Component { templ_7745c5c3_Err = components.Table( &vcsTable{Actions: tableAction}, props.providers, - "page-results", ).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err @@ -208,7 +207,7 @@ func (t vcsTable) Row(provider *vcs.Provider) templ.Component { var templ_7745c5c3_Var8 string templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs("item-vcsprovider-" + provider.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 64, Col: 49} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 63, Col: 49} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { @@ -229,7 +228,7 @@ func (t vcsTable) Row(provider *vcs.Provider) templ.Component { var templ_7745c5c3_Var9 templ.SafeURL templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinURLErrs(paths.EditVCSProvider(provider.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 68, Col: 61} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 67, Col: 61} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { @@ -242,7 +241,7 @@ func (t vcsTable) Row(provider *vcs.Provider) templ.Component { var templ_7745c5c3_Var10 string templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(provider.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 69, Col: 24} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 68, Col: 24} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) if templ_7745c5c3_Err != nil { @@ -263,7 +262,7 @@ func (t vcsTable) Row(provider *vcs.Provider) templ.Component { var templ_7745c5c3_Var11 string templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(internal.Ago(time.Now(), provider.CreatedAt)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 77, Col: 49} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 76, Col: 49} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { @@ -313,7 +312,7 @@ func tableAction(vcsProviderID resource.TfeID) templ.Component { var templ_7745c5c3_Var13 templ.SafeURL templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinURLErrs(paths.EditVCSProvider(vcsProviderID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 86, Col: 75} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 85, Col: 75} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) if templ_7745c5c3_Err != nil { @@ -334,7 +333,7 @@ func tableAction(vcsProviderID resource.TfeID) templ.Component { var templ_7745c5c3_Var14 string templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(vcsProviderID.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 88, Col: 63} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 87, Col: 63} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) if templ_7745c5c3_Err != nil { @@ -396,7 +395,7 @@ func edit(provider *vcs.Provider) templ.Component { var templ_7745c5c3_Var17 templ.SafeURL templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinURLErrs(paths.DeleteVCSProvider(provider.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 109, Col: 53} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 108, Col: 53} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) if templ_7745c5c3_Err != nil { @@ -528,7 +527,7 @@ func vcsForm(props vcsFormProps) templ.Component { var templ_7745c5c3_Var21 string templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(internal.Title(string(props.provider.Kind.ID))) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 147, Col: 65} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 146, Col: 65} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) if templ_7745c5c3_Err != nil { @@ -560,7 +559,7 @@ func vcsForm(props vcsFormProps) templ.Component { var templ_7745c5c3_Var22 templ.SafeURL templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinURLErrs(paths.NewGithubApp()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 166, Col: 86} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 165, Col: 86} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) if templ_7745c5c3_Err != nil { @@ -578,7 +577,7 @@ func vcsForm(props vcsFormProps) templ.Component { var templ_7745c5c3_Var23 templ.SafeURL templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinURLErrs(props.action) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 169, Col: 57} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 168, Col: 57} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) if templ_7745c5c3_Err != nil { @@ -591,7 +590,7 @@ func vcsForm(props vcsFormProps) templ.Component { var templ_7745c5c3_Var24 string templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(props.provider.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 177, Col: 36} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 176, Col: 36} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) if templ_7745c5c3_Err != nil { @@ -639,7 +638,7 @@ func vcsForm(props vcsFormProps) templ.Component { var templ_7745c5c3_Var25 string templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(props.provider.Installation.ID) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 205, Col: 129} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 204, Col: 129} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) if templ_7745c5c3_Err != nil { @@ -668,7 +667,7 @@ func vcsForm(props vcsFormProps) templ.Component { var templ_7745c5c3_Var26 string templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(install.ID) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 219, Col: 35} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 218, Col: 35} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) if templ_7745c5c3_Err != nil { @@ -681,7 +680,7 @@ func vcsForm(props vcsFormProps) templ.Component { var templ_7745c5c3_Var27 string templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(install.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 220, Col: 28} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 219, Col: 28} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) if templ_7745c5c3_Err != nil { @@ -704,7 +703,7 @@ func vcsForm(props vcsFormProps) templ.Component { var templ_7745c5c3_Var28 templ.SafeURL templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinURLErrs(app.InstallationLink()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 227, Col: 97} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 226, Col: 97} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28)) if templ_7745c5c3_Err != nil { @@ -729,7 +728,7 @@ func vcsForm(props vcsFormProps) templ.Component { var templ_7745c5c3_Var29 string templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(props.provider.BaseURL.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 238, Col: 45} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 237, Col: 45} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29)) if templ_7745c5c3_Err != nil { @@ -747,7 +746,7 @@ func vcsForm(props vcsFormProps) templ.Component { var templ_7745c5c3_Var30 string templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(props.provider.DefaultURL.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 240, Col: 48} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 239, Col: 48} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30)) if templ_7745c5c3_Err != nil { @@ -791,7 +790,7 @@ func vcsForm(props vcsFormProps) templ.Component { var templ_7745c5c3_Var31 string templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(string(props.provider.Kind.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 257, Col: 85} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/vcs_view.templ`, Line: 256, Col: 85} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31)) if templ_7745c5c3_Err != nil { diff --git a/internal/ui/workspace.go b/internal/ui/workspace.go index 1fad7e1a6..2207c14fa 100644 --- a/internal/ui/workspace.go +++ b/internal/ui/workspace.go @@ -6,8 +6,6 @@ import ( "net/http" "time" - "github.com/gorilla/websocket" - "github.com/a-h/templ" "github.com/go-logr/logr" "github.com/gorilla/mux" @@ -21,6 +19,7 @@ import ( "github.com/leg100/otf/internal/organization" "github.com/leg100/otf/internal/pubsub" "github.com/leg100/otf/internal/resource" + "github.com/leg100/otf/internal/run" "github.com/leg100/otf/internal/team" "github.com/leg100/otf/internal/user" "github.com/leg100/otf/internal/vcs" @@ -51,13 +50,14 @@ const ( type ( workspaceHandlers struct { *workspaceUIHelpers - logger logr.Logger - teams workspaceTeamClient - vcsproviders workspaceVCSProvidersClient - client workspaceClient - authorizer workspaceAuthorizer - releases workspaceEngineClient - websocketListHandler *components.WebsocketListHandler[*workspace.Workspace, *workspace.Event, workspace.ListOptions] + logger logr.Logger + teams workspaceTeamClient + vcsproviders workspaceVCSProvidersClient + client workspaceClient + authorizer workspaceAuthorizer + releases workspaceEngineClient + runs workspaceRunClient + users workspaceUserClient } workspaceTeamClient interface { @@ -97,6 +97,14 @@ type ( UnsetPermission(ctx context.Context, workspaceID, teamID resource.TfeID) error Watch(context.Context) (<-chan pubsub.Event[*workspace.Event], func()) } + + workspaceRunClient interface { + Get(ctx context.Context, id resource.TfeID) (*run.Run, error) + } + + workspaceUserClient interface { + GetUser(ctx context.Context, spec user.UserSpec) (*user.User, error) + } ) // addWorkspaceHandlers registers workspace UI handlers with the router @@ -108,6 +116,8 @@ func addWorkspaceHandlers( vcsproviders workspaceVCSProvidersClient, authorizer workspaceAuthorizer, releases workspaceEngineClient, + runs workspaceRunClient, + users workspaceUserClient, ) { h := &workspaceHandlers{ workspaceUIHelpers: &workspaceUIHelpers{ @@ -118,13 +128,9 @@ func addWorkspaceHandlers( teams: teams, vcsproviders: vcsproviders, client: workspaces, - websocketListHandler: &components.WebsocketListHandler[*workspace.Workspace, *workspace.Event, workspace.ListOptions]{ - Logger: logger, - Client: workspaces, - Populator: &workspaceTable{}, - ID: "page-results", - }, - releases: releases, + releases: releases, + runs: runs, + users: users, } r.HandleFunc("/organizations/{organization_name}/workspaces", h.listWorkspaces).Methods("GET") @@ -152,11 +158,6 @@ func addWorkspaceHandlers( } func (h *workspaceHandlers) listWorkspaces(w http.ResponseWriter, r *http.Request) { - if websocket.IsWebSocketUpgrade(r) { - h.websocketListHandler.Handler(w, r) - return - } - var params struct { workspace.ListOptions StatusFilterVisible bool `schema:"status_filter_visible"` @@ -182,6 +183,12 @@ func (h *workspaceHandlers) listWorkspaces(w http.ResponseWriter, r *http.Reques tagStrings[i] = tag.Name } + page, err := h.client.List(r.Context(), params.ListOptions) + if err != nil { + html.Error(r, w, err.Error()) + return + } + props := workspaceListProps{ organization: *params.Organization, allTags: tagStrings, @@ -196,6 +203,7 @@ func (h *workspaceHandlers) listWorkspaces(w http.ResponseWriter, r *http.Reques params.Organization, ), pageOptions: params.PageOptions, + page: page, } html.Render(workspaceList(props), w, r) @@ -286,6 +294,17 @@ func (h *workspaceHandlers) getWorkspace(w http.ResponseWriter, r *http.Request) return } + // get latest run if there is one. + var latestRun *run.Run + if ws.LatestRun != nil { + run, err := h.runs.Get(r.Context(), ws.LatestRun.ID) + if err != nil { + html.Error(r, w, err.Error()) + return + } + latestRun = run + } + props := workspaceGetProps{ ws: ws, workspaceLockInfo: lockInfo, @@ -305,6 +324,8 @@ func (h *workspaceHandlers) getWorkspace(w http.ResponseWriter, r *http.Request) Placeholder: "Add tags", Width: components.NarrowDropDown, }, + latestRun: latestRun, + users: h.users, } html.Render(workspaceGet(props), w, r) } diff --git a/internal/ui/workspace_view.templ b/internal/ui/workspace_view.templ index b3e7b05fe..2cead0cb4 100644 --- a/internal/ui/workspace_view.templ +++ b/internal/ui/workspace_view.templ @@ -9,6 +9,7 @@ import ( "github.com/leg100/otf/internal/http/html/components/paths" "github.com/leg100/otf/internal/organization" "github.com/leg100/otf/internal/resource" + "github.com/leg100/otf/internal/run" "github.com/leg100/otf/internal/runstatus" "github.com/leg100/otf/internal/team" "github.com/leg100/otf/internal/vcs" @@ -46,40 +47,36 @@ type workspaceListProps struct { statusFilterVisible bool tagFilterVisible bool pageOptions resource.PageOptions + page *resource.Page[*workspace.Workspace] } templ workspaceList(props workspaceListProps) { {{ - layoutProps := components.LayoutProps{ - Title: "workspaces", - Organization: props.organization, - ContentLinks: workspaceListActions(props.organization, props.canCreate), - Breadcrumbs: []components.Breadcrumb{ - {Name: "Workspaces"}, - }, - } + layoutProps := components.LayoutProps{ + Title: "workspaces", + Organization: props.organization, + ContentLinks: workspaceListActions(props.organization, props.canCreate), + Breadcrumbs: []components.Breadcrumb{ + {Name: "Workspaces"}, + }, + } }} @components.Layout(layoutProps) { -
+
-
- -
+ @runstatus.Filter(props.status, props.statusFilterVisible) @components.Filter(components.FilterProps[string]{ Title: "Filter by tag", @@ -94,20 +91,20 @@ templ workspaceList(props workspaceListProps) { }, })
+ @components.PollingTable(workspacesTable{}, props.page)
-
} } -type workspaceTable struct{} +type workspacesTable struct{} -templ (t workspaceTable) Header() { +templ (t workspacesTable) Header() { Name Status Tags } -templ (t workspaceTable) Row(ws *workspace.Workspace) { +templ (t workspacesTable) Row(ws *workspace.Workspace) { { ws.Name } @@ -165,19 +162,21 @@ type workspaceGetProps struct { canUpdateWorkspace bool unassignedTags []string tagsDropdown components.SearchDropdownProps + latestRun *run.Run + users workspaceUserClient } templ workspaceGet(props workspaceGetProps) { {{ - layoutProps := components.LayoutProps{ - Title: "workspaces", - Organization: props.ws.Organization, - ContentLinks: workspaceHeaderLinksAndStartRunSelector(props), - Breadcrumbs: []components.Breadcrumb{ - {Name: "Workspaces"}, - {Name: props.ws.Name}, - }, - } + layoutProps := components.LayoutProps{ + Title: "workspaces", + Organization: props.ws.Organization, + ContentLinks: workspaceHeaderLinksAndStartRunSelector(props), + Breadcrumbs: []components.Breadcrumb{ + {Name: "Workspaces"}, + {Name: props.ws.Name}, + }, + } }} @components.Layout(layoutProps) {
@@ -193,11 +192,11 @@ templ workspaceGet(props workspaceGetProps) { Latest Run
- if props.ws.LatestRun != nil { -
+ if props.latestRun != nil { + @components.UnpaginatedTable(&runsTable{users: props.users}, []*run.Run{props.latestRun}) } else { There are no runs for this workspace. } @@ -397,16 +396,16 @@ type workspacePerm struct { templ workspaceEdit(props workspaceEditProps) { {{ - layoutProps := components.LayoutProps{ - Title: "edit | " + props.ws.ID.String(), - Organization: props.ws.Organization, - ContentLinks: WorkspaceHeaderLinks(props.ws.ID, props.canUpdateWorkspace), - Breadcrumbs: []components.Breadcrumb{ - {Name: "Workspaces", Link: paths.Workspaces(props.ws.Organization)}, - {Name: props.ws.Name, Link: paths.Workspace(props.ws.ID)}, - {Name: "settings"}, - }, - } + layoutProps := components.LayoutProps{ + Title: "edit | " + props.ws.ID.String(), + Organization: props.ws.Organization, + ContentLinks: WorkspaceHeaderLinks(props.ws.ID, props.canUpdateWorkspace), + Breadcrumbs: []components.Breadcrumb{ + {Name: "Workspaces", Link: paths.Workspaces(props.ws.Organization)}, + {Name: props.ws.Name, Link: paths.Workspace(props.ws.ID)}, + {Name: "settings"}, + }, + } }} @components.Layout(layoutProps) {
@@ -737,15 +736,15 @@ templ editPermissions(props workspaceEditProps) { templ listVCSProviders(ws *workspace.Workspace, providers []*vcs.Provider) { {{ - layoutProps := components.LayoutProps{ - Title: "list vcs providers | " + ws.ID.String(), - Organization: ws.Organization, - Breadcrumbs: []components.Breadcrumb{ - {Name: "workspaces", Link: paths.Workspaces(ws.Organization)}, - {Name: ws.Name, Link: paths.Workspace(ws.ID)}, - {Name: "vcs providers"}, - }, - } + layoutProps := components.LayoutProps{ + Title: "list vcs providers | " + ws.ID.String(), + Organization: ws.Organization, + Breadcrumbs: []components.Breadcrumb{ + {Name: "workspaces", Link: paths.Workspaces(ws.Organization)}, + {Name: ws.Name, Link: paths.Workspace(ws.ID)}, + {Name: "vcs providers"}, + }, + } }} @components.Layout(layoutProps) { @ConnectionSteps(ConnectStep) @@ -755,7 +754,6 @@ templ listVCSProviders(ws *workspace.Workspace, providers []*vcs.Provider) { Actions: vcsProviderSelector{workspaceID: ws.ID}.action, }, providers, - "vcs-providers-table", ) if len(providers) == 0 { @@ -778,15 +776,15 @@ templ (s vcsProviderSelector) action(vcsProviderID resource.TfeID) { templ listVCSRepos(ws *workspace.Workspace, vcsProviderID resource.TfeID, repos []vcs.Repo) { {{ - layoutProps := components.LayoutProps{ - Title: "list vcs repos | " + ws.ID.String(), - Organization: ws.Organization, - Breadcrumbs: []components.Breadcrumb{ - {Name: "workspaces", Link: paths.Workspaces(ws.Organization)}, - {Name: ws.Name, Link: paths.Workspace(ws.ID)}, - {Name: "vcs repositories"}, - }, - } + layoutProps := components.LayoutProps{ + Title: "list vcs repos | " + ws.ID.String(), + Organization: ws.Organization, + Breadcrumbs: []components.Breadcrumb{ + {Name: "workspaces", Link: paths.Workspaces(ws.Organization)}, + {Name: ws.Name, Link: paths.Workspace(ws.ID)}, + {Name: "vcs repositories"}, + }, + } }} @components.Layout(layoutProps) { @ConnectionSteps(SelectRepoStep) @@ -806,7 +804,6 @@ templ listVCSRepos(ws *workspace.Workspace, vcsProviderID resource.TfeID, repos }.action, }, repos, - "repos-table", ) } } diff --git a/internal/ui/workspace_view_templ.go b/internal/ui/workspace_view_templ.go index 6303d04ff..f37ec3422 100644 --- a/internal/ui/workspace_view_templ.go +++ b/internal/ui/workspace_view_templ.go @@ -17,6 +17,7 @@ import ( "github.com/leg100/otf/internal/http/html/components/paths" "github.com/leg100/otf/internal/organization" "github.com/leg100/otf/internal/resource" + "github.com/leg100/otf/internal/run" "github.com/leg100/otf/internal/runstatus" "github.com/leg100/otf/internal/team" "github.com/leg100/otf/internal/vcs" @@ -63,7 +64,7 @@ func workspaceNew(organization organization.Name) templ.Component { var templ_7745c5c3_Var3 templ.SafeURL templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(paths.CreateWorkspace(organization)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 27, Col: 80} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 28, Col: 80} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { @@ -100,6 +101,7 @@ type workspaceListProps struct { statusFilterVisible bool tagFilterVisible bool pageOptions resource.PageOptions + page *resource.Page[*workspace.Workspace] } func workspaceList(props workspaceListProps) templ.Component { @@ -151,52 +153,52 @@ func workspaceList(props workspaceListProps) templ.Component { var templ_7745c5c3_Var6 templ.SafeURL templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(paths.Workspaces(props.organization)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 64, Col: 48} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 65, Col: 53} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" hx-ext=\"ws\" ws-connect=\"") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" hx-include=\"this\" class=\"flex flex-col gap-2\">
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\" hx-target=\"#polling-table\" id=\"workspace-search\" onblur=\"if (this.defaultValue != this.value) { this.form.submit() }\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -219,7 +221,15 @@ func workspaceList(props workspaceListProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = components.PollingTable(workspacesTable{}, props.page).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -233,9 +243,9 @@ func workspaceList(props workspaceListProps) templ.Component { }) } -type workspaceTable struct{} +type workspacesTable struct{} -func (t workspaceTable) Header() templ.Component { +func (t workspacesTable) Header() templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -256,7 +266,7 @@ func (t workspaceTable) Header() templ.Component { templ_7745c5c3_Var10 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "NameStatusTags") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "NameStatusTags") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -264,7 +274,7 @@ func (t workspaceTable) Header() templ.Component { }) } -func (t workspaceTable) Row(ws *workspace.Workspace) templ.Component { +func (t workspacesTable) Row(ws *workspace.Workspace) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -285,46 +295,46 @@ func (t workspaceTable) Row(ws *workspace.Workspace) templ.Component { templ_7745c5c3_Var11 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var14 string templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(ws.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 113, Col: 60} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 110, Col: 60} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -334,7 +344,7 @@ func (t workspaceTable) Row(ws *workspace.Workspace) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -344,7 +354,7 @@ func (t workspaceTable) Row(ws *workspace.Workspace) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -373,33 +383,33 @@ func tag(name string) templ.Component { templ_7745c5c3_Var15 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "\" class=\"badge badge-accent badge-soft badge-md\"> ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var17 string templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 143, Col: 8} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 140, Col: 8} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -429,20 +439,20 @@ func workspaceListActions(organization organization.Name, canCreate bool) templ. } ctx = templ.ClearChildren(ctx) if canCreate { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "\" method=\"GET\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -464,6 +474,8 @@ type workspaceGetProps struct { canUpdateWorkspace bool unassignedTags []string tagsDropdown components.SearchDropdownProps + latestRun *run.Run + users workspaceUserClient } func workspaceGet(props workspaceGetProps) templ.Component { @@ -509,7 +521,7 @@ func workspaceGet(props workspaceGetProps) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -520,25 +532,25 @@ func workspaceGet(props workspaceGetProps) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "

Latest Run

Latest Run

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - if props.ws.LatestRun != nil { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "
") + if props.latestRun != nil { + templ_7745c5c3_Err = components.UnpaginatedTable(&runsTable{users: props.users}, []*run.Run{props.latestRun}).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -555,7 +567,7 @@ func workspaceGet(props workspaceGetProps) templ.Component { var templ_7745c5c3_Var23 string templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(string(paths.StateWorkspace(props.ws.ID))) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 207, Col: 60} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 206, Col: 60} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) if templ_7745c5c3_Err != nil { @@ -576,7 +588,7 @@ func workspaceGet(props workspaceGetProps) templ.Component { var templ_7745c5c3_Var24 templ.SafeURL templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinURLErrs(paths.EditWorkspace(props.ws.ID) + "#engine-version-field") if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 221, Col: 72} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 220, Col: 72} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) if templ_7745c5c3_Err != nil { @@ -589,7 +601,7 @@ func workspaceGet(props workspaceGetProps) templ.Component { var templ_7745c5c3_Var25 string templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(props.ws.Engine.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 225, Col: 34} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 224, Col: 34} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) if templ_7745c5c3_Err != nil { @@ -602,7 +614,7 @@ func workspaceGet(props workspaceGetProps) templ.Component { var templ_7745c5c3_Var26 templ.SafeURL templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinURLErrs(paths.EditWorkspace(props.ws.ID) + "#engine-version-field") if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 230, Col: 72} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 229, Col: 72} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) if templ_7745c5c3_Err != nil { @@ -615,7 +627,7 @@ func workspaceGet(props workspaceGetProps) templ.Component { var templ_7745c5c3_Var27 string templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(props.ws.EngineVersion.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 234, Col: 41} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 233, Col: 41} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) if templ_7745c5c3_Err != nil { @@ -641,7 +653,7 @@ func workspaceGet(props workspaceGetProps) templ.Component { var templ_7745c5c3_Var28 templ.SafeURL templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinURLErrs(RepoURL(props.vcsProvider, props.ws.Connection.Repo)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 247, Col: 67} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 246, Col: 67} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28)) if templ_7745c5c3_Err != nil { @@ -654,7 +666,7 @@ func workspaceGet(props workspaceGetProps) templ.Component { var templ_7745c5c3_Var29 string templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(props.ws.Connection.Repo.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 250, Col: 43} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 249, Col: 43} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29)) if templ_7745c5c3_Err != nil { @@ -680,7 +692,7 @@ func workspaceGet(props workspaceGetProps) templ.Component { var templ_7745c5c3_Var30 templ.SafeURL templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinURLErrs(paths.DeleteTagWorkspace(props.ws.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 259, Col: 57} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 258, Col: 57} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30)) if templ_7745c5c3_Err != nil { @@ -702,7 +714,7 @@ func workspaceGet(props workspaceGetProps) templ.Component { var templ_7745c5c3_Var31 string templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 268, Col: 22} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 267, Col: 22} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31)) if templ_7745c5c3_Err != nil { @@ -818,7 +830,7 @@ func lockWidget(props lockWidgetProps) templ.Component { var templ_7745c5c3_Var35 templ.SafeURL templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.JoinURLErrs(paths.Run(props.ws.Lock)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 319, Col: 65} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 318, Col: 65} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35)) if templ_7745c5c3_Err != nil { @@ -831,7 +843,7 @@ func lockWidget(props lockWidgetProps) templ.Component { var templ_7745c5c3_Var36 string templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(props.ws.Lock.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 320, Col: 32} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 319, Col: 32} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36)) if templ_7745c5c3_Err != nil { @@ -849,7 +861,7 @@ func lockWidget(props lockWidgetProps) templ.Component { var templ_7745c5c3_Var37 string templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.JoinStringErrs(props.ws.Lock.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 323, Col: 41} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 322, Col: 41} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var37)) if templ_7745c5c3_Err != nil { @@ -869,7 +881,7 @@ func lockWidget(props lockWidgetProps) templ.Component { var templ_7745c5c3_Var38 templ.SafeURL templ_7745c5c3_Var38, templ_7745c5c3_Err = templ.JoinURLErrs(props.info.Action) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 330, Col: 34} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 329, Col: 34} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var38)) if templ_7745c5c3_Err != nil { @@ -892,7 +904,7 @@ func lockWidget(props lockWidgetProps) templ.Component { var templ_7745c5c3_Var39 string templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.JoinStringErrs(props.info.Tooltip) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 335, Col: 30} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 334, Col: 30} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var39)) if templ_7745c5c3_Err != nil { @@ -1068,7 +1080,7 @@ func workspaceEdit(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var44 templ.SafeURL templ_7745c5c3_Var44, templ_7745c5c3_Err = templ.JoinURLErrs(paths.DisconnectWorkspace(props.ws.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 414, Col: 57} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 413, Col: 57} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var44)) if templ_7745c5c3_Err != nil { @@ -1081,7 +1093,7 @@ func workspaceEdit(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var45 string templ_7745c5c3_Var45, templ_7745c5c3_Err = templ.JoinStringErrs(props.ws.Connection.Repo.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 416, Col: 57} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 415, Col: 57} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var45)) if templ_7745c5c3_Err != nil { @@ -1094,7 +1106,7 @@ func workspaceEdit(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var46 string templ_7745c5c3_Var46, templ_7745c5c3_Err = templ.JoinStringErrs(props.vcsProvider.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 416, Col: 89} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 415, Col: 89} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var46)) if templ_7745c5c3_Err != nil { @@ -1112,7 +1124,7 @@ func workspaceEdit(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var47 templ.SafeURL templ_7745c5c3_Var47, templ_7745c5c3_Err = templ.JoinURLErrs(paths.SetupConnectionProviderWorkspace(props.ws.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 420, Col: 70} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 419, Col: 70} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var47)) if templ_7745c5c3_Err != nil { @@ -1130,7 +1142,7 @@ func workspaceEdit(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var48 templ.SafeURL templ_7745c5c3_Var48, templ_7745c5c3_Err = templ.JoinURLErrs(paths.UpdateWorkspace(props.ws.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 428, Col: 79} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 427, Col: 79} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var48)) if templ_7745c5c3_Err != nil { @@ -1143,7 +1155,7 @@ func workspaceEdit(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var49 string templ_7745c5c3_Var49, templ_7745c5c3_Err = templ.JoinStringErrs(props.ws.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 431, Col: 85} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 430, Col: 85} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var49)) if templ_7745c5c3_Err != nil { @@ -1156,7 +1168,7 @@ func workspaceEdit(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var50 string templ_7745c5c3_Var50, templ_7745c5c3_Err = templ.JoinStringErrs(props.ws.Description) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 435, Col: 103} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 434, Col: 103} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var50)) if templ_7745c5c3_Err != nil { @@ -1199,7 +1211,7 @@ func workspaceEdit(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var51 string templ_7745c5c3_Var51, templ_7745c5c3_Err = templ.JoinStringErrs(props.poolsURL) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 458, Col: 35} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 457, Col: 35} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var51)) if templ_7745c5c3_Err != nil { @@ -1212,7 +1224,7 @@ func workspaceEdit(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var52 templ.SafeURL templ_7745c5c3_Var52, templ_7745c5c3_Err = templ.JoinURLErrs(paths.AgentPools(props.ws.Organization)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 460, Col: 301} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 459, Col: 301} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var52)) if templ_7745c5c3_Err != nil { @@ -1253,7 +1265,7 @@ func workspaceEdit(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var53 string templ_7745c5c3_Var53, templ_7745c5c3_Err = templ.JoinStringErrs(props.ws.WorkingDirectory) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 480, Col: 123} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 479, Col: 123} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var53)) if templ_7745c5c3_Err != nil { @@ -1294,7 +1306,7 @@ func workspaceEdit(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var54 templ.SafeURL templ_7745c5c3_Var54, templ_7745c5c3_Err = templ.JoinURLErrs(paths.StartRunWorkspace(props.ws.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 505, Col: 54} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 504, Col: 54} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var54)) if templ_7745c5c3_Err != nil { @@ -1307,7 +1319,7 @@ func workspaceEdit(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var55 string templ_7745c5c3_Var55, templ_7745c5c3_Err = templ.JoinStringErrs(workspaceBoolString(props.ws.Connection != nil)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 509, Col: 97} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 508, Col: 97} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var55)) if templ_7745c5c3_Err != nil { @@ -1325,7 +1337,7 @@ func workspaceEdit(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var56 templ.SafeURL templ_7745c5c3_Var56, templ_7745c5c3_Err = templ.JoinURLErrs(paths.DeleteWorkspace(props.ws.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 513, Col: 53} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 512, Col: 53} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var56)) if templ_7745c5c3_Err != nil { @@ -1389,7 +1401,7 @@ func engineSelector(props engineSelectorProps) templ.Component { var templ_7745c5c3_Var58 string templ_7745c5c3_Var58, templ_7745c5c3_Err = templ.JoinStringErrs("{current: '" + props.current + "', isCurrent(engine){ return engine == this.current }}") if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 535, Col: 131} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 534, Col: 131} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var58)) if templ_7745c5c3_Err != nil { @@ -1407,7 +1419,7 @@ func engineSelector(props engineSelectorProps) templ.Component { var templ_7745c5c3_Var59 string templ_7745c5c3_Var59, templ_7745c5c3_Err = templ.JoinStringErrs(engine.name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 540, Col: 55} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 539, Col: 55} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var59)) if templ_7745c5c3_Err != nil { @@ -1420,7 +1432,7 @@ func engineSelector(props engineSelectorProps) templ.Component { var templ_7745c5c3_Var60 string templ_7745c5c3_Var60, templ_7745c5c3_Err = templ.JoinStringErrs(engine.name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 540, Col: 77} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 539, Col: 77} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var60)) if templ_7745c5c3_Err != nil { @@ -1433,7 +1445,7 @@ func engineSelector(props engineSelectorProps) templ.Component { var templ_7745c5c3_Var61 string templ_7745c5c3_Var61, templ_7745c5c3_Err = templ.JoinStringErrs("isCurrent('" + engine.name + "')") if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 540, Col: 143} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 539, Col: 143} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var61)) if templ_7745c5c3_Err != nil { @@ -1446,7 +1458,7 @@ func engineSelector(props engineSelectorProps) templ.Component { var templ_7745c5c3_Var62 string templ_7745c5c3_Var62, templ_7745c5c3_Err = templ.JoinStringErrs(engine.name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 541, Col: 29} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 540, Col: 29} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var62)) if templ_7745c5c3_Err != nil { @@ -1459,7 +1471,7 @@ func engineSelector(props engineSelectorProps) templ.Component { var templ_7745c5c3_Var63 string templ_7745c5c3_Var63, templ_7745c5c3_Err = templ.JoinStringErrs(internal.Title(engine.name)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 541, Col: 61} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 540, Col: 61} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var63)) if templ_7745c5c3_Err != nil { @@ -1498,7 +1510,7 @@ func engineSelector(props engineSelectorProps) templ.Component { var templ_7745c5c3_Var64 string templ_7745c5c3_Var64, templ_7745c5c3_Err = templ.JoinStringErrs("isCurrent('" + engine.name + "')") if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 555, Col: 54} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 554, Col: 54} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var64)) if templ_7745c5c3_Err != nil { @@ -1581,7 +1593,7 @@ func engineVersionSelector(props engineSelectorEngine) templ.Component { var templ_7745c5c3_Var68 string templ_7745c5c3_Var68, templ_7745c5c3_Err = templ.JoinStringErrs(props.version) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 574, Col: 25} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 573, Col: 25} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var68)) if templ_7745c5c3_Err != nil { @@ -1633,7 +1645,7 @@ func editConnection(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var70 string templ_7745c5c3_Var70, templ_7745c5c3_Err = templ.JoinStringErrs(props.vcsTriggerAlways) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 594, Col: 97} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 593, Col: 97} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var70)) if templ_7745c5c3_Err != nil { @@ -1656,7 +1668,7 @@ func editConnection(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var71 string templ_7745c5c3_Var71, templ_7745c5c3_Err = templ.JoinStringErrs(props.vcsTriggerPatterns) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 599, Col: 114} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 598, Col: 114} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var71)) if templ_7745c5c3_Err != nil { @@ -1679,7 +1691,7 @@ func editConnection(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var72 string templ_7745c5c3_Var72, templ_7745c5c3_Err = templ.JoinStringErrs(components.AssetPath(ctx, "/static/js/workspace_trigger_patterns.js")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 602, Col: 86} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 601, Col: 86} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var72)) if templ_7745c5c3_Err != nil { @@ -1692,7 +1704,7 @@ func editConnection(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var73 string templ_7745c5c3_Var73, templ_7745c5c3_Err = templ.JoinStringErrs("workspace_trigger_patterns(" + toJSON(props.ws.TriggerPatterns) + ")") if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 603, Col: 161} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 602, Col: 161} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var73)) if templ_7745c5c3_Err != nil { @@ -1705,7 +1717,7 @@ func editConnection(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var74 string templ_7745c5c3_Var74, templ_7745c5c3_Err = templ.JoinStringErrs(props.vcsTriggerTags) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 621, Col: 105} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 620, Col: 105} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var74)) if templ_7745c5c3_Err != nil { @@ -1728,7 +1740,7 @@ func editConnection(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var75 string templ_7745c5c3_Var75, templ_7745c5c3_Err = templ.JoinStringErrs("{regex: " + toJSON(props.ws.Connection.TagsRegex) + "}") if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 625, Col: 102} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 624, Col: 102} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var75)) if templ_7745c5c3_Err != nil { @@ -1741,7 +1753,7 @@ func editConnection(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var76 string templ_7745c5c3_Var76, templ_7745c5c3_Err = templ.JoinStringErrs(props.vcsTagRegexDefault) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 627, Col: 100} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 626, Col: 100} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var76)) if templ_7745c5c3_Err != nil { @@ -1764,7 +1776,7 @@ func editConnection(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var77 string templ_7745c5c3_Var77, templ_7745c5c3_Err = templ.JoinStringErrs(props.vcsTagRegexPrefix) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 632, Col: 98} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 631, Col: 98} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var77)) if templ_7745c5c3_Err != nil { @@ -1787,7 +1799,7 @@ func editConnection(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var78 string templ_7745c5c3_Var78, templ_7745c5c3_Err = templ.JoinStringErrs(props.vcsTagRegexSuffix) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 637, Col: 98} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 636, Col: 98} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var78)) if templ_7745c5c3_Err != nil { @@ -1815,7 +1827,7 @@ func editConnection(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var79 string templ_7745c5c3_Var79, templ_7745c5c3_Err = templ.JoinStringErrs(props.vcsTagRegexCustom) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 643, Col: 111} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 642, Col: 111} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var79)) if templ_7745c5c3_Err != nil { @@ -1838,7 +1850,7 @@ func editConnection(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var80 string templ_7745c5c3_Var80, templ_7745c5c3_Err = templ.JoinStringErrs(props.ws.Connection.TagsRegex) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 645, Col: 149} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 644, Col: 149} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var80)) if templ_7745c5c3_Err != nil { @@ -1851,7 +1863,7 @@ func editConnection(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var81 string templ_7745c5c3_Var81, templ_7745c5c3_Err = templ.JoinStringErrs(props.ws.Connection.Branch) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 652, Col: 109} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 651, Col: 109} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var81)) if templ_7745c5c3_Err != nil { @@ -1924,7 +1936,7 @@ func editPermissions(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var83 string templ_7745c5c3_Var83, templ_7745c5c3_Err = templ.JoinStringErrs("permissions-" + workspacePerm.team.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 689, Col: 54} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 688, Col: 54} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var83)) if templ_7745c5c3_Err != nil { @@ -1937,7 +1949,7 @@ func editPermissions(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var84 templ.SafeURL templ_7745c5c3_Var84, templ_7745c5c3_Err = templ.JoinURLErrs(paths.SetPermissionWorkspace(props.ws.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 690, Col: 95} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 689, Col: 95} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var84)) if templ_7745c5c3_Err != nil { @@ -1950,7 +1962,7 @@ func editPermissions(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var85 templ.SafeURL templ_7745c5c3_Var85, templ_7745c5c3_Err = templ.JoinURLErrs(paths.Team(workspacePerm.team.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 691, Col: 62} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 690, Col: 62} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var85)) if templ_7745c5c3_Err != nil { @@ -1963,7 +1975,7 @@ func editPermissions(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var86 string templ_7745c5c3_Var86, templ_7745c5c3_Err = templ.JoinStringErrs(workspacePerm.team.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 691, Col: 90} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 690, Col: 90} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var86)) if templ_7745c5c3_Err != nil { @@ -1976,7 +1988,7 @@ func editPermissions(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var87 string templ_7745c5c3_Var87, templ_7745c5c3_Err = templ.JoinStringErrs(workspacePerm.team.ID.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 693, Col: 67} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 692, Col: 67} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var87)) if templ_7745c5c3_Err != nil { @@ -1994,7 +2006,7 @@ func editPermissions(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var88 string templ_7745c5c3_Var88, templ_7745c5c3_Err = templ.JoinStringErrs(role.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 696, Col: 38} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 695, Col: 38} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var88)) if templ_7745c5c3_Err != nil { @@ -2017,7 +2029,7 @@ func editPermissions(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var89 string templ_7745c5c3_Var89, templ_7745c5c3_Err = templ.JoinStringErrs(role.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 696, Col: 115} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 695, Col: 115} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var89)) if templ_7745c5c3_Err != nil { @@ -2035,7 +2047,7 @@ func editPermissions(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var90 templ.SafeURL templ_7745c5c3_Var90, templ_7745c5c3_Err = templ.JoinURLErrs(paths.UnsetPermissionWorkspace(props.ws.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 702, Col: 74} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 701, Col: 74} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var90)) if templ_7745c5c3_Err != nil { @@ -2048,7 +2060,7 @@ func editPermissions(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var91 string templ_7745c5c3_Var91, templ_7745c5c3_Err = templ.JoinStringErrs(workspacePerm.team.ID.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 703, Col: 68} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 702, Col: 68} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var91)) if templ_7745c5c3_Err != nil { @@ -2074,7 +2086,7 @@ func editPermissions(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var92 templ.SafeURL templ_7745c5c3_Var92, templ_7745c5c3_Err = templ.JoinURLErrs(paths.SetPermissionWorkspace(props.ws.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 710, Col: 87} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 709, Col: 87} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var92)) if templ_7745c5c3_Err != nil { @@ -2092,7 +2104,7 @@ func editPermissions(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var93 string templ_7745c5c3_Var93, templ_7745c5c3_Err = templ.JoinStringErrs(workspacePerm.ID.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 715, Col: 49} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 714, Col: 49} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var93)) if templ_7745c5c3_Err != nil { @@ -2105,7 +2117,7 @@ func editPermissions(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var94 string templ_7745c5c3_Var94, templ_7745c5c3_Err = templ.JoinStringErrs(workspacePerm.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 715, Col: 72} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 714, Col: 72} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var94)) if templ_7745c5c3_Err != nil { @@ -2128,7 +2140,7 @@ func editPermissions(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var95 string templ_7745c5c3_Var95, templ_7745c5c3_Err = templ.JoinStringErrs(role.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 723, Col: 37} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 722, Col: 37} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var95)) if templ_7745c5c3_Err != nil { @@ -2141,7 +2153,7 @@ func editPermissions(props workspaceEditProps) templ.Component { var templ_7745c5c3_Var96 string templ_7745c5c3_Var96, templ_7745c5c3_Err = templ.JoinStringErrs(role.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 723, Col: 55} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 722, Col: 55} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var96)) if templ_7745c5c3_Err != nil { @@ -2214,7 +2226,7 @@ func listVCSProviders(ws *workspace.Workspace, providers []*vcs.Provider) templ. var templ_7745c5c3_Var99 templ.SafeURL templ_7745c5c3_Var99, templ_7745c5c3_Err = templ.JoinURLErrs(paths.VCSProviders(ws.Organization)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 752, Col: 79} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 751, Col: 79} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var99)) if templ_7745c5c3_Err != nil { @@ -2229,7 +2241,6 @@ func listVCSProviders(ws *workspace.Workspace, providers []*vcs.Provider) templ. Actions: vcsProviderSelector{workspaceID: ws.ID}.action, }, providers, - "vcs-providers-table", ).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err @@ -2246,7 +2257,7 @@ func listVCSProviders(ws *workspace.Workspace, providers []*vcs.Provider) templ. var templ_7745c5c3_Var100 templ.SafeURL templ_7745c5c3_Var100, templ_7745c5c3_Err = templ.JoinURLErrs(paths.VCSProviders(ws.Organization)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 762, Col: 132} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 760, Col: 132} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var100)) if templ_7745c5c3_Err != nil { @@ -2299,7 +2310,7 @@ func (s vcsProviderSelector) action(vcsProviderID resource.TfeID) templ.Componen var templ_7745c5c3_Var102 templ.SafeURL templ_7745c5c3_Var102, templ_7745c5c3_Err = templ.JoinURLErrs(paths.SetupConnectionRepoWorkspace(s.workspaceID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 773, Col: 65} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 771, Col: 65} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var102)) if templ_7745c5c3_Err != nil { @@ -2312,7 +2323,7 @@ func (s vcsProviderSelector) action(vcsProviderID resource.TfeID) templ.Componen var templ_7745c5c3_Var103 string templ_7745c5c3_Var103, templ_7745c5c3_Err = templ.JoinStringErrs(vcsProviderID.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 774, Col: 76} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 772, Col: 76} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var103)) if templ_7745c5c3_Err != nil { @@ -2380,7 +2391,7 @@ func listVCSRepos(ws *workspace.Workspace, vcsProviderID resource.TfeID, repos [ var templ_7745c5c3_Var106 templ.SafeURL templ_7745c5c3_Var106, templ_7745c5c3_Err = templ.JoinURLErrs(paths.ConnectWorkspace(ws.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 796, Col: 46} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 794, Col: 46} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var106)) if templ_7745c5c3_Err != nil { @@ -2393,7 +2404,7 @@ func listVCSRepos(ws *workspace.Workspace, vcsProviderID resource.TfeID, repos [ var templ_7745c5c3_Var107 string templ_7745c5c3_Var107, templ_7745c5c3_Err = templ.JoinStringErrs(vcsProviderID.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 797, Col: 98} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 795, Col: 98} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var107)) if templ_7745c5c3_Err != nil { @@ -2411,7 +2422,6 @@ func listVCSRepos(ws *workspace.Workspace, vcsProviderID resource.TfeID, repos [ }.action, }, repos, - "repos-table", ).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err @@ -2459,7 +2469,7 @@ func (s workspaceRepoSelector) action(repo vcs.Repo) templ.Component { var templ_7745c5c3_Var109 templ.SafeURL templ_7745c5c3_Var109, templ_7745c5c3_Err = templ.JoinURLErrs(paths.ConnectWorkspace(s.workspaceID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 820, Col: 53} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 817, Col: 53} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var109)) if templ_7745c5c3_Err != nil { @@ -2472,7 +2482,7 @@ func (s workspaceRepoSelector) action(repo vcs.Repo) templ.Component { var templ_7745c5c3_Var110 string templ_7745c5c3_Var110, templ_7745c5c3_Err = templ.JoinStringErrs(s.vcsProviderID.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 821, Col: 78} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 818, Col: 78} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var110)) if templ_7745c5c3_Err != nil { @@ -2485,7 +2495,7 @@ func (s workspaceRepoSelector) action(repo vcs.Repo) templ.Component { var templ_7745c5c3_Var111 string templ_7745c5c3_Var111, templ_7745c5c3_Err = templ.JoinStringErrs(repo.String()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 822, Col: 78} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 819, Col: 78} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var111)) if templ_7745c5c3_Err != nil { @@ -2579,7 +2589,7 @@ func workspaceHeaderLinksAndStartRunSelector(props workspaceGetProps) templ.Comp var templ_7745c5c3_Var114 templ.SafeURL templ_7745c5c3_Var114, templ_7745c5c3_Err = templ.JoinURLErrs(paths.StartRunWorkspace(props.ws.ID)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 841, Col: 84} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/ui/workspace_view.templ`, Line: 838, Col: 84} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var114)) if templ_7745c5c3_Err != nil {