aboutsummaryrefslogtreecommitdiff
path: root/clients
diff options
context:
space:
mode:
Diffstat (limited to 'clients')
-rw-r--r--clients/bokftui.c134
1 files changed, 122 insertions, 12 deletions
diff --git a/clients/bokftui.c b/clients/bokftui.c
index ccbce14..a8b582c 100644
--- a/clients/bokftui.c
+++ b/clients/bokftui.c
@@ -1,4 +1,5 @@
#include <dirent.h>
+#include <errno.h>
#include <locale.h>
#include <math.h>
#include <ncursesw/ncurses.h>
@@ -20,6 +21,10 @@
#define KEY_CTRL_N 0x0e
/* Ctrl+C quits the application; Esc is navigation only */
static int g_quit = 0;
+/* Ctrl+R re-execs the binary, keeping session, org, year and screen */
+static int g_reload = 0;
+static char g_scene[32] = "dashboard";
+static char g_reload_scene[32];
static int ui_getch(void)
{
@@ -28,6 +33,11 @@ static int ui_getch(void)
g_quit = 1;
return 27; /* behave like "back" so screens unwind */
}
+ if (ch == 18) { /* Ctrl+R */
+ g_reload = 1;
+ snprintf(g_reload_scene, sizeof g_reload_scene, "%s", g_scene);
+ return 27;
+ }
return ch;
}
@@ -411,8 +421,10 @@ static void frame(const char *title)
static void hints(const char *s)
{
+ char line[512];
+ snprintf(line, sizeof line, "%s ^R = ladda om", s);
attron(A_DIM);
- mvaddstr(LINES - 1, 2, s);
+ mvaddstr(LINES - 1, 2, line);
attroff(A_DIM);
clrtoeol();
}
@@ -3933,6 +3945,52 @@ static void templates_screen(struct app *a)
}
}
+/* Screen names for Ctrl+R restoration and --screen. Only the top-level
+ views; sub-screens unwind to their parent. */
+static void open_scene(struct app *a, const char *scene)
+{
+ snprintf(g_scene, sizeof g_scene, "%s", scene);
+ if (strcmp(scene, "vouchers") == 0)
+ vouchers_screen(a);
+ else if (strcmp(scene, "inbox") == 0)
+ inbox_screen(a);
+ else if (strcmp(scene, "ib") == 0)
+ ib_screen(a);
+ else if (strcmp(scene, "templates") == 0)
+ templates_screen(a);
+ else if (strcmp(scene, "reports") == 0)
+ reports_screen(a);
+ else if (strcmp(scene, "audit") == 0)
+ audit_screen(a);
+ else if (strcmp(scene, "settings") == 0)
+ settings_screen(a);
+ else if (strcmp(scene, "company") == 0)
+ company_screen(a);
+}
+
+static void do_reload(struct app *a, const char *self)
+{
+ char orgbuf[32], fybuf[32];
+ char *argv[12];
+ int n = 0;
+ snprintf(orgbuf, sizeof orgbuf, "%lld", (long long)a->org);
+ snprintf(fybuf, sizeof fybuf, "%lld", (long long)a->fy);
+ argv[n++] = (char *)(self && *self ? self : "bokftui");
+ argv[n++] = "--org";
+ argv[n++] = orgbuf;
+ if (a->fy > 0) {
+ argv[n++] = "--fy";
+ argv[n++] = fybuf;
+ }
+ argv[n++] = "--screen";
+ argv[n++] = g_reload_scene[0] ? g_reload_scene : g_scene;
+ argv[n] = NULL;
+ setenv("BOKFD_SESSION", a->session, 1);
+ endwin();
+ execvp(argv[0], argv);
+ fprintf(stderr, "bokftui: kunde inte ladda om: %s\n", strerror(errno));
+}
+
static const char *const MAIN_ITEMS[] = {
"Verifikat", "Underlag (inkorg)", "IngÄende balans",
"Mallar", "Rapporter", "Revision",
@@ -3944,6 +4002,7 @@ static void dashboard(struct app *a)
{
for (;;) {
int sel = menu("Bokf", MAIN_ITEMS, 10, 1);
+ snprintf(g_scene, sizeof g_scene, "%s", "dashboard");
if (g_quit)
return;
if (sel == -4) {
@@ -3956,28 +4015,28 @@ static void dashboard(struct app *a)
continue; /* Esc/back at the top level never exits */
switch (sel) {
case 0:
- vouchers_screen(a);
+ open_scene(a, "vouchers");
break;
case 1:
- inbox_screen(a);
+ open_scene(a, "inbox");
break;
case 2:
- ib_screen(a);
+ open_scene(a, "ib");
break;
case 3:
- templates_screen(a);
+ open_scene(a, "templates");
break;
case 4:
- reports_screen(a);
+ open_scene(a, "reports");
break;
case 5:
- audit_screen(a);
+ open_scene(a, "audit");
break;
case 6:
- settings_screen(a);
+ open_scene(a, "settings");
break;
case 7:
- company_screen(a);
+ open_scene(a, "company");
break;
case 8:
select_fiscal_year(a);
@@ -4274,6 +4333,10 @@ static void usage(FILE *f)
" --socket TARGET unix path, tcp:host:port or tls:host:port\n"
" --user NAME prefill username\n"
" --org ID select org directly\n"
+ " --fy ID select fiscal year directly\n"
+ " --session ID reuse an open session (or BOKFD_SESSION)\n"
+ " --screen NAME start in a view: dashboard, vouchers, inbox,\n"
+ " ib, templates, reports, audit, settings, company\n"
" --version\n");
}
@@ -4282,13 +4345,21 @@ int main(int argc, char **argv)
struct app app;
memset(&app, 0, sizeof app);
app.conn.fd = -1;
- const char *cli_socket = NULL, *cli_user = NULL;
- int64_t want_org = 0;
+ const char *self = argc > 0 ? argv[0] : "bokftui";
+ const char *cli_socket = NULL, *cli_user = NULL, *cli_session = NULL;
+ const char *screen_arg = NULL;
+ int64_t want_org = 0, want_fy = 0;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--socket") == 0 && i + 1 < argc)
cli_socket = argv[++i];
else if (strcmp(argv[i], "--user") == 0 && i + 1 < argc)
cli_user = argv[++i];
+ else if (strcmp(argv[i], "--session") == 0 && i + 1 < argc)
+ cli_session = argv[++i];
+ else if (strcmp(argv[i], "--screen") == 0 && i + 1 < argc)
+ screen_arg = argv[++i];
+ else if (strcmp(argv[i], "--fy") == 0 && i + 1 < argc)
+ want_fy = strtoll(argv[++i], NULL, 10);
else if (strcmp(argv[i], "--org") == 0 && i + 1 < argc) {
want_org = strtoll(argv[++i], NULL, 10);
} else if (strcmp(argv[i], "--version") == 0) {
@@ -4325,8 +4396,21 @@ int main(int argc, char **argv)
keypad(stdscr, TRUE);
curs_set(1);
+ const char *env_session = getenv("BOKFD_SESSION");
+ const char *session_arg = cli_session ? cli_session : env_session;
+ if (session_arg && *session_arg &&
+ client_connect(app.socket, &app.conn) == 0) {
+ char *resp =
+ client_rpc(&app.conn, "session.whoami", session_arg, 0, NULL);
+ if (resp && client_ok(resp))
+ snprintf(app.session, sizeof app.session, "%s", session_arg);
+ else
+ client_close(&app.conn);
+ free(resp);
+ }
+
const char *token = getenv("BOKFD_TOKEN");
- if (token && *token) {
+ if (!app.session[0] && token && *token) {
char *err = NULL;
if (try_login(&app, NULL, NULL, token, &err) == 0) {
config_save(&app);
@@ -4348,9 +4432,35 @@ int main(int argc, char **argv)
return 0;
}
app_refresh_context(&app);
+ if (want_fy > 0) {
+ char args[64];
+ snprintf(args, sizeof args, "{\"id\":%lld}", (long long)want_fy);
+ char *resp = client_rpc(&app.conn, "fiscal_year.get", app.session,
+ app.org, args);
+ if (resp && client_ok(resp)) {
+ app.fy = want_fy;
+ char *label = jstr_dup(resp, "result.label");
+ char *start = jstr_dup(resp, "result.start_date");
+ char *end = jstr_dup(resp, "result.end_date");
+ if (label)
+ snprintf(app.fy_label, sizeof app.fy_label, "%s", label);
+ if (start)
+ snprintf(app.fy_start, sizeof app.fy_start, "%s", start);
+ if (end)
+ snprintf(app.fy_end, sizeof app.fy_end, "%s", end);
+ free(label);
+ free(start);
+ free(end);
+ }
+ free(resp);
+ }
update_status(&app);
+ if (screen_arg && *screen_arg && strcmp(screen_arg, "dashboard") != 0)
+ open_scene(&app, screen_arg);
dashboard(&app);
+ if (g_reload)
+ do_reload(&app, self);
client_rpc(&app.conn, "session.close", app.session, 0, "{}");
acct_cache_free();
client_close(&app.conn);