cerrado @ b71c6c0e5b8dd00d44e40ac0551902a23cbe19d5

feat: Add summary page
diff --git a/pkg/git/git.go b/pkg/git/git.go
index 428bfb164e78ca7e8055097fbe77a31b985e5da4..b725cd875a2615e043e4b15cad5b6bfc98860a85 100644
--- a/pkg/git/git.go
+++ b/pkg/git/git.go
@@ -77,7 +77,7 @@ 	}
 	return c, nil
 }
 
-func (g *GitRepository) Commits() ([]*object.Commit, error) {
+func (g *GitRepository) Commits(count int) ([]*object.Commit, error) {
 	err := g.validateRef()
 	if err != nil {
 		return nil, err
@@ -90,7 +90,7 @@ 	}
 
 	commits := []*object.Commit{}
 	// TODO: for now only load first 1000
-	for x := 0; x < 1000; x++ {
+	for x := 0; x < count; x++ {
 		c, err := ci.Next()
 		if err != nil && errors.Is(err, io.EOF) {
 			break
diff --git a/pkg/handler/git/handler.go b/pkg/handler/git/handler.go
index 48093629296b5531caef1fe0e4736576b205fca6..899f61ee30eab7f322c42d25636de59791763221 100644
--- a/pkg/handler/git/handler.go
+++ b/pkg/handler/git/handler.go
@@ -29,7 +29,7 @@ 	}
 
 	gitService interface {
 		ListRepositories() ([]*service.Repository, error)
-		ListCommits(name string, ref string) ([]*object.Commit, error)
+		ListCommits(name string, ref string, count int) ([]*object.Commit, error)
 		GetHead(name string) (*plumbing.Reference, error)
 		GetTree(name, ref, path string) (*object.Tree, error)
 		GetFileContent(name, ref, path string) (string, error)
@@ -91,10 +91,29 @@ 	if err != nil {
 		return err
 	}
 
+	tags, err := g.gitService.ListTags(name)
+	if err != nil {
+		return err
+	}
+
+	branches, err := g.gitService.ListBranches(name)
+	if err != nil {
+		return err
+	}
+
+	commits, err := g.gitService.ListCommits(name, "", 10)
+	if err != nil {
+		return err
+	}
+
 	gitList := &templates.GitItemPage{
-		Name:        name,
-		Ref:         ref.Name().Short(),
-		GitItemBase: &templates.GitItemSummaryPage{},
+		Name: name,
+		Ref:  ref.Name().Short(),
+		GitItemBase: &templates.GitItemSummaryPage{
+			Tags:     tags,
+			Branches: branches,
+			Commits:  commits,
+		},
 	}
 	templates.WritePageTemplate(w, gitList)
 	return nil
@@ -215,7 +234,7 @@ 	ext.SetHTML(w)
 	name := r.PathValue("name")
 	ref := r.PathValue("ref")
 
-	commits, err := g.gitService.ListCommits(name, ref)
+	commits, err := g.gitService.ListCommits(name, ref, 1000)
 	if err != nil {
 		return err
 	}
diff --git a/pkg/service/git.go b/pkg/service/git.go
index 071e10d640e86887901e442c608f898fa6058ffe..2165abef8acdfbe13d4831c7e6e0c2556678b004 100644
--- a/pkg/service/git.go
+++ b/pkg/service/git.go
@@ -74,7 +74,7 @@
 	return repos, nil
 }
 
-func (g *GitService) ListCommits(name, ref string) ([]*object.Commit, error) {
+func (g *GitService) ListCommits(name, ref string, count int) ([]*object.Commit, error) {
 	r := g.configRepo.GetByName(name)
 	if r == nil {
 		return nil, RepositoryNotFoundErr
@@ -89,7 +89,7 @@ 	err = repo.SetRef(ref)
 	if err != nil {
 		return nil, err
 	}
-	return repo.Commits()
+	return repo.Commits(count)
 }
 
 func (g *GitService) GetTree(name, ref, path string) (*object.Tree, error) {
diff --git a/scss/main.scss b/scss/main.scss
index af8a00210b514e60d9459176b42217b525a24b92..107a4c8231a96c66e05ffc6cc91dda311568a367 100644
--- a/scss/main.scss
+++ b/scss/main.scss
@@ -114,35 +114,6 @@     display: grid;
     overflow-x: auto;
 }
 
-.logs {
-  >div {
-    background: #f8f9fa;
-  }
-
-  >div {
-    padding: 5px;
-    margin: $spacer;
-  }
-
-  @include media-breakpoint-down(md) {
-    >div {
-      margin: $spacer 0 $spacer 0;
-    }
-  }
-
-  pre {
-    font-size: $base-font-size;
-    margin: 0;
-  }
-}
-
-.logs>div>div:first-child {
-  margin-bottom: 15px;
-}
-.logs>div>div:last-child {
-  margin-top: 15px;
-}
-
 #about {
   padding: 0 $spacer $spacer $spacer;
   > p:first-child {
diff --git a/templates/gititemlog.qtpl b/templates/gititemlog.qtpl
index 1af05ca2b19a2ef3bc21e3533ee7333425e21298..a28e7ad52cbd51c2cb6509b3f008116b61e7d8be 100644
--- a/templates/gititemlog.qtpl
+++ b/templates/gititemlog.qtpl
@@ -9,9 +9,9 @@
 {% func (g *GitItemLogPage) Nav(name, ref string) %}{%= GitItemNav(name, ref, Log) %}{% endfunc %}
 
 {% func (g *GitItemLogPage) GitContent(name, ref string) %}
-<div class="logs">
+<div class="event-list">
   {% for _, c := range g.Commits %}
-  <div class="row">
+  <div class="row event">
       <div class="col-xxl-2">
        {%s TimeFormat(c.Committer.When) %}
       </div>
diff --git a/templates/gititemlog.qtpl.go b/templates/gititemlog.qtpl.go
index 185b1538470f819fe06465b82a2d762fc279962a..76c24329c241285809f56a6a9014e1e4274d47bb 100644
--- a/templates/gititemlog.qtpl.go
+++ b/templates/gititemlog.qtpl.go
@@ -62,13 +62,13 @@ //line gititemlog.qtpl:11
 func (g *GitItemLogPage) StreamGitContent(qw422016 *qt422016.Writer, name, ref string) {
 //line gititemlog.qtpl:11
 	qw422016.N().S(`
-<div class="logs">
+<div class="event-list">
   `)
 //line gititemlog.qtpl:13
 	for _, c := range g.Commits {
 //line gititemlog.qtpl:13
 		qw422016.N().S(`
-  <div class="row">
+  <div class="row event">
       <div class="col-xxl-2">
        `)
 //line gititemlog.qtpl:16
diff --git a/templates/gititemsummary.qtpl b/templates/gititemsummary.qtpl
index 4cbf324c71e3d0d1d627e029553b682dd46feee5..9a3e2ee56526ef12d8b10e699d8ca98a3446cb88 100644
--- a/templates/gititemsummary.qtpl
+++ b/templates/gititemsummary.qtpl
@@ -1,10 +1,72 @@
+{% import "github.com/go-git/go-git/v5/plumbing" %}
+{% import "github.com/go-git/go-git/v5/plumbing/object" %}
+
 {% code
 type GitItemSummaryPage struct {
+    Tags []*plumbing.Reference
+    Branches []*plumbing.Reference
+    Commits []*object.Commit
 }
 %}
 
 {% func (g *GitItemSummaryPage) Nav(name, ref string) %}{%= GitItemNav(name, ref, Summary) %}{% endfunc %}
 
 {% func (g *GitItemSummaryPage) GitContent(name, ref string) %}
-<h4>Summary</h4>
+<div class="row">
+  <div class="col-md-8">
+    {% if len(g.Tags) > 0 %}
+    <div class="event-list">
+      {% for _, t := range g.Tags %}
+      <div class="row event me-md-2">
+          <div class="col-4">
+           {%s t.Name().Short() %}
+          </div>
+          <div class="col-8">
+            <div class="float-end">
+              <a href="/{%s name %}/tree/{%s t.Name().Short() %}">tree</a>
+              <a href="/{%s name %}/log/{%s t.Name().Short() %}">log</a>
+            </div>
+          </div>
+      </div>
+      {% endfor %}
+    </div>
+    {% else %}
+        <p> No tags </p>
+    {% endif %}
+  </div>
+  <div class="col-md-4">
+    <div class="event-list">
+      {% for _, b := range g.Branches %}
+      <div class="row event">
+          <div class="col-4">
+           {%s b.Name().Short() %}
+          </div>
+          <div class="col-8">
+            <div class="float-end">
+              <a href="/{%s name %}/tree/{%s b.Name().Short() %}">tree</a>
+              <a href="/{%s name %}/log/{%s b.Name().Short() %}">log</a>
+            </div>
+          </div>
+      </div>
+      {% endfor %}
+    </div>
+  </div>
+</div>
+<div class="row">
+  <div class="event-list">
+    {% for _, c := range g.Commits %}
+    <div class="row event">
+        <div class="col-xxl-2">
+         {%s TimeFormat(c.Committer.When) %}
+        </div>
+        <div class="col-xxl-7 code-view">
+         <pre>{%s c.Message %}</pre>
+        </div>
+        <div class="col-xxl-3">
+         <small>{%s c.Committer.Name %} &lt;{%s c.Committer.Email %}&gt;</small>
+        </div>
+    </div>
+    {% endfor %}
+  </div>
+</div>
 {% endfunc %}
diff --git a/templates/gititemsummary.qtpl.go b/templates/gititemsummary.qtpl.go
index d8606a58c8b3d823a2ab6a293f0073fae603a7fa..cf1c07cac00b465234917bc9e5a92e2ec7eab62b 100644
--- a/templates/gititemsummary.qtpl.go
+++ b/templates/gititemsummary.qtpl.go
@@ -5,86 +5,243 @@ //line gititemsummary.qtpl:1
 package templates
 
 //line gititemsummary.qtpl:1
+import "github.com/go-git/go-git/v5/plumbing"
+
+//line gititemsummary.qtpl:2
+import "github.com/go-git/go-git/v5/plumbing/object"
+
+//line gititemsummary.qtpl:4
 import (
 	qtio422016 "io"
 
 	qt422016 "github.com/valyala/quicktemplate"
 )
 
-//line gititemsummary.qtpl:1
+//line gititemsummary.qtpl:4
 var (
 	_ = qtio422016.Copy
 	_ = qt422016.AcquireByteBuffer
 )
 
-//line gititemsummary.qtpl:2
+//line gititemsummary.qtpl:5
 type GitItemSummaryPage struct {
+	Tags     []*plumbing.Reference
+	Branches []*plumbing.Reference
+	Commits  []*object.Commit
 }
 
-//line gititemsummary.qtpl:6
+//line gititemsummary.qtpl:12
 func (g *GitItemSummaryPage) StreamNav(qw422016 *qt422016.Writer, name, ref string) {
-//line gititemsummary.qtpl:6
+//line gititemsummary.qtpl:12
 	StreamGitItemNav(qw422016, name, ref, Summary)
-//line gititemsummary.qtpl:6
+//line gititemsummary.qtpl:12
 }
 
-//line gititemsummary.qtpl:6
+//line gititemsummary.qtpl:12
 func (g *GitItemSummaryPage) WriteNav(qq422016 qtio422016.Writer, name, ref string) {
-//line gititemsummary.qtpl:6
+//line gititemsummary.qtpl:12
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line gititemsummary.qtpl:6
+//line gititemsummary.qtpl:12
 	g.StreamNav(qw422016, name, ref)
-//line gititemsummary.qtpl:6
+//line gititemsummary.qtpl:12
 	qt422016.ReleaseWriter(qw422016)
-//line gititemsummary.qtpl:6
+//line gititemsummary.qtpl:12
 }
 
-//line gititemsummary.qtpl:6
+//line gititemsummary.qtpl:12
 func (g *GitItemSummaryPage) Nav(name, ref string) string {
-//line gititemsummary.qtpl:6
+//line gititemsummary.qtpl:12
 	qb422016 := qt422016.AcquireByteBuffer()
-//line gititemsummary.qtpl:6
+//line gititemsummary.qtpl:12
 	g.WriteNav(qb422016, name, ref)
-//line gititemsummary.qtpl:6
+//line gititemsummary.qtpl:12
 	qs422016 := string(qb422016.B)
-//line gititemsummary.qtpl:6
+//line gititemsummary.qtpl:12
 	qt422016.ReleaseByteBuffer(qb422016)
-//line gititemsummary.qtpl:6
+//line gititemsummary.qtpl:12
 	return qs422016
-//line gititemsummary.qtpl:6
+//line gititemsummary.qtpl:12
 }
 
-//line gititemsummary.qtpl:8
+//line gititemsummary.qtpl:14
 func (g *GitItemSummaryPage) StreamGitContent(qw422016 *qt422016.Writer, name, ref string) {
-//line gititemsummary.qtpl:8
+//line gititemsummary.qtpl:14
+	qw422016.N().S(`
+<div class="row">
+  <div class="col-md-8">
+    `)
+//line gititemsummary.qtpl:17
+	if len(g.Tags) > 0 {
+//line gititemsummary.qtpl:17
+		qw422016.N().S(`
+    <div class="event-list">
+      `)
+//line gititemsummary.qtpl:19
+		for _, t := range g.Tags {
+//line gititemsummary.qtpl:19
+			qw422016.N().S(`
+      <div class="row event me-md-2">
+          <div class="col-4">
+           `)
+//line gititemsummary.qtpl:22
+			qw422016.E().S(t.Name().Short())
+//line gititemsummary.qtpl:22
+			qw422016.N().S(`
+          </div>
+          <div class="col-8">
+            <div class="float-end">
+              <a href="/`)
+//line gititemsummary.qtpl:26
+			qw422016.E().S(name)
+//line gititemsummary.qtpl:26
+			qw422016.N().S(`/tree/`)
+//line gititemsummary.qtpl:26
+			qw422016.E().S(t.Name().Short())
+//line gititemsummary.qtpl:26
+			qw422016.N().S(`">tree</a>
+              <a href="/`)
+//line gititemsummary.qtpl:27
+			qw422016.E().S(name)
+//line gititemsummary.qtpl:27
+			qw422016.N().S(`/log/`)
+//line gititemsummary.qtpl:27
+			qw422016.E().S(t.Name().Short())
+//line gititemsummary.qtpl:27
+			qw422016.N().S(`">log</a>
+            </div>
+          </div>
+      </div>
+      `)
+//line gititemsummary.qtpl:31
+		}
+//line gititemsummary.qtpl:31
+		qw422016.N().S(`
+    </div>
+    `)
+//line gititemsummary.qtpl:33
+	} else {
+//line gititemsummary.qtpl:33
+		qw422016.N().S(`
+        <p> No tags </p>
+    `)
+//line gititemsummary.qtpl:35
+	}
+//line gititemsummary.qtpl:35
+	qw422016.N().S(`
+  </div>
+  <div class="col-md-4">
+    <div class="event-list">
+      `)
+//line gititemsummary.qtpl:39
+	for _, b := range g.Branches {
+//line gititemsummary.qtpl:39
+		qw422016.N().S(`
+      <div class="row event">
+          <div class="col-4">
+           `)
+//line gititemsummary.qtpl:42
+		qw422016.E().S(b.Name().Short())
+//line gititemsummary.qtpl:42
+		qw422016.N().S(`
+          </div>
+          <div class="col-8">
+            <div class="float-end">
+              <a href="/`)
+//line gititemsummary.qtpl:46
+		qw422016.E().S(name)
+//line gititemsummary.qtpl:46
+		qw422016.N().S(`/tree/`)
+//line gititemsummary.qtpl:46
+		qw422016.E().S(b.Name().Short())
+//line gititemsummary.qtpl:46
+		qw422016.N().S(`">tree</a>
+              <a href="/`)
+//line gititemsummary.qtpl:47
+		qw422016.E().S(name)
+//line gititemsummary.qtpl:47
+		qw422016.N().S(`/log/`)
+//line gititemsummary.qtpl:47
+		qw422016.E().S(b.Name().Short())
+//line gititemsummary.qtpl:47
+		qw422016.N().S(`">log</a>
+            </div>
+          </div>
+      </div>
+      `)
+//line gititemsummary.qtpl:51
+	}
+//line gititemsummary.qtpl:51
+	qw422016.N().S(`
+    </div>
+  </div>
+</div>
+<div class="row">
+  <div class="event-list">
+    `)
+//line gititemsummary.qtpl:57
+	for _, c := range g.Commits {
+//line gititemsummary.qtpl:57
+		qw422016.N().S(`
+    <div class="row event">
+        <div class="col-xxl-2">
+         `)
+//line gititemsummary.qtpl:60
+		qw422016.E().S(TimeFormat(c.Committer.When))
+//line gititemsummary.qtpl:60
+		qw422016.N().S(`
+        </div>
+        <div class="col-xxl-7 code-view">
+         <pre>`)
+//line gititemsummary.qtpl:63
+		qw422016.E().S(c.Message)
+//line gititemsummary.qtpl:63
+		qw422016.N().S(`</pre>
+        </div>
+        <div class="col-xxl-3">
+         <small>`)
+//line gititemsummary.qtpl:66
+		qw422016.E().S(c.Committer.Name)
+//line gititemsummary.qtpl:66
+		qw422016.N().S(` &lt;`)
+//line gititemsummary.qtpl:66
+		qw422016.E().S(c.Committer.Email)
+//line gititemsummary.qtpl:66
+		qw422016.N().S(`&gt;</small>
+        </div>
+    </div>
+    `)
+//line gititemsummary.qtpl:69
+	}
+//line gititemsummary.qtpl:69
 	qw422016.N().S(`
-<h4>Summary</h4>
+  </div>
+</div>
 `)
-//line gititemsummary.qtpl:10
+//line gititemsummary.qtpl:72
 }
 
-//line gititemsummary.qtpl:10
+//line gititemsummary.qtpl:72
 func (g *GitItemSummaryPage) WriteGitContent(qq422016 qtio422016.Writer, name, ref string) {
-//line gititemsummary.qtpl:10
+//line gititemsummary.qtpl:72
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line gititemsummary.qtpl:10
+//line gititemsummary.qtpl:72
 	g.StreamGitContent(qw422016, name, ref)
-//line gititemsummary.qtpl:10
+//line gititemsummary.qtpl:72
 	qt422016.ReleaseWriter(qw422016)
-//line gititemsummary.qtpl:10
+//line gititemsummary.qtpl:72
 }
 
-//line gititemsummary.qtpl:10
+//line gititemsummary.qtpl:72
 func (g *GitItemSummaryPage) GitContent(name, ref string) string {
-//line gititemsummary.qtpl:10
+//line gititemsummary.qtpl:72
 	qb422016 := qt422016.AcquireByteBuffer()
-//line gititemsummary.qtpl:10
+//line gititemsummary.qtpl:72
 	g.WriteGitContent(qb422016, name, ref)
-//line gititemsummary.qtpl:10
+//line gititemsummary.qtpl:72
 	qs422016 := string(qb422016.B)
-//line gititemsummary.qtpl:10
+//line gititemsummary.qtpl:72
 	qt422016.ReleaseByteBuffer(qb422016)
-//line gititemsummary.qtpl:10
+//line gititemsummary.qtpl:72
 	return qs422016
-//line gititemsummary.qtpl:10
+//line gititemsummary.qtpl:72
 }