cerrado @ f1643ffcbd543cacfe9ab5e46eafdd0c39cd47fd

feat: Add refs page

UI now it is a broken state. I'll all pages working first so I can
better style it later.
diff --git a/pkg/git/git.go b/pkg/git/git.go
index 80c0e4613fdd261329634bf48bd58069ff827f6b..7ef23f74b726b769ed7f197bd3ec25b30c2363a7 100644
--- a/pkg/git/git.go
+++ b/pkg/git/git.go
@@ -6,6 +6,7 @@ 	"fmt"
 	"io"
 
 	"github.com/go-git/go-git/v5"
+	"github.com/go-git/go-git/v5/plumbing"
 	"github.com/go-git/go-git/v5/plumbing/object"
 )
 
@@ -54,6 +55,7 @@ 	repo, err := git.PlainOpen(g.path)
 	if err != nil {
 		return nil, err
 	}
+
 	ref, err := repo.Head()
 	if err != nil {
 		return nil, errors.Join(MissingHeadErr, err)
@@ -81,3 +83,49 @@ 	}
 
 	return commits, nil
 }
+
+func (g *GitRepository) Tags() ([]*object.Tag, error) {
+	repo, err := git.PlainOpen(g.path)
+	if err != nil {
+		return nil, err
+	}
+
+	ti, err := repo.TagObjects()
+	if err != nil {
+		return nil, err
+	}
+
+	tags := []*object.Tag{}
+	err = ti.ForEach(func(t *object.Tag) error {
+		tags = append(tags, t)
+		return nil
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	return tags, nil
+}
+
+func (g *GitRepository) Branches() ([]*plumbing.Reference, error) {
+	repo, err := git.PlainOpen(g.path)
+	if err != nil {
+		return nil, err
+	}
+
+	bs, err := repo.Branches()
+	if err != nil {
+		return nil, err
+	}
+
+	branches := []*plumbing.Reference{}
+	err = bs.ForEach(func(ref *plumbing.Reference) error {
+		branches = append(branches, ref)
+		return nil
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	return branches, nil
+}
diff --git a/pkg/handler/git/handler.go b/pkg/handler/git/handler.go
index ebfb37f298597e7aee5afa1ca9026e44fe9b364e..d090f2269b5c0057caf828048fe161028afcfacc 100644
--- a/pkg/handler/git/handler.go
+++ b/pkg/handler/git/handler.go
@@ -6,6 +6,7 @@ 	"net/http"
 
 	"git.gabrielgio.me/cerrado/pkg/service"
 	"git.gabrielgio.me/cerrado/templates"
+	"github.com/go-git/go-git/v5/plumbing"
 	"github.com/go-git/go-git/v5/plumbing/object"
 	"github.com/gorilla/mux"
 )
@@ -18,6 +19,8 @@
 	gitService interface {
 		ListRepositories() ([]*service.Repository, error)
 		ListCommits(string) ([]*object.Commit, error)
+		ListTags(string) ([]*object.Tag, error)
+		ListBranches(string) ([]*plumbing.Reference, error)
 	}
 )
 
@@ -58,9 +61,25 @@ }
 
 func (g *GitHandler) Refs(w http.ResponseWriter, r *http.Request) {
 	name := mux.Vars(r)["name"]
+
+	tags, err := g.gitService.ListTags(name)
+	if err != nil {
+		slog.Error("Error loading tags", "error", err)
+		return
+	}
+
+	branches, err := g.gitService.ListBranches(name)
+	if err != nil {
+		slog.Error("Error loading branches", "error", err)
+		return
+	}
+
 	gitList := &templates.GitItemPage{
-		Name:        name,
-		GitItemBase: &templates.GitItemRefsPage{},
+		Name: name,
+		GitItemBase: &templates.GitItemRefsPage{
+			Tags:     tags,
+			Branches: branches,
+		},
 	}
 	templates.WritePageTemplate(w, gitList)
 }
diff --git a/pkg/service/git.go b/pkg/service/git.go
index 614770fa55884c145409031ec3e31fee1c9f6a07..57b9b6e7327aa0901955e95bc0c2958d9185d408 100644
--- a/pkg/service/git.go
+++ b/pkg/service/git.go
@@ -5,6 +5,7 @@ 	"path"
 
 	"git.gabrielgio.me/cerrado/pkg/config"
 	"git.gabrielgio.me/cerrado/pkg/git"
+	"github.com/go-git/go-git/v5/plumbing"
 	"github.com/go-git/go-git/v5/plumbing/object"
 )
 
