summaryrefslogtreecommitdiffabout
authorLars Hjemli <hjemli@gmail.com>2007-10-30 09:47:38 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2007-10-30 12:38:34 (UTC)
commit0c8e184e9cbf4d3a1e907de9125f6d8210c169d6 (patch) (unidiff)
tree2e82baf582b7ba0b34f498e1e7494800070067f9
parent10ac7ad1f30f914dc5ff36ba3651ef6dca11aaf7 (diff)
downloadcgit-0c8e184e9cbf4d3a1e907de9125f6d8210c169d6.zip
cgit-0c8e184e9cbf4d3a1e907de9125f6d8210c169d6.tar.gz
cgit-0c8e184e9cbf4d3a1e907de9125f6d8210c169d6.tar.bz2
Change the cgit layout
This modifies and hopefully improves the layout of all cgit pages: * Remove the header from all pages and replace it with a sidebar; most pages have sufficient width but many needs more height. * Add a dropdown-box to switch between branches, using a one-liner javascript to reload the current page in context of the selected branch. * Include refs found below refs/archives in the sidebar, appearing as a set of menuitems below a 'download' heading. * Include the brand new cgit logo Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.css149
-rw-r--r--cgit.h2
-rw-r--r--cgit.pngbin0 -> 3790 bytes
-rw-r--r--cgitrc9
-rw-r--r--shared.c31
-rw-r--r--ui-shared.c172
-rw-r--r--ui-summary.c65
7 files changed, 231 insertions, 197 deletions
diff --git a/cgit.css b/cgit.css
index 5d47099..6cf4517 100644
--- a/cgit.css
+++ b/cgit.css
@@ -1,15 +1,16 @@
1body {
2 font-family: arial, sans-serif;
3 font-size: 11pt;
4 color: black;
5 background: white;
6}
7
8body, table { 1body, table {
9 padding: 0em; 2 padding: 0em;
10 margin: 0em; 3 margin: 0em;
11} 4}
12 5
6body {
7 font-family: sans;
8 font-size: 10pt;
9 color: #333;
10 background: white;
11 padding-left: 4px;
12}
13
13table { 14table {
14 border-collapse: collapse; 15 border-collapse: collapse;
15} 16}
@@ -35,12 +36,13 @@ h4 {
35} 36}
36 37
37a { 38a {
38 color: blue; 39 color: #600;
39 text-decoration: none; 40 text-decoration: none;
40} 41}
41 42
42a:hover { 43a:hover {
43 text-decoration: underline; 44 background-color: #ddd;
45 text-decoration: none;
44} 46}
45 47
46table.list { 48table.list {
@@ -53,7 +55,7 @@ table.list tr {
53} 55}
54 56
55table.list tr:hover { 57table.list tr:hover {
56 background: #eee; 58 background: #f8f8f8;
57} 59}
58 60
59table.list tr.nohover:hover { 61table.list tr.nohover:hover {
@@ -76,98 +78,78 @@ img {
76 border: none; 78 border: none;
77} 79}
78 80
79table#layout { 81div#sidebar {
80 width: 100%; 82 vertical-align: top;
81 border-collapse: collapse; 83 width: 162px;
82 margin: 0px; 84 padding: 0px 0px 0px 0px;
83} 85 margin: 4px;
84 86 float: left;
85td#header, td#logo {
86 color: #666;
87 background-color: #ddd;
88 border-bottom: solid 1px #000;
89}
90
91td#header {
92 font-size: 150%;
93 font-weight: bold;
94 padding: 0.2em 0.5em;
95 vertical-align: text-bottom;
96}
97
98td#header a {
99 color: #666;
100}
101
102td#header a:hover {
103 text-decoration: underline;
104} 87}
105 88
106td#logo { 89div#logo {
107 text-align: right; 90 margin: 0px;
108 vertical-align: middle; 91 padding: 4px 0px 4px 0px;
109 padding-right: 0.5em; 92 text-align: center;
93 background-color: #ccc;
94 border-top: solid 1px #eee;
95 border-left: solid 1px #eee;
96 border-right: solid 1px #aaa;
97 border-bottom: solid 1px #aaa;
110} 98}
111 99
112td#crumb, td#search { 100div#sidebar div.infobox {
113 color: #ccc; 101 margin: 0px 0px 0pax 0px;
114 border-top: solid 3px #555; 102 padding: 0.5em;
115 background-color: #666; 103 text-align: left;
116 border-bottom: solid 1px #333; 104 background-color: #ccc;
117 padding: 2px 1em; 105 border-top: solid 1px #eee;
106 border-left: solid 1px #eee;
107 border-right: solid 1px #aaa;
108 border-bottom: solid 1px #aaa;
118} 109}
119 110
120td#crumb { 111div#sidebar div.infobox h1 {
112 font-size: 11pt;
121 font-weight: bold; 113 font-weight: bold;
114 margin: 0px;
122} 115}
123 116
124td#crumb a { 117div#sidebar div.infobox a.menu {
125 color: #ccc; 118 display: block;
126 background-color: #666;
127 padding: 0em 0.5em 0em 0.5em;
128}
129
130td#crumb a:hover {
131 color: #666;
132 background-color: #ccc; 119 background-color: #ccc;
120 padding: 0.1em 0.5em;
133 text-decoration: none; 121 text-decoration: none;
134} 122}
135 123
136td#search { 124div#sidebar div.infobox a.menu:hover {
137 text-align: right; 125 background-color: #bbb;
138 vertical-align: middle; 126 text-decoration: none;
139 padding-right: 0.5em;
140}
141
142td#search form {
143 margin: 0px;
144 padding: 0px;
145} 127}
146 128
147td#search select { 129div#sidebar div.infobox select {
148 font-size: 9pt; 130 width: 100%;
131 border: solid 1px #aaa;
132 background-color: #bbb;
133 margin: 2px 0px 0px 0px;
149 padding: 0px; 134 padding: 0px;
150 border: solid 1px #333;
151 color: #333;
152 background-color: #fff;
153} 135}
154 136
155td#search input { 137div#sidebar div.infobox input.txt {
156 font-size: 9pt; 138 width: 100%;
157 padding: 0px; 139 border: solid 1px #aaa;
140 background-color: #bbb;
141 margin: 2px 0px 0px 0px;
142 padding: 0;
158} 143}
159 144
160td#search input.txt { 145table#grid {
161 width: 8em; 146 margin: 0px;
162 border: solid 1px #333;
163 color: #333;
164 background-color: #fff;
165} 147}
166 148
167td#search input.btn { 149td#content {
168 border: solid 1px #333; 150 vertical-align: top;
169 color: #333; 151 padding: 1em 2em 1em 1em;
170 background-color: #ccc; 152 border: none;
171} 153}
172 154
173div#summary { 155div#summary {
@@ -187,10 +169,6 @@ table#downloads th {
187 background-color: #ccc; 169 background-color: #ccc;
188} 170}
189 171
190td#content {
191 padding: 1em 0.5em;
192}
193
194div#blob { 172div#blob {
195 border: solid 1px black; 173 border: solid 1px black;
196} 174}
@@ -284,7 +262,6 @@ div.diffstat-header {
284 262
285table.diffstat { 263table.diffstat {
286 border-collapse: collapse; 264 border-collapse: collapse;
287 width: 100%;
288 border: solid 1px #aaa; 265 border: solid 1px #aaa;
289 background-color: #eee; 266 background-color: #eee;
290} 267}
@@ -325,7 +302,7 @@ table.diffstat td.upd a {
325} 302}
326 303
327table.diffstat td.graph { 304table.diffstat td.graph {
328 width: 75%; 305 width: 500px;
329 vertical-align: middle; 306 vertical-align: middle;
330} 307}
331 308
diff --git a/cgit.h b/cgit.h
index b8af970..42036c3 100644
--- a/cgit.h
+++ b/cgit.h
@@ -181,6 +181,8 @@ extern int chk_non_negative(int result, char *msg);
181 181
182extern int hextoint(char c); 182extern int hextoint(char c);
183extern char *trim_end(const char *str, char c); 183extern char *trim_end(const char *str, char c);
184extern char *strlpart(char *txt, int maxlen);
185extern char *strrpart(char *txt, int maxlen);
184 186
185extern void cgit_add_ref(struct reflist *list, struct refinfo *ref); 187extern void cgit_add_ref(struct reflist *list, struct refinfo *ref);
186extern int cgit_refs_cb(const char *refname, const unsigned char *sha1, 188extern int cgit_refs_cb(const char *refname, const unsigned char *sha1,
diff --git a/cgit.png b/cgit.png
new file mode 100644
index 0000000..ee48197
--- a/dev/null
+++ b/cgit.png
Binary files differ
diff --git a/cgitrc b/cgitrc
index 2b09e01..6363c9c 100644
--- a/cgitrc
+++ b/cgitrc
@@ -85,8 +85,13 @@
85#root-title=Git repository browser 85#root-title=Git repository browser
86 86
87 87
88## If specified, the file at this path will be included as HTML in the index 88## If specified, the file at this path will be included as HTML in the
89## of repositories 89## sidebar on the repository index page
90#index-info=
91
92
93## If specified, the file at this path will be included as HTML above
94## the repository index
90#index-header= 95#index-header=
91 96
92 97
diff --git a/shared.c b/shared.c
index 50fe8e1..e06df91 100644
--- a/shared.c
+++ b/shared.c
@@ -303,6 +303,37 @@ char *trim_end(const char *str, char c)
303 return s; 303 return s;
304} 304}
305 305
306char *strlpart(char *txt, int maxlen)
307{
308 char *result;
309
310 if (!txt)
311 return txt;
312
313 if (strlen(txt) <= maxlen)
314 return txt;
315 result = xmalloc(maxlen + 1);
316 memcpy(result, txt, maxlen - 3);
317 result[maxlen-1] = result[maxlen-2] = result[maxlen-3] = '.';
318 result[maxlen] = '\0';
319 return result;
320}
321
322char *strrpart(char *txt, int maxlen)
323{
324 char *result;
325
326 if (!txt)
327 return txt;
328
329 if (strlen(txt) <= maxlen)
330 return txt;
331 result = xmalloc(maxlen + 1);
332 memcpy(result + 3, txt + strlen(txt) - maxlen + 4, maxlen - 3);
333 result[0] = result[1] = result[2] = '.';
334 return result;
335}
336
306void cgit_add_ref(struct reflist *list, struct refinfo *ref) 337void cgit_add_ref(struct reflist *list, struct refinfo *ref)
307{ 338{
308 size_t size; 339 size_t size;
diff --git a/ui-shared.c b/ui-shared.c
index 1418010..1d66940 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -362,77 +362,149 @@ void cgit_print_docstart(char *title, struct cacheitem *item)
362 362
363void cgit_print_docend() 363void cgit_print_docend()
364{ 364{
365 html("</td></tr></table>"); 365 html("</td>\n</tr>\n<table>\n</body>\n</html>\n");
366 html("</body>\n</html>\n"); 366}
367
368int print_branch_option(const char *refname, const unsigned char *sha1,
369 int flags, void *cb_data)
370{
371 char *name = (char *)refname;
372 html_option(name, name, cgit_query_head);
373 return 0;
374}
375
376int print_archive_ref(const char *refname, const unsigned char *sha1,
377 int flags, void *cb_data)
378{
379 struct tag *tag;
380 struct taginfo *info;
381 struct object *obj;
382 char buf[256], *url;
383 unsigned char fileid[20];
384 int *header = (int *)cb_data;
385
386 if (prefixcmp(refname, "refs/archives"))
387 return 0;
388 strncpy(buf, refname+14, sizeof(buf));
389 obj = parse_object(sha1);
390 if (!obj)
391 return 1;
392 if (obj->type == OBJ_TAG) {
393 tag = lookup_tag(sha1);
394 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag)))
395 return 0;
396 hashcpy(fileid, tag->tagged->sha1);
397 } else if (obj->type != OBJ_BLOB) {
398 return 0;
399 } else {
400 hashcpy(fileid, sha1);
401 }
402 if (!*header) {
403 html("<p><h1>download</h1>");
404 *header = 1;
405 }
406 url = cgit_pageurl(cgit_query_repo, "blob",
407 fmt("id=%s&amp;path=%s", sha1_to_hex(fileid),
408 buf));
409 html_link_open(url, NULL, "menu");
410 html_txt(strlpart(buf, 20));
411 html_link_close();
412 return 0;
413}
414
415void add_hidden_formfields(int incl_head, int incl_search)
416{
417 if (!cgit_virtual_root) {
418 if (cgit_query_repo)
419 html_hidden("r", cgit_query_repo);
420 if (cgit_query_page)
421 html_hidden("p", cgit_query_page);
422 }
423
424 if (incl_head && strcmp(cgit_query_head, cgit_repo->defbranch))
425 html_hidden("h", cgit_query_head);
426
427 if (cgit_query_sha1)
428 html_hidden("id", cgit_query_sha1);
429 if (cgit_query_sha2)
430 html_hidden("id2", cgit_query_sha2);
431
432 if (incl_search) {
433 if (cgit_query_grep)
434 html_hidden("qt", cgit_query_grep);
435 if (cgit_query_search)
436 html_hidden("q", cgit_query_search);
437 }
367} 438}
368 439
369void cgit_print_pageheader(char *title, int show_search) 440void cgit_print_pageheader(char *title, int show_search)
370{ 441{
371 html("<table id='layout'>"); 442 static const char *default_info = "This is cgit, a fast webinterface for git repositories";
372 html("<tr><td id='header'><a href='"); 443 int header = 0;
373 html_attr(cgit_rooturl()); 444
374 html("'>"); 445 html("<div id='sidebar'>\n");
375 html_txt(cgit_root_title);
376 html("</a></td><td id='logo'>");
377 html("<a href='"); 446 html("<a href='");
378 html_attr(cgit_logo_link); 447 html_attr(cgit_rooturl());
379 htmlf("'><img src='%s' alt='logo'/></a>", cgit_logo); 448 htmlf("'><div id='logo'><img src='%s' alt='cgit'/></div></a>\n",
380 html("</td></tr>"); 449 cgit_logo);
381 html("<tr><td id='crumb'>"); 450 html("<div class='infobox'>");
382 if (cgit_query_repo) { 451 if (cgit_query_repo) {
383 html_txt(cgit_repo->name); 452 html("<h1>");
384 html(" ("); 453 html_txt(strrpart(cgit_repo->name, 20));
385 html_txt(cgit_query_head); 454 html("</h1>\n");
386 html(") : &nbsp;"); 455 html_txt(cgit_repo->desc);
387 reporevlink(NULL, "summary", NULL, NULL, cgit_query_head, 456 if (cgit_repo->owner) {
457 html("<p>\n<h1>owner</h1>\n");
458 html_txt(cgit_repo->owner);
459 }
460 html("<p>\n<h1>navigate</h1>\n");
461 reporevlink(NULL, "summary", NULL, "menu", cgit_query_head,
388 NULL, NULL); 462 NULL, NULL);
389 html(" "); 463 cgit_log_link("log", NULL, "menu", cgit_query_head,
390 cgit_log_link("log", NULL, NULL, cgit_query_head,
391 cgit_query_sha1, cgit_query_path, 0); 464 cgit_query_sha1, cgit_query_path, 0);
392 html(" "); 465 cgit_tree_link("tree", NULL, "menu", cgit_query_head,
393 cgit_tree_link("tree", NULL, NULL, cgit_query_head,
394 cgit_query_sha1, NULL); 466 cgit_query_sha1, NULL);
395 html(" "); 467 cgit_commit_link("commit", NULL, "menu", cgit_query_head,
396 cgit_commit_link("commit", NULL, NULL, cgit_query_head,
397 cgit_query_sha1); 468 cgit_query_sha1);
398 html(" "); 469 cgit_diff_link("diff", NULL, "menu", cgit_query_head,
399 cgit_diff_link("diff", NULL, NULL, cgit_query_head,
400 cgit_query_sha1, cgit_query_sha2, 470 cgit_query_sha1, cgit_query_sha2,
401 cgit_query_path); 471 cgit_query_path);
402 } else { 472
403 html_txt("Index of repositories"); 473 for_each_ref(print_archive_ref, &header);
404 } 474
405 html("</td>"); 475 html("<p>\n<h1>branch</h1>\n");
406 html("<td id='search'>"); 476 html("<form method='get' action=''>\n");
407 if (show_search) { 477 add_hidden_formfields(0, 1);
478 html("<select name='h' onchange='this.form.submit();'>\n");
479 for_each_branch_ref(print_branch_option, cgit_query_head);
480 html("</select>\n");
481 html("</form>\n");
482
483 html("<p>\n<h1>search</h1>\n");
408 html("<form method='get' action='"); 484 html("<form method='get' action='");
409 html_attr(cgit_currurl()); 485 html_attr(cgit_pageurl(cgit_query_repo, "log", NULL));
410 html("'>"); 486 html("'>\n");
411 if (!cgit_virtual_root) { 487 add_hidden_formfields(1, 0);
412 if (cgit_query_repo) 488 html("<select name='qt'>\n");
413 html_hidden("r", cgit_query_repo);
414 if (cgit_query_page)
415 html_hidden("p", cgit_query_page);
416 }
417 if (cgit_query_head)
418 html_hidden("h", cgit_query_head);
419 if (cgit_query_sha1)
420 html_hidden("id", cgit_query_sha1);
421 if (cgit_query_sha2)
422 html_hidden("id2", cgit_query_sha2);
423 html("<select name='qt'>");
424 html_option("grep", "log msg", cgit_query_grep); 489 html_option("grep", "log msg", cgit_query_grep);
425 html_option("author", "author", cgit_query_grep); 490 html_option("author", "author", cgit_query_grep);
426 html_option("committer", "committer", cgit_query_grep); 491 html_option("committer", "committer", cgit_query_grep);
427 html("</select>"); 492 html("</select>\n");
428 html("<input class='txt' type='text' name='q' value='"); 493 html("<input class='txt' type='text' name='q' value='");
429 html_attr(cgit_query_search); 494 html_attr(cgit_query_search);
430 html("'/><input class='btn' type='submit' value='...'/></form>"); 495 html("'/>\n");
496 html("</form>\n");
497 } else {
498 if (!cgit_index_info || html_include(cgit_index_info))
499 html(default_info);
431 } 500 }
432 html("</td></tr>"); 501
433 html("<tr><td id='content' colspan='2'>"); 502 html("</div>\n");
503
504 html("</div>\n<table class='grid'><tr><td id='content'>\n");
434} 505}
435 506
507
436void cgit_print_snapshot_start(const char *mimetype, const char *filename, 508void cgit_print_snapshot_start(const char *mimetype, const char *filename,
437 struct cacheitem *item) 509 struct cacheitem *item)
438{ 510{
diff --git a/ui-summary.c b/ui-summary.c
index ba90510..39fe330 100644
--- a/ui-summary.c
+++ b/ui-summary.c
@@ -120,47 +120,6 @@ static int print_tag(struct refinfo *ref)
120 return 0; 120 return 0;
121} 121}
122 122
123static int cgit_print_archive_cb(const char *refname, const unsigned char *sha1,
124 int flags, void *cb_data)
125{
126 struct tag *tag;
127 struct taginfo *info;
128 struct object *obj;
129 char buf[256], *url;
130 unsigned char fileid[20];
131
132 if (prefixcmp(refname, "refs/archives"))
133 return 0;
134 strncpy(buf, refname+14, sizeof(buf));
135 obj = parse_object(sha1);
136 if (!obj)
137 return 1;
138 if (obj->type == OBJ_TAG) {
139 tag = lookup_tag(sha1);
140 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag)))
141 return 0;
142 hashcpy(fileid, tag->tagged->sha1);
143 } else if (obj->type != OBJ_BLOB) {
144 return 0;
145 } else {
146 hashcpy(fileid, sha1);
147 }
148 if (!header) {
149 html("<table id='downloads'>");
150 html("<tr><th>Downloads</th></tr>");
151 header = 1;
152 }
153 html("<tr><td>");
154 url = cgit_pageurl(cgit_query_repo, "blob",
155 fmt("id=%s&amp;path=%s", sha1_to_hex(fileid),
156 buf));
157 html_link_open(url, NULL, NULL);
158 html_txt(buf);
159 html_link_close();
160 html("</td></tr>");
161 return 0;
162}
163
164static void print_refs_link(char *path) 123static void print_refs_link(char *path)
165{ 124{
166 html("<tr class='nohover'><td colspan='4'>"); 125 html("<tr class='nohover'><td colspan='4'>");
@@ -221,28 +180,16 @@ void cgit_print_tags(int maxcount)
221 print_refs_link("tags"); 180 print_refs_link("tags");
222} 181}
223 182
224static void cgit_print_archives()
225{
226 header = 0;
227 for_each_ref(cgit_print_archive_cb, NULL);
228 if (header)
229 html("</table>");
230}
231
232void cgit_print_summary() 183void cgit_print_summary()
233{ 184{
234 html("<div id='summary'>"); 185 if (cgit_repo->readme) {
235 cgit_print_archives(); 186 html("<div id='summary'>");
236 html("<h2>");
237 html_txt(cgit_repo->name);
238 html(" - ");
239 html_txt(cgit_repo->desc);
240 html("</h2>");
241 if (cgit_repo->readme)
242 html_include(cgit_repo->readme); 187 html_include(cgit_repo->readme);
243 html("</div>"); 188 html("</div>");
189 }
244 if (cgit_summary_log > 0) 190 if (cgit_summary_log > 0)
245 cgit_print_log(cgit_query_head, 0, cgit_summary_log, NULL, NULL, NULL, 0); 191 cgit_print_log(cgit_query_head, 0, cgit_summary_log, NULL,
192 NULL, NULL, 0);
246 html("<table class='list nowrap'>"); 193 html("<table class='list nowrap'>");
247 if (cgit_summary_log > 0) 194 if (cgit_summary_log > 0)
248 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>"); 195 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>");