diff --git a/cmd/ketchup/templates/index.html b/cmd/ketchup/templates/index.html index b367a4c0..3067f251 100644 --- a/cmd/ketchup/templates/index.html +++ b/cmd/ketchup/templates/index.html @@ -105,7 +105,7 @@ .bg-grey, .bg-grey:hover { background-color: var(--grey); - color: var(--dark); + color: var(--white); text-decoration: none; } @@ -212,6 +212,14 @@ margin: var(--space-size); } + .margin-left { + margin-left: var(--space-size); + } + + .margin-right { + margin-right: var(--space-size); + } + .margin-half { margin: calc(var(--space-size) / 2); } diff --git a/cmd/ketchup/templates/public.html b/cmd/ketchup/templates/public.html index 3b60eb5d..f6165669 100644 --- a/cmd/ketchup/templates/public.html +++ b/cmd/ketchup/templates/public.html @@ -31,6 +31,14 @@ {{ define "header-part" }} {{ with .Root }} {{ if ne . "/" }} +
+ + + +
+ Create {{ end }} {{ end }} diff --git a/pkg/ketchup/ketchups.go b/pkg/ketchup/ketchups.go index b9aa3d6c..3541e326 100644 --- a/pkg/ketchup/ketchups.go +++ b/pkg/ketchup/ketchups.go @@ -75,6 +75,17 @@ func (a app) handleCreate(w http.ResponseWriter, r *http.Request) { } func (a app) handleUpdate(w http.ResponseWriter, r *http.Request) { + rawID := strings.Trim(r.URL.Path, "/") + if rawID == "all" { + if err := a.ketchupService.UpdateAll(r.Context()); err != nil { + a.rendererApp.Error(w, err) + } else { + a.rendererApp.Redirect(w, r, fmt.Sprintf("%s/", appPath), renderer.NewSuccessMessage("All ketchups are up-to-date!")) + } + + return + } + id, err := strconv.ParseUint(strings.Trim(r.URL.Path, "/"), 10, 64) if err != nil { a.rendererApp.Error(w, httpModel.WrapInvalid(err)) diff --git a/pkg/service/ketchup/ketchup.go b/pkg/service/ketchup/ketchup.go index c39f2608..3ea147fd 100644 --- a/pkg/service/ketchup/ketchup.go +++ b/pkg/service/ketchup/ketchup.go @@ -21,6 +21,7 @@ type App interface { ListOutdatedByFrequency(ctx context.Context, frequency model.KetchupFrequency) ([]model.Ketchup, error) Create(ctx context.Context, item model.Ketchup) (model.Ketchup, error) Update(ctx context.Context, item model.Ketchup) (model.Ketchup, error) + UpdateAll(ctx context.Context) error Delete(ctx context.Context, item model.Ketchup) error } @@ -98,6 +99,17 @@ func (a app) Create(ctx context.Context, item model.Ketchup) (model.Ketchup, err return output, err } +func (a app) UpdateAll(ctx context.Context) error { + err := a.ketchupStore.DoAtomic(ctx, func(ctx context.Context) error { + return a.ketchupStore.UpdateAll(ctx) + }) + if err != nil { + return fmt.Errorf("unable to update all ketchup: %s", err) + } + + return nil +} + func (a app) Update(ctx context.Context, item model.Ketchup) (model.Ketchup, error) { var output model.Ketchup diff --git a/pkg/service/ketchup/ketchuptest/ketchuptest.go b/pkg/service/ketchup/ketchuptest/ketchuptest.go index a17fef5c..b48cbaa2 100644 --- a/pkg/service/ketchup/ketchuptest/ketchuptest.go +++ b/pkg/service/ketchup/ketchuptest/ketchuptest.go @@ -77,6 +77,11 @@ func (a App) Update(_ context.Context, _ model.Ketchup) (model.Ketchup, error) { return model.NoneKetchup, nil } +// UpdateAll mocks +func (a App) UpdateAll(_ context.Context) error { + return nil +} + // Delete mocks func (a App) Delete(_ context.Context, _ model.Ketchup) error { return nil diff --git a/pkg/store/ketchup/ketchup.go b/pkg/store/ketchup/ketchup.go index b72e3d0f..2f80c403 100644 --- a/pkg/store/ketchup/ketchup.go +++ b/pkg/store/ketchup/ketchup.go @@ -22,6 +22,7 @@ type App interface { GetByRepository(ctx context.Context, id uint64, pattern string, forUpdate bool) (model.Ketchup, error) Create(ctx context.Context, o model.Ketchup) (uint64, error) Update(ctx context.Context, o model.Ketchup, oldPattern string) error + UpdateAll(ctx context.Context) error Delete(ctx context.Context, o model.Ketchup) error } @@ -333,6 +334,26 @@ func (a app) Update(ctx context.Context, o model.Ketchup, oldPattern string) err return a.db.Exec(ctx, updateQuery, o.Repository.ID, model.ReadUser(ctx).ID, oldPattern, o.Pattern, o.Version, strings.ToLower(o.Frequency.String())) } +const updateAllQuery = ` +UPDATE + ketchup.ketchup AS k +SET + version = rv.version +FROM + ketchup.repository AS r, + ketchup.repository_version AS rv +WHERE + k.repository_id = r.id + AND k.repository_id = rv.repository_id + AND k.pattern = rv.pattern + AND k.version <> rv.version + AND k.user_id = $1 +` + +func (a app) UpdateAll(ctx context.Context) error { + return a.db.Exec(ctx, updateAllQuery, model.ReadUser(ctx).ID) +} + const deleteQuery = ` DELETE FROM ketchup.ketchup diff --git a/pkg/store/ketchup/ketchuptest/ketchuptest.go b/pkg/store/ketchup/ketchuptest/ketchuptest.go index 6aa4a402..ba9ae5ab 100644 --- a/pkg/store/ketchup/ketchuptest/ketchuptest.go +++ b/pkg/store/ketchup/ketchuptest/ketchuptest.go @@ -140,6 +140,11 @@ func (a *App) Update(_ context.Context, _ model.Ketchup, _ string) error { return a.updateErr } +// UpdateAll mocks +func (a *App) UpdateAll(_ context.Context) error { + return nil +} + // Delete mocks func (a *App) Delete(_ context.Context, _ model.Ketchup) error { return a.deleteErr