@@ -65,3 +66,19 @@
 	repo := git.NewGitRepository(r.Path)
 	return repo.Commits()
 }
+
+func (g *GitService) ListTags(name string) ([]*object.Tag, error) {
+	// TODO: handle nil
+	r := g.configRepo.GetByName(name)
+
+	repo := git.NewGitRepository(r.Path)
+	return repo.Tags()
+}
+
+func (g *GitService) ListBranches(name string) ([]*plumbing.Reference, error) {
+	// TODO: handle nil
+	r := g.configRepo.GetByName(name)
+
+	repo := git.NewGitRepository(r.Path)
+	return repo.Branches()
+}
diff --git a/scss/main.scss b/scss/main.scss
index 9f17dadab978cf2bef7863c4ff6a292d87e107a8..bb7d7f08ab56d7d605e119b1a4bf85817ed8a76f 100644
--- a/scss/main.scss
+++ b/scss/main.scss
@@ -80,15 +80,10 @@
 .logs pre::first-line {
   font-weight: bold;
 }
-
-@include media-breakpoint-down(sm) {
-  // add extra spacing then list is seen on vertical
-  .logs>div>div:first-child {
-    margin-bottom: 15px;
-  }
-  .logs>div>div:last-child {
-    margin-top: 15px;
-  }
+.logs>div>div:first-child {
+  margin-bottom: 15px;
+}
+.logs>div>div:last-child {
+  margin-top: 15px;
 }
 
-
diff --git a/templates/gititemlog.qtpl b/templates/gititemlog.qtpl
index a39fb777497d50df7bec71fa6d2465b3a1b56570..436c1d274193ee35357d087d94ce89d99ff30d7a 100644
--- a/templates/gititemlog.qtpl
+++ b/templates/gititemlog.qtpl
@@ -12,14 +12,14 @@ {% func (g *GitItemLogPage) GitContent() %}
 <div class="logs">
   {% for _, c := range g.Commits %}
   <div class="row">
-      <div class="col-sm-2">
+      <div class="col-xxl-2">
        {%s TimeFormat(c.Committer.When) %}
       </div>
-      <div class="col-sm-7">
+      <div class="col-xxl-7">
        <pre>{%s c.Message %}</pre>
       </div>
-      <div class="col-sm-3">
-       {%s c.Committer.Name %}
+      <div class="col-xxl-3">
+       <small>{%s c.Committer.Name %}</small>
       </div>
   </div>
   {% endfor %}
diff --git a/templates/gititemlog.qtpl.go b/templates/gititemlog.qtpl.go
index cc5652d56de5724d82b1ec87ed045e9722c6dfc5..e63c8712559c77e4efff48789b7ab17c4bd4ce41 100644
--- a/templates/gititemlog.qtpl.go
+++ b/templates/gititemlog.qtpl.go
@@ -69,26 +69,26 @@ 	for _, c := range g.Commits {
 //line gititemlog.qtpl:13
 		qw422016.N().S(`
   <div class="row">
-      <div class="col-sm-2">
+      <div class="col-xxl-2">
        `)
 //line gititemlog.qtpl:16
 		qw422016.E().S(TimeFormat(c.Committer.When))
 //line gititemlog.qtpl:16
 		qw422016.N().S(`
       </div>
-      <div class="col-sm-7">
+      <div class="col-xxl-7">
        <pre>`)
 //line gititemlog.qtpl:19
 		qw422016.E().S(c.Message)
 //line gititemlog.qtpl:19
 		qw422016.N().S(`</pre>
       </div>
-      <div class="col-sm-3">
-       `)
+      <div class="col-xxl-3">
+       <small>`)
 //line gititemlog.qtpl:22
 		qw422016.E().S(c.Committer.Name)
 //line gititemlog.qtpl:22
-		qw422016.N().S(`
+		qw422016.N().S(`</small>
       </div>
   </div>
   `)
diff --git a/templates/gititemrefs.qtpl b/templates/gititemrefs.qtpl
index 5fed393c6d715def0febba111bf84b0792dc1fa5..9c588630a087401485881be712c413e026664f07 100644
--- a/templates/gititemrefs.qtpl
+++ b/templates/gititemrefs.qtpl
@@ -1,10 +1,46 @@
+{% import "github.com/go-git/go-git/v5/plumbing" %}
+{% import "github.com/go-git/go-git/v5/plumbing/object" %}
+
 {% code
 type GitItemRefsPage struct {
+    Tags []*object.Tag
+    Branches []*plumbing.Reference
 }
 %}
 
 {% func (g *GitItemRefsPage) Nav(name string) %}{%= GitItemNav(name ,Refs) %}{% endfunc %}
 
 {% func (g *GitItemRefsPage) GitContent() %}
-<h4>Refs</h4>
+<div class="row">
+  <div class="col-xxl">
+    <h4>Tags</h4>
+    <div class="logs">
+      {% for _, t := range g.Tags %}
+      <div class="row">
+          <div class="col-xxl-2">
+           {%s TimeFormat(t.Tagger.When) %}
+          </div>
+          <div class="col-xxl-7">
+           <pre>{%s t.Message %}</pre>
+          </div>
+          <div class="col-xxl-3">
+           <small>{%s t.Tagger.Name %}</small>
+          </div>
+      </div>
+      {% endfor %}
+    </div>
+  </div>
+  <div class="col-xxl">
+    <h4>Branches</h4>
+    <div class="logs">
+      {% for _, b := range g.Branches %}
+      <div class="row">
+          <div class="col-xxl">
+           {%s b.String() %}
+          </div>
+      </div>
+      {% endfor %}
+    </div>
+  </div>
+</div>
 {% endfunc %}
diff --git a/templates/gititemrefs.qtpl.go b/templates/gititemrefs.qtpl.go
index 5294bf9fc28d8cbc2b1e1999729412e9dc6e0c9b..f2d2b6fcec5540caa852103cb2513ce0bcb6b518 100644
--- a/templates/gititemrefs.qtpl.go
+++ b/templates/gititemrefs.qtpl.go
@@ -5,86 +5,157 @@ //line gititemrefs.qtpl:1
 package templates
 
 //line gititemrefs.qtpl:1
+import "github.com/go-git/go-git/v5/plumbing"
+
+//line gititemrefs.qtpl:2
+import "github.com/go-git/go-git/v5/plumbing/object"
+
+//line gititemrefs.qtpl:4
 import (
 	qtio422016 "io"
 
 	qt422016 "github.com/valyala/quicktemplate"
 )
 
-//line gititemrefs.qtpl:1
+//line gititemrefs.qtpl:4
 var (
 	_ = qtio422016.Copy
 	_ = qt422016.AcquireByteBuffer
 )
 
-//line gititemrefs.qtpl:2
+//line gititemrefs.qtpl:5
 type GitItemRefsPage struct {
+	Tags     []*object.Tag
+	Branches []*plumbing.Reference
 }
 
-//line gititemrefs.qtpl:6
+//line gititemrefs.qtpl:11
 func (g *GitItemRefsPage) StreamNav(qw422016 *qt422016.Writer, name string) {
-//line gititemrefs.qtpl:6
+//line gititemrefs.qtpl:11
 	StreamGitItemNav(qw422016, name, Refs)
-//line gititemrefs.qtpl:6
+//line gititemrefs.qtpl:11
 }
 
-//line gititemrefs.qtpl:6
+//line gititemrefs.qtpl:11
 func (g *GitItemRefsPage) WriteNav(qq422016 qtio422016.Writer, name string) {
-//line gititemrefs.qtpl:6
+//line gititemrefs.qtpl:11
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line gititemrefs.qtpl:6
+//line gititemrefs.qtpl:11
 	g.StreamNav(qw422016, name)
-//line gititemrefs.qtpl:6
+//line gititemrefs.qtpl:11
 	qt422016.ReleaseWriter(qw422016)
-//line gititemrefs.qtpl:6
+//line gititemrefs.qtpl:11
 }
 
-//line gititemrefs.qtpl:6
+//line gititemrefs.qtpl:11
 func (g *GitItemRefsPage) Nav(name string) string {
-//line gititemrefs.qtpl:6
+//line gititemrefs.qtpl:11
 	qb422016 := qt422016.AcquireByteBuffer()
-//line gititemrefs.qtpl:6
+//line gititemrefs.qtpl:11
 	g.WriteNav(qb422016, name)
-//line gititemrefs.qtpl:6
+//line gititemrefs.qtpl:11
 	qs422016 := string(qb422016.B)
-//line gititemrefs.qtpl:6
+//line gititemrefs.qtpl:11
 	qt422016.ReleaseByteBuffer(qb422016)
-//line gititemrefs.qtpl:6
+//line gititemrefs.qtpl:11
 	return qs422016
-//line gititemrefs.qtpl:6
+//line gititemrefs.qtpl:11
 }
 
-//line gititemrefs.qtpl:8
+//line gititemrefs.qtpl:13
 func (g *GitItemRefsPage) StreamGitContent(qw422016 *qt422016.Writer) {
-//line gititemrefs.qtpl:8
+//line gititemrefs.qtpl:13
+	qw422016.N().S(`
+<div class="row">
+  <div class="col-xxl">
+    <h4>Tags</h4>
+    <div class="logs">
+      `)
+//line gititemrefs.qtpl:18
+	for _, t := range g.Tags {
+//line gititemrefs.qtpl:18
+		qw422016.N().S(`
+      <div class="row">
+          <div class="col-xxl-2">
+           `)
+//line gititemrefs.qtpl:21
+		qw422016.E().S(TimeFormat(t.Tagger.When))
+//line gititemrefs.qtpl:21
+		qw422016.N().S(`
+          </div>
+          <div class="col-xxl-7">
+           <pre>`)
+//line gititemrefs.qtpl:24
+		qw422016.E().S(t.Message)
+//line gititemrefs.qtpl:24
+		qw422016.N().S(`</pre>
+          </div>
+          <div class="col-xxl-3">
+           <small>`)
+//line gititemrefs.qtpl:27
+		qw422016.E().S(t.Tagger.Name)
+//line gititemrefs.qtpl:27
+		qw422016.N().S(`</small>
+          </div>
+      </div>
+      `)
+//line gititemrefs.qtpl:30
+	}
+//line gititemrefs.qtpl:30
 	qw422016.N().S(`
-<h4>Refs</h4>
+    </div>
+  </div>
+  <div class="col-xxl">
+    <h4>Branches</h4>
+    <div class="logs">
+      `)
+//line gititemrefs.qtpl:36
+	for _, b := range g.Branches {
+//line gititemrefs.qtpl:36
+		qw422016.N().S(`
+      <div class="row">
+          <div class="col-xxl">
+           `)
+//line gititemrefs.qtpl:39
+		qw422016.E().S(b.String())
+//line gititemrefs.qtpl:39
+		qw422016.N().S(`
+          </div>
+      </div>
+      `)
+//line gititemrefs.qtpl:42
+	}
+//line gititemrefs.qtpl:42
+	qw422016.N().S(`
+    </div>
+  </div>
+</div>
 `)
-//line gititemrefs.qtpl:10
+//line gititemrefs.qtpl:46
 }
 
-//line gititemrefs.qtpl:10
+//line gititemrefs.qtpl:46
 func (g *GitItemRefsPage) WriteGitContent(qq422016 qtio422016.Writer) {
-//line gititemrefs.qtpl:10
+//line gititemrefs.qtpl:46
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line gititemrefs.qtpl:10
+//line gititemrefs.qtpl:46
 	g.StreamGitContent(qw422016)
-//line gititemrefs.qtpl:10
+//line gititemrefs.qtpl:46
 	qt422016.ReleaseWriter(qw422016)
-//line gititemrefs.qtpl:10
+//line gititemrefs.qtpl:46
 }
 
-//line gititemrefs.qtpl:10
+//line gititemrefs.qtpl:46
 func (g *GitItemRefsPage) GitContent() string {
-//line gititemrefs.qtpl:10
+//line gititemrefs.qtpl:46
 	qb422016 := qt422016.AcquireByteBuffer()
-//line gititemrefs.qtpl:10
+//line gititemrefs.qtpl:46
 	g.WriteGitContent(qb422016)
-//line gititemrefs.qtpl:10
+//line gititemrefs.qtpl:46
 	qs422016 := string(qb422016.B)
-//line gititemrefs.qtpl:10
+//line gititemrefs.qtpl:46
 	qt422016.ReleaseByteBuffer(qb422016)
-//line gititemrefs.qtpl:10
+//line gititemrefs.qtpl:46
 	return qs422016
-//line gititemrefs.qtpl:10
+//line gititemrefs.qtpl:46
 }