timekeeper

[Abandoned unfinished] CGI web application in C for time tracking. (My first, just a learning project)
Log | Files | Refs | README

commit c8c1bdc0d41666d6f7448938be8acb6d6af38588
parent f6800c76a107b76c4c9a004e1946b745ea4615e9
Author: Jacob R. Edwards <jacob@jacobedwards.org>
Date:   Tue, 19 Mar 2024 20:25:02 -0700

Add archive page

This page displays a summary of finished periods and allows you to
display or export them.

Diffstat:
MMakefile | 2+-
Apages/archive.c | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpages/pages.h | 2++
Mtimekeeper.c | 6++++--
4 files changed, 114 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile @@ -5,7 +5,7 @@ lddflags = ${LDDFLAGS} -static -L/usr/local/lib -lkcgi -lkcgihtml -lz -lsqlbox - prefix = /var/www/htdocs/${name}.primus.lan pages = pages/index.c pages/login.c pages/logout.c \ - pages/account.c pages/main.c pages/export.c + pages/account.c pages/main.c pages/export.c pages/archive.c hdrsrc = page.c html.c user.c stmt.c key.c times.c src = ${hdrsrc} ${pages} pages/util.c hdr = ${hdrsrc:.c=.h} util.h pages/util.h pages/pages.h diff --git a/pages/archive.c b/pages/archive.c @@ -0,0 +1,107 @@ +#include <assert.h> +#define const + +#include <time.h> + +#include "common.h" +#include "pages.h" +#include "../times.h" + +enum kcgi_err +showform(struct pagedata *pd, char *name, int page, int64_t period) +{ + enum kcgi_err status; + + if ((status = khtml_attr(&pd->html, KELEM_FORM, + KATTR_ACTION, pd->pages[page], KATTR__MAX)) != KCGI_OK || + (status = khtml_attrx(&pd->html, KELEM_INPUT, + KATTR_TYPE, KATTRX_STRING, "hidden", + KATTR_NAME, KATTRX_STRING, pd->keys[KeyPeriod].name, + KATTR_VALUE, KATTRX_INT, period, + KATTR__MAX)) != KCGI_OK || + (status = khtml_attr(&pd->html, KELEM_INPUT, + KATTR_TYPE, "submit", + KATTR_VALUE, name, KATTR__MAX)) != KCGI_OK || + (status = khtml_closeelem(&pd->html, 1)) != KCGI_OK) + return status; + return KCGI_OK; +} + +enum kcgi_err +showperiod(struct pagedata *pd, struct timesheet **rts) +{ + enum kcgi_err status; + time_t from, to; + struct timesheet *ts, *lts; + time_t duration; + unsigned int period; + unsigned int count; + + ts = *rts; + assert(ts->set & StartTimeFlag); + from = ts->times[StartTime]; + + duration = 0; + period = ts->period; + count = 0; + for (; ts && ts->period == period; ts = ts->next) { + duration += getduration(ts); + lts = ts; + ++count; + } + + assert(lts->set & EndTimeFlag); + to = lts->times[EndTime]; + + if ((status = khtml_attrx(&pd->html, KELEM_LI, + KATTR_VALUE, KATTRX_INT, (int64_t)period, + KATTR__MAX)) != KCGI_OK || + (status = htmldate(pd, from)) != KCGI_OK || + (status = khtml_puts(&pd->html, " to ")) != KCGI_OK || + (status = htmldate(pd, to)) != KCGI_OK || + (status = khtml_printf(&pd->html, "; %d entries, ", count)) != KCGI_OK || + (status = htmlduration(pd, duration, NULL, 0)) != KCGI_OK || + (status = khtml_puts(&pd->html, " hours")) != KCGI_OK || + (status = showform(pd, "Show", PageMain, period)) != KCGI_OK || + (status = showform(pd, "Export", PageExport, period)) != KCGI_OK || + (status = khtml_closeelem(&pd->html, 1))) + return status; + + *rts = ts; + return KCGI_OK; +} + +enum kcgi_err +pagearchive(struct pagedata *pd) +{ + static char *css[] = { "css/main.css", NULL }; + static struct pagetemplate template = { + "Archive", + .css = css + }; + + enum kcgi_err status; + struct timesheet *times, *firsttimes; + + startpage(pd, &template, KHTTP_200); + + if (!pd->user) + errorpage(pd, KHTTP_401); + + if (gettimes(pd, pd->user->hash, -1, &times)) + return KCGI_SYSTEM; + + if ((status = htmlwithin(pd, KELEM_H1, "Archive")) != KCGI_OK || + (status = htmlwithin(pd, KELEM_H2, "Periods")) != KCGI_OK || + (status = khtml_elem(&pd->html, KELEM_OL)) != KCGI_OK) + return status; + + firsttimes = times; + while (times && showperiod(pd, &times) == KCGI_OK) + ; + freetimesheet(firsttimes); + + if ((status = khtml_closeelem(&pd->html, 1)) != KCGI_OK) + return status; + return endpage(pd, &template); +} diff --git a/pages/pages.h b/pages/pages.h @@ -5,6 +5,7 @@ enum Page { PageAccount, PageMain, PageExport, + PageArchive, PageMax }; @@ -14,3 +15,4 @@ enum kcgi_err pagelogout(struct pagedata *pd); enum kcgi_err pageaccount(struct pagedata *pd); enum kcgi_err pageexport(struct pagedata *pd); enum kcgi_err pagemain(struct pagedata *pd); +enum kcgi_err pagearchive(struct pagedata *pd); diff --git a/timekeeper.c b/timekeeper.c @@ -34,7 +34,8 @@ static char *pages[] = { [PageLogout] = "logout", [PageAccount] = "account", [PageMain] = "main", - [PageExport] = "export" + [PageExport] = "export", + [PageArchive] = "archive" }; int @@ -67,7 +68,8 @@ main(void) [PageLogout] = pagelogout, [PageAccount] = pageaccount, [PageMain] = pagemain, - [PageExport] = pageexport + [PageExport] = pageexport, + [PageArchive] = pagearchive }; memset(&cfg, 0, sizeof(cfg));