author | Lars Hjemli <hjemli@gmail.com> | 2007-06-17 22:18:42 (UTC) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2007-06-18 06:29:53 (UTC) |
commit | b8be028a309381b83abe924f5e8e01cf02b121a2 (patch) (side-by-side diff) | |
tree | 669b8ac253e8cc1d8568723167764f5428ae5d83 | |
parent | 4a0be586662843382ecfa53af34a13b291312bc0 (diff) | |
download | cgit-b8be028a309381b83abe924f5e8e01cf02b121a2.zip cgit-b8be028a309381b83abe924f5e8e01cf02b121a2.tar.gz cgit-b8be028a309381b83abe924f5e8e01cf02b121a2.tar.bz2 |
Add more menuitems on repo pages
In an attempt to get better usability, a set of 'semistatic' menuitems
are added to the page header on all pages except the repository index.
The menuitems (summary, log, files, commit and diff) honours the current
branch and revision. To switch the current branch one can use the branch
links on the summary page.
The backlink to the repository index page is now available by clicking
the static page heading.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
-rw-r--r-- | cgit.css | 14 | ||||
-rw-r--r-- | ui-shared.c | 51 |
2 files changed, 49 insertions, 16 deletions
@@ -1,315 +1,325 @@ body { font-family: arial, sans-serif; font-size: 11pt; color: black; background: white; } body, table { padding: 0em; margin: 0em; } table { border-collapse: collapse; } h2 { font-size: 120%; font-weight: bold; margin-top: 0em; margin-bottom: 0.25em; } h3 { margin-top: 0em; font-size: 100%; font-weight: normal; } h4 { margin-top: 1.5em; margin-bottom: 0.1em; font-size: 100%; font-weight: bold; } a { color: blue; text-decoration: none; } a:hover { text-decoration: underline; } table.list { border: none; border-collapse: collapse; } table.list tr { background: white; } table.list tr:hover { background: #eee; } table.list tr.nohover:hover { background: white; } table.list th { font-weight: bold; border-bottom: solid 1px #777; padding: 0.1em 0.5em 0.1em 0.5em; vertical-align: baseline; } table.list td { border: none; padding: 0.1em 0.5em 0.1em 0.5em; } img { border: none; } table#layout { width: 100%; border-collapse: collapse; margin: 0px; } td#header, td#logo { color: #666; background-color: #ddd; border-bottom: solid 1px #000; } td#header { font-size: 150%; font-weight: bold; padding: 0.2em 0.5em; vertical-align: text-bottom; } +td#header a { + color: #666; +} + +td#header a:hoved { + text-decoration: underline; +} + td#logo { text-align: right; vertical-align: middle; padding-right: 0.5em; } td#crumb, td#search { color: #ccc; border-top: solid 3px #555; background-color: #666; border-bottom: solid 1px #333; padding: 2px 1em; } td#crumb { font-weight: bold; } td#crumb a { color: #ccc; background-color: #666; + padding: 0em 0.5em 0em 0.5em; } td#crumb a:hover { - color: #eee; - background-color: #666; + color: #666; + background-color: #ccc; + text-decoration: none; } td#search { text-align: right; vertical-align: middle; padding-right: 0.5em; } td#search form { margin: 0px; padding: 0px; } td#search input { font-size: 9pt; padding: 0px; width: 10em; border: solid 1px #333; color: #333; background-color: #fff; } div#summary { vertical-align: top; margin-bottom: 1em; } table#downloads { float: right; border-collapse: collapse; border: solid 1px #777; margin-left: 0.5em; margin-bottom: 0.5em; } table#downloads th { background-color: #ccc; } td#content { padding: 1em 0.5em; } div#blob { border: solid 1px black; } div.error { color: red; font-weight: bold; margin: 1em 2em; } a.ls-blob, a.ls-dir, a.ls-mod { font-family: monospace; } td.ls-size { text-align: right; } td.ls-size { font-family: monospace; } td.ls-mode { font-family: monospace; } table.blob { margin-top: 0.5em; border-top: solid 1px black; } table.blob td.no { border-right: solid 1px black; color: black; background-color: #eee; text-align: right; } table.blob td.txt { white-space: pre; font-family: monospace; padding-left: 0.5em; } table.nowrap td { white-space: nowrap; } table.commit-info { border-collapse: collapse; margin-top: 1.5em; } table.commit-info th { text-align: left; font-weight: normal; padding: 0.1em 1em 0.1em 0.1em; } table.commit-info td { font-weight: normal; padding: 0.1em 1em 0.1em 0.1em; } div.commit-subject { font-weight: bold; font-size: 125%; margin: 1.5em 0em 0.5em 0em; padding: 0em; } div.commit-msg { white-space: pre; font-family: monospace; } div.diffstat-header { font-weight: bold; padding-top: 1.5em; } table.diffstat { border-collapse: collapse; width: 100%; border: solid 1px #aaa; background-color: #eee; } table.diffstat tr:hover { background-color: #ccc; } table.diffstat th { font-weight: normal; text-align: left; text-decoration: underline; padding: 0.1em 1em 0.1em 0.1em; font-size: 100%; } table.diffstat td { padding: 0.2em 0.2em 0.1em 0.1em; font-size: 100%; border: none; } table.diffstat td.mode { white-space: nowrap; } table.diffstat td span.modechange { padding-left: 1em; color: red; } table.diffstat td.add a { color: green; } table.diffstat td.del a { color: red; } table.diffstat td.upd a { color: blue; } table.diffstat td.graph { width: 75%; vertical-align: middle; } table.diffstat td.graph table { border: none; } table.diffstat td.graph td { padding: 0px; border: 0px; height: 7pt; } table.diffstat td.graph td.add { background-color: #5c5; } table.diffstat td.graph td.rem { background-color: #c55; } diff --git a/ui-shared.c b/ui-shared.c index 15d8254..383b8ac 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -1,331 +1,354 @@ /* ui-shared.c: common web output functions * * Copyright (C) 2006 Lars Hjemli * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ #include "cgit.h" const char cgit_doctype[] = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"; static char *http_date(time_t t) { static char day[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; static char month[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Now", "Dec"}; struct tm *tm = gmtime(&t); return fmt("%s, %02d %s %04d %02d:%02d:%02d GMT", day[tm->tm_wday], tm->tm_mday, month[tm->tm_mon], 1900+tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec); } static long ttl_seconds(long ttl) { if (ttl<0) return 60 * 60 * 24 * 365; else return ttl * 60; } void cgit_print_error(char *msg) { html("<div class='error'>"); html_txt(msg); html("</div>\n"); } char *cgit_rooturl() { if (cgit_virtual_root) return fmt("%s/", cgit_virtual_root); else return cgit_script_name; } char *cgit_repourl(const char *reponame) { if (cgit_virtual_root) { return fmt("%s/%s/", cgit_virtual_root, reponame); } else { return fmt("?r=%s", reponame); } } char *cgit_pageurl(const char *reponame, const char *pagename, const char *query) { if (cgit_virtual_root) { if (query) return fmt("%s/%s/%s/?%s", cgit_virtual_root, reponame, pagename, query); else return fmt("%s/%s/%s/", cgit_virtual_root, reponame, pagename); } else { if (query) return fmt("?r=%s&p=%s&%s", reponame, pagename, query); else return fmt("?r=%s&p=%s", reponame, pagename); } } char *cgit_currurl() { if (!cgit_virtual_root) return cgit_script_name; else if (cgit_query_page) return fmt("%s/%s/%s/", cgit_virtual_root, cgit_query_repo, cgit_query_page); else if (cgit_query_repo) return fmt("%s/%s/", cgit_virtual_root, cgit_query_repo); else return fmt("%s/", cgit_virtual_root); } static char *repolink(char *title, char *class, char *page, char *head, char *path) { char *delim = "?"; html("<a"); if (title) { html(" title='"); html_attr(title); html("'"); } if (class) { html(" class='"); html_attr(class); html("'"); } html(" href='"); if (cgit_virtual_root) { html_attr(cgit_virtual_root); if (cgit_virtual_root[strlen(cgit_virtual_root) - 1] != '/') html("/"); html_attr(cgit_repo->url); if (cgit_repo->url[strlen(cgit_repo->url) - 1] != '/') html("/"); - html(page); - html("/"); - if (path) - html_attr(path); + if (page) { + html(page); + html("/"); + if (path) + html_attr(path); + } } else { html(cgit_script_name); html("?url="); html_attr(cgit_repo->url); if (cgit_repo->url[strlen(cgit_repo->url) - 1] != '/') html("/"); - html(page); - html("/"); - if (path) - html_attr(path); + if (page) { + html(page); + html("/"); + if (path) + html_attr(path); + } delim = "&"; } if (head && strcmp(head, cgit_repo->defbranch)) { html(delim); html("h="); html_attr(head); delim = "&"; } return fmt("%s", delim); } static void reporevlink(char *page, char *name, char *title, char *class, char *head, char *rev, char *path) { char *delim; delim = repolink(title, class, page, head, path); if (rev && strcmp(rev, cgit_query_head)) { html(delim); html("id="); html_attr(rev); } html("'>"); html_txt(name); html("</a>"); } void cgit_tree_link(char *name, char *title, char *class, char *head, char *rev, char *path) { reporevlink("tree", name, title, class, head, rev, path); } void cgit_log_link(char *name, char *title, char *class, char *head, char *rev, char *path) { reporevlink("log", name, title, class, head, rev, path); } void cgit_commit_link(char *name, char *title, char *class, char *head, char *rev) { if (strlen(name) > cgit_max_msg_len && cgit_max_msg_len >= 15) { name[cgit_max_msg_len] = '\0'; name[cgit_max_msg_len - 1] = '.'; name[cgit_max_msg_len - 2] = '.'; name[cgit_max_msg_len - 3] = '.'; } reporevlink("commit", name, title, class, head, rev, NULL); } void cgit_diff_link(char *name, char *title, char *class, char *head, char *new_rev, char *old_rev, char *path) { char *delim; delim = repolink(title, class, "diff", head, path); if (new_rev && strcmp(new_rev, cgit_query_head)) { html(delim); html("id="); html_attr(new_rev); delim = "&"; } if (old_rev) { html(delim); html("id2="); html_attr(old_rev); } html("'>"); html_txt(name); html("</a>"); } void cgit_print_date(time_t secs, char *format) { char buf[64]; struct tm *time; time = gmtime(&secs); strftime(buf, sizeof(buf)-1, format, time); html_txt(buf); } void cgit_print_age(time_t t, time_t max_relative, char *format) { time_t now, secs; time(&now); secs = now - t; if (secs > max_relative && max_relative >= 0) { cgit_print_date(t, format); return; } if (secs < TM_HOUR * 2) { htmlf("<span class='age-mins'>%.0f min.</span>", secs * 1.0 / TM_MIN); return; } if (secs < TM_DAY * 2) { htmlf("<span class='age-hours'>%.0f hours</span>", secs * 1.0 / TM_HOUR); return; } if (secs < TM_WEEK * 2) { htmlf("<span class='age-days'>%.0f days</span>", secs * 1.0 / TM_DAY); return; } if (secs < TM_MONTH * 2) { htmlf("<span class='age-weeks'>%.0f weeks</span>", secs * 1.0 / TM_WEEK); return; } if (secs < TM_YEAR * 2) { htmlf("<span class='age-months'>%.0f months</span>", secs * 1.0 / TM_MONTH); return; } htmlf("<span class='age-years'>%.0f years</span>", secs * 1.0 / TM_YEAR); } void cgit_print_docstart(char *title, struct cacheitem *item) { html("Content-Type: text/html; charset=utf-8\n"); htmlf("Last-Modified: %s\n", http_date(item->st.st_mtime)); htmlf("Expires: %s\n", http_date(item->st.st_mtime + ttl_seconds(item->ttl))); html("\n"); html(cgit_doctype); html("<html>\n"); html("<head>\n"); html("<title>"); html_txt(title); html("</title>\n"); htmlf("<meta name='generator' content='cgit v%s'/>\n", cgit_version); html("<link rel='stylesheet' type='text/css' href='"); html_attr(cgit_css); html("'/>\n"); html("</head>\n"); html("<body>\n"); } void cgit_print_docend() { html("</td></tr></table>"); html("</body>\n</html>\n"); } void cgit_print_pageheader(char *title, int show_search) { html("<table id='layout'>"); - html("<tr><td id='header'>"); - html(cgit_root_title); - html("</td><td id='logo'>"); + html("<tr><td id='header'><a href='"); + html_attr(cgit_rooturl()); + html("'>"); + html_txt(cgit_root_title); + html("</a></td><td id='logo'>"); html("<a href='"); html_attr(cgit_logo_link); htmlf("'><img src='%s' alt='logo'/></a>", cgit_logo); html("</td></tr>"); html("<tr><td id='crumb'>"); - htmlf("<a href='%s'>root</a>", cgit_rooturl()); if (cgit_query_repo) { - htmlf(" : <a href='%s'>", cgit_repourl(cgit_repo->url)); html_txt(cgit_repo->name); - htmlf("</a> : %s", title); + html(" ("); + html_txt(cgit_query_head); + html(") : "); + reporevlink(NULL, "summary", NULL, NULL, cgit_query_head, + NULL, NULL); + html(" "); + cgit_log_link("log", NULL, NULL, cgit_query_head, + cgit_query_sha1, cgit_query_path); + html(" "); + cgit_tree_link("files", NULL, NULL, cgit_query_head, + cgit_query_sha1, cgit_query_path); + html(" "); + cgit_commit_link("commit", NULL, NULL, cgit_query_head, + cgit_query_sha1); + html(" "); + cgit_diff_link("diff", NULL, NULL, cgit_query_head, + cgit_query_sha1, cgit_query_sha2, + cgit_query_path); + } else { + html_txt("Index of repositories"); } html("</td>"); html("<td id='search'>"); if (show_search) { html("<form method='get' action='"); html_attr(cgit_currurl()); html("'>"); if (!cgit_virtual_root) { if (cgit_query_repo) html_hidden("r", cgit_query_repo); if (cgit_query_page) html_hidden("p", cgit_query_page); } if (cgit_query_head) html_hidden("h", cgit_query_head); if (cgit_query_sha1) html_hidden("id", cgit_query_sha1); if (cgit_query_sha2) html_hidden("id2", cgit_query_sha2); html("<input type='text' name='q' value='"); html_attr(cgit_query_search); html("'/></form>"); } html("</td></tr>"); html("<tr><td id='content' colspan='2'>"); } void cgit_print_snapshot_start(const char *mimetype, const char *filename, struct cacheitem *item) { htmlf("Content-Type: %s\n", mimetype); htmlf("Content-Disposition: inline; filename=\"%s\"\n", filename); htmlf("Last-Modified: %s\n", http_date(item->st.st_mtime)); htmlf("Expires: %s\n", http_date(item->st.st_mtime + ttl_seconds(item->ttl))); html("\n"); } |