Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move "Recently Installed Updates" section to the top. #94

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions _data/component/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ type UpdatesBody struct {
func (*UpdatesBody) Render() vecty.ComponentOrHTML {
return elem.Body(
gpscomponent.UpdatesContent(
mockComponentRPs,
mockActive,
mockHistory,
true,
)...,
)
}

var mockComponentRPs = []*model.RepoPresentation{
var mockActive = []*model.RepoPresentation{
{
RepoRoot: "github.com/gopherjs/gopherjs",
ImportPathPattern: "github.com/gopherjs/gopherjs/...",
Expand Down Expand Up @@ -95,6 +96,9 @@ var mockComponentRPs = []*model.RepoPresentation{
UpdateState: model.Available,
UpdateSupported: true,
},
}

var mockHistory = []*model.RepoPresentation{
{
RepoRoot: "golang.org/x/image",
ImportPathPattern: "golang.org/x/image/...",
Expand Down
18 changes: 9 additions & 9 deletions assets/assets_vfsdata.go

Large diffs are not rendered by default.

41 changes: 23 additions & 18 deletions component/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,34 @@ func (*Header) Render() vecty.ComponentOrHTML {
// updatesHeader combines checkingForUpdates, noUpdates and updatesHeading
// into one high level component.
type updatesHeader struct {
RPs []*model.RepoPresentation
Active []*model.RepoPresentation
CheckingUpdates bool
}

func (u updatesHeader) Render() []vecty.MarkupOrChild {
var ns []vecty.MarkupOrChild
// Show "Checking for updates..." while still checking.
if u.CheckingUpdates {
ns = append(ns, checkingForUpdates())
}
available, updating, supported := u.status()
// Show "No Updates Available" if we're done checking and there are no remaining updates.
if !u.CheckingUpdates && available == 0 && !updating {
ns = append(ns, noUpdates())
switch {
case u.CheckingUpdates:
// Show "Checking for updates..." while still checking.
ns = append(ns, heading(elem.Heading2, "Checking for updates..."))
case !u.CheckingUpdates && len(u.Active) > 0:
// Show "Updates Available" if we're done checking and there are active updates.
ns = append(ns, heading(elem.Heading2, "Updates Available"))
case !u.CheckingUpdates && len(u.Active) == 0:
// Show "No Updates Available" if we're done checking and there are no remaining updates.
ns = append(ns,
elem.Heading2(
vecty.Markup(vecty.Style("text-align", "center"), vecty.Style("margin-bottom", "2px")),
vecty.Text("No Updates Available"),
),
elem.Heading4(
vecty.Markup(vecty.Style("text-align", "center"), vecty.Style("margin-top", "2px"), vecty.Style("font-weight", "normal")),
vecty.Text("All your Go packages are up to date"),
),
)
}
// Show number of updates available and Update All button.
available, updating, supported := u.status()
ns = append(ns, &updatesHeading{
Available: available,
Updating: updating,
Expand All @@ -56,9 +68,9 @@ func (u updatesHeader) Render() []vecty.MarkupOrChild {
return ns
}

// status returns available, updating, supported updates in u.RPs.
// status reports available, updating, supported updates in u.Active.
func (u updatesHeader) status() (available uint, updating bool, supported bool) {
for _, rp := range u.RPs {
for _, rp := range u.Active {
switch rp.UpdateState {
case model.Available:
available++
Expand Down Expand Up @@ -138,13 +150,6 @@ func (u *updatesHeading) updateAllButton() *vecty.HTML {
}
}

// InstalledUpdates is a heading for installed updates.
func InstalledUpdates() *vecty.HTML { return heading(elem.Heading3, "Installed Updates") }

func checkingForUpdates() *vecty.HTML { return heading(elem.Heading2, "Checking for updates...") }

func noUpdates() *vecty.HTML { return heading(elem.Heading2, "No Updates Available") }

func heading(heading func(markup ...vecty.MarkupOrChild) *vecty.HTML, text string) *vecty.HTML {
return heading(
vecty.Markup(vecty.Style("text-align", "center")),
Expand Down
34 changes: 23 additions & 11 deletions component/updates.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,49 @@ import (
)

// UpdatesContent returns the entire content of updates tab.
func UpdatesContent(rps []*model.RepoPresentation, checkingUpdates bool) []vecty.MarkupOrChild {
func UpdatesContent(active, history []*model.RepoPresentation, checkingUpdates bool) []vecty.MarkupOrChild {
return []vecty.MarkupOrChild{
&Header{},
elem.Div(
vecty.Markup(vecty.Class("center-max-width")),
elem.Div(
updatesContent(rps, checkingUpdates)...,
updatesContent(active, history, checkingUpdates)...,
),
),
}
}

func updatesContent(rps []*model.RepoPresentation, checkingUpdates bool) []vecty.MarkupOrChild {
func updatesContent(active, history []*model.RepoPresentation, checkingUpdates bool) []vecty.MarkupOrChild {
var content = []vecty.MarkupOrChild{
vecty.Markup(vecty.Class("content")),
}

// History with "Recently Installed Updates" heading, if any.
if len(history) > 0 {
content = append(content, heading(elem.Heading3, "Recently Installed Updates"))

for _, rp := range history {
content = append(content, &RepoPresentation{
RepoPresentation: rp,
})
}

// Spacer at the bottom.
content = append(content, elem.Div(
vecty.Markup(vecty.Style("height", "60px")),
))
}

// Updates header.
content = append(content,
updatesHeader{
RPs: rps,
Active: active,
CheckingUpdates: checkingUpdates,
}.Render()...,
)

wroteInstalledUpdates := false
for _, rp := range rps {
if rp.UpdateState == model.Updated && !wroteInstalledUpdates {
content = append(content, InstalledUpdates())
wroteInstalledUpdates = true
}

// Active updates.
for _, rp := range active {
content = append(content, &RepoPresentation{
RepoPresentation: rp,
})
Expand Down
3 changes: 2 additions & 1 deletion frontend/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ type UpdatesBody struct {
func (b *UpdatesBody) Render() vecty.ComponentOrHTML {
return elem.Body(
gpscomponent.UpdatesContent(
store.RPs(),
store.Active(),
store.History(),
store.CheckingUpdates(),
)...,
)
Expand Down
57 changes: 25 additions & 32 deletions frontend/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@ import (
)

var (
rps []*model.RepoPresentation
active []*model.RepoPresentation
history []*model.RepoPresentation
checkingUpdates = true
)

// RPs returns the repo presentations of store.
func RPs() []*model.RepoPresentation { return rps }
// Active returns the active repo presentations in store.
func Active() []*model.RepoPresentation { return active }

// History returns the historical repo presentations in store.
func History() []*model.RepoPresentation { return history }

// CheckingUpdates reports whether the process of checking for updates is still running.
func CheckingUpdates() bool { return checkingUpdates }
Expand All @@ -24,12 +28,16 @@ func CheckingUpdates() bool { return checkingUpdates }
func Apply(a action.Action) action.Response {
switch a := a.(type) {
case *action.AppendRP:
rps = append(rps, a.RP)
moveUp(rps, a.RP)
switch a.RP.UpdateState {
case model.Available, model.Updating:
active = append(active, a.RP)
case model.Updated:
history = append(history, a.RP)
}
return nil

case *action.SetUpdating:
for _, rp := range rps {
for _, rp := range active {
if rp.RepoRoot == a.RepoRoot {
rp.UpdateState = model.Updating
return nil
Expand All @@ -39,7 +47,7 @@ func Apply(a action.Action) action.Response {

case *action.SetUpdatingAll:
var repoRoots []string
for _, rp := range rps {
for _, rp := range active {
if rp.UpdateState == model.Available {
repoRoots = append(repoRoots, rp.RepoRoot)
rp.UpdateState = model.Updating
Expand All @@ -51,10 +59,18 @@ func Apply(a action.Action) action.Response {
return &action.SetUpdatingAllResponse{RepoRoots: repoRoots}

case *action.SetUpdated:
moveDown(rps, a.RepoRoot)
for _, rp := range rps {
for i, rp := range active {
if rp.RepoRoot == a.RepoRoot {
// Remove from active.
copy(active[i:], active[i+1:])
active = active[:len(active)-1]

// Set UpdateState.
rp.UpdateState = model.Updated

// Append to history.
history = append(history, rp)

return nil
}
}
Expand All @@ -68,26 +84,3 @@ func Apply(a action.Action) action.Response {
panic(fmt.Errorf("%v (type %T) is not a valid action", a, a))
}
}

// TODO: Both moveDown and moveUp can be inlined and simplified.

// moveDown moves root down the rps towards all other updated.
func moveDown(rps []*model.RepoPresentation, root string) {
var i int
for ; rps[i].RepoRoot != root; i++ { // i is the current package about to be updated.
}
for ; i+1 < len(rps) && rps[i+1].UpdateState != model.Updated; i++ {
rps[i], rps[i+1] = rps[i+1], rps[i] // Swap the two.
}
}

// moveUp moves last entry up the rps above all other updated entries, unless rp is already updated.
func moveUp(rps []*model.RepoPresentation, rp *model.RepoPresentation) {
// TODO: The "unless rp is already updated" part might not be needed if more strict about possible cases.
if rp.UpdateState == model.Updated {
return
}
for i := len(rps) - 1; i-1 >= 0 && rps[i-1].UpdateState == model.Updated; i-- {
rps[i], rps[i-1] = rps[i-1], rps[i] // Swap the two.
}
}