mirror of
https://github.com/michaeldv/pit.git
synced 2025-12-09 16:05:35 +00:00
More work with notes; refactored actions; added tests
This commit is contained in:
21
src/action.c
21
src/action.c
@@ -5,11 +5,9 @@
|
||||
|
||||
static void action_list()
|
||||
{
|
||||
PPager ppager;
|
||||
|
||||
pit_db_load();
|
||||
if (actions->number_of_records > 0) {
|
||||
ppager = pit_pager_initialize(PAGER_ACTION, 0, actions->number_of_records);
|
||||
PPager ppager = pit_pager_initialize(PAGER_ACTION, 0, actions->number_of_records);
|
||||
for_each_action(pa) {
|
||||
pit_pager_print(ppager, (char *)pa);
|
||||
}
|
||||
@@ -17,17 +15,14 @@ static void action_list()
|
||||
}
|
||||
}
|
||||
|
||||
void pit_action(int id, char *subject, char *message)
|
||||
void pit_action(PAction pa)
|
||||
{
|
||||
static Action action = { 0 };
|
||||
|
||||
action.subject_id = id;
|
||||
strncpy(action.subject, subject, sizeof(action.subject) - 1);
|
||||
strncpy(action.username, current_user(), sizeof(action.username) - 1);
|
||||
strncpy(action.message, message, sizeof(action.message) - 1);
|
||||
|
||||
pit_table_insert(actions, (char *)&action);
|
||||
if (strcmp(subject, "pit")) puts(message);
|
||||
if (pa) {
|
||||
strncpy(pa->username, current_user(), sizeof(pa->username) - 1);
|
||||
pit_table_insert(actions, (char *)pa);
|
||||
if (pa->project_id || pa->task_id || pa->note_id)
|
||||
puts(pa->message);
|
||||
}
|
||||
}
|
||||
|
||||
void pit_log(char *argv[])
|
||||
|
||||
6
src/db.c
6
src/db.c
@@ -110,13 +110,15 @@ void pit_db_load() {
|
||||
}
|
||||
|
||||
void pit_db_initialize() {
|
||||
Action a = { 0 };
|
||||
|
||||
projects = pit_table_initialize(sizeof(Project), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS);
|
||||
tasks = pit_table_initialize(sizeof(Task), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS);
|
||||
notes = pit_table_initialize(sizeof(Note), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS);
|
||||
actions = pit_table_initialize(sizeof(Action), TABLE_HAS_CREATED_AT);
|
||||
|
||||
pit_action(0, "pit", "Initialized pit");
|
||||
|
||||
strcpy(a.message, "Initialized pit");
|
||||
pit_action(&a);
|
||||
pit_db_save();
|
||||
}
|
||||
|
||||
|
||||
230
src/note.c
230
src/note.c
@@ -3,85 +3,40 @@
|
||||
#include <stdio.h>
|
||||
#include "pit.h"
|
||||
|
||||
/*
|
||||
** CREATING NOTES:
|
||||
** pit note -c message
|
||||
**
|
||||
** EDITING NOTES:
|
||||
** pit note -e [number] message
|
||||
**
|
||||
** DELETING NOTES:
|
||||
** pit note -d [number]
|
||||
**
|
||||
** LISTING NOTES:
|
||||
** pit note
|
||||
*/
|
||||
|
||||
static int note_find_current(int id, PProject *ppp)
|
||||
static int note_find_current(int id, PNote *ppn)
|
||||
{
|
||||
// if (id) {
|
||||
// *ppp = (PProject)pit_table_find(notes, id);
|
||||
// if (!*ppp) die("could not find note %d", id);
|
||||
// } else {
|
||||
// *ppp = (PProject)pit_table_current(notes);
|
||||
// if (!*ppp) die("could not find current note");
|
||||
// }
|
||||
// return *ppp ? (*(PProject *)ppp)->id : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void note_log_create(PNote pn, POptions po)
|
||||
{
|
||||
char str[256];
|
||||
|
||||
sprintf(str, "created note %d: %s (task %d)", pn->id, po->note.message, pn->task_id);
|
||||
pit_action(pn->id, "note", str);
|
||||
}
|
||||
|
||||
static void note_log_update(PNote pn, POptions po)
|
||||
{
|
||||
// char str[256];
|
||||
// bool empty = TRUE;
|
||||
//
|
||||
// sprintf(str, "updated note %d:", pn->id);
|
||||
// if (po->note.name) {
|
||||
// sprintf(str + strlen(str), " (name: %s", po->note.name);
|
||||
// empty = FALSE;
|
||||
// } else {
|
||||
// sprintf(str + strlen(str), " %s (", pn->name);
|
||||
// }
|
||||
// if (po->note.status) {
|
||||
// sprintf(str + strlen(str), "%sstatus: %s)", (empty ? "" : ", "), po->note.status);
|
||||
// }
|
||||
// strcat(str, ")");
|
||||
// pit_action(pn->id, "note", str);
|
||||
}
|
||||
|
||||
static void note_log_delete(int id, char *name, int number_of_tasks)
|
||||
{
|
||||
// char str[256];
|
||||
//
|
||||
// sprintf(str, "deleted note %d: %s", id, name);
|
||||
// if (number_of_tasks > 0) {
|
||||
// sprintf(str + strlen(str), " with %d task%s", number_of_tasks, (number_of_tasks == 1 ? "" : "s"));
|
||||
// }
|
||||
// pit_action(id, "note", str);
|
||||
}
|
||||
|
||||
void pit_note_list(PTask pt)
|
||||
{
|
||||
if (!notes) pit_db_load();
|
||||
|
||||
if (notes->number_of_records > 0) {
|
||||
PPager ppager = pit_pager_initialize(PAGER_NOTE, pt ? 4 : 0, notes->number_of_records);
|
||||
if (!pt) pt = (PTask)pit_table_current(tasks);
|
||||
for_each_note(pn) {
|
||||
if (pt && pn->task_id != pt->id)
|
||||
continue;
|
||||
pit_pager_print(ppager, (char *)pn);
|
||||
}
|
||||
pit_pager_flush(ppager);
|
||||
if (id) {
|
||||
*ppn = (PNote)pit_table_find(notes, id);
|
||||
if (!*ppn) die("could not find note %d", id);
|
||||
} else {
|
||||
*ppn = (PNote)pit_table_current(notes);
|
||||
if (!*ppn) die("could not find current note");
|
||||
}
|
||||
return *ppn ? (*(PNote *)ppn)->id : 0;
|
||||
}
|
||||
|
||||
static void note_log_create(PTask pt, PNote pn, POptions po)
|
||||
{
|
||||
Action a = { pt->project_id, pt->id, pn->id, { 0 } };
|
||||
|
||||
sprintf(a.message, "created note %d: %s (task %d)", pn->id, po->note.message, pn->task_id);
|
||||
pit_action(&a);
|
||||
}
|
||||
|
||||
static void note_log_update(PTask pt, PNote pn, POptions po)
|
||||
{
|
||||
Action a = { pt->project_id, pt->id, pn->id, { 0 } };
|
||||
|
||||
sprintf(a.message, "updated note %d: (message: %s, task %d)", pn->id, pn->message, pn->task_id);
|
||||
pit_action(&a);
|
||||
}
|
||||
|
||||
static void note_log_delete(int project_id, int task_id, int id, char *message)
|
||||
{
|
||||
Action a = { project_id, task_id, id, { 0 } };
|
||||
|
||||
sprintf(a.message, "deleted note %d: %s (task %d)", id, message, task_id);
|
||||
pit_action(&a);
|
||||
}
|
||||
|
||||
static void note_create(POptions po)
|
||||
@@ -101,62 +56,89 @@ static void note_create(POptions po)
|
||||
pn = (PNote)pit_table_insert(notes, (char *)&n);
|
||||
pit_table_mark(notes, pn->id);
|
||||
pt->number_of_notes++;
|
||||
note_log_create(pn, po);
|
||||
note_log_create(pt, pn, po);
|
||||
pit_db_save();
|
||||
}
|
||||
}
|
||||
|
||||
static void note_update(int id, POptions po)
|
||||
{
|
||||
puts("note_update");
|
||||
// PProject pp;
|
||||
//
|
||||
// pit_db_load();
|
||||
// id = note_find_current(id, &pp);
|
||||
//
|
||||
// if (po->note.name) strncpy(pp->name, po->note.name, sizeof(pp->name) - 1);
|
||||
// if (po->note.status) strncpy(pp->status, po->note.status, sizeof(pp->status) - 1);
|
||||
// pit_table_mark(notes, pp->id);
|
||||
//
|
||||
// note_log_update(pp, po);
|
||||
// pit_db_save();
|
||||
PNote pn;
|
||||
|
||||
pit_db_load();
|
||||
id = note_find_current(id, &pn);
|
||||
|
||||
strncpy(pn->message, po->note.message, sizeof(pn->message) - 1);
|
||||
strncpy(pn->username, current_user(), sizeof(pn->username) - 1);
|
||||
pit_table_mark(notes, pn->id);
|
||||
|
||||
note_log_update((PTask)pit_table_find(tasks, pn->task_id), pn, po);
|
||||
pit_db_save();
|
||||
}
|
||||
|
||||
/*
|
||||
** A note could be deleted as standalone entity or as part of cascading task
|
||||
** or project delete.
|
||||
*/
|
||||
void pit_note_delete(int id, PTask pt)
|
||||
{
|
||||
puts("note_delete");
|
||||
// PProject pp;
|
||||
//
|
||||
// pit_db_load();
|
||||
// id = note_find_current(id, &pp);
|
||||
// /*
|
||||
// ** Delete note tasks.
|
||||
// */
|
||||
// if (pp->number_of_tasks > 0) {
|
||||
// for_each_task(pt) {
|
||||
// if (pt->note_id == id) {
|
||||
// pit_task_delete(pt->id, pp);
|
||||
// --pt; /* Make the task pointer stay since it now points to the next task. */
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// /*
|
||||
// ** Ready to delete the note itself. But first preserve the
|
||||
// ** name and number of tasks since we need these bits for logging.
|
||||
// */
|
||||
// char *deleted_name = str2str(pp->name);
|
||||
// int deleted_number_of_tasks = pp->number_of_tasks;
|
||||
//
|
||||
// pp = (PProject)pit_table_delete(notes, id);
|
||||
// if (pp) {
|
||||
// pit_table_mark(notes, 0); /* TODO: find better current note candidate. */
|
||||
// note_log_delete(id, deleted_name, deleted_number_of_tasks);
|
||||
// pit_db_save();
|
||||
// } else {
|
||||
// die("could not delete the note");
|
||||
// }
|
||||
PNote pn;
|
||||
bool standalone = (pt == NULL);
|
||||
|
||||
if (standalone) pit_db_load();
|
||||
id = note_find_current(id, &pn);
|
||||
if (standalone) pt = (PTask)pit_table_find(tasks, pn->task_id);
|
||||
|
||||
if (pt) {
|
||||
char *deleted_message = str2str(pn->message);
|
||||
|
||||
pn = (PNote)pit_table_delete(notes, id);
|
||||
if (pn) {
|
||||
pit_table_mark(notes, 0); /* TODO: find better current note candidate. */
|
||||
note_log_delete(pt->project_id, pt->id, id, deleted_message);
|
||||
if (standalone) {
|
||||
pt->number_of_notes--;
|
||||
pit_db_save();
|
||||
}
|
||||
free(deleted_message);
|
||||
} else {
|
||||
free(deleted_message);
|
||||
die("could not delete note %d", id);
|
||||
}
|
||||
} else {
|
||||
die("could not find task for note %d", id);
|
||||
}
|
||||
}
|
||||
|
||||
void pit_note_list(PTask pt)
|
||||
{
|
||||
if (!notes) pit_db_load();
|
||||
|
||||
if (notes->number_of_records > 0) {
|
||||
PPager ppager = pit_pager_initialize(PAGER_NOTE, pt ? 4 : 0, notes->number_of_records);
|
||||
if (!pt) pt = (PTask)pit_table_current(tasks);
|
||||
for_each_note(pn) {
|
||||
if (pt && pn->task_id != pt->id)
|
||||
continue;
|
||||
pit_pager_print(ppager, (char *)pn);
|
||||
}
|
||||
pit_pager_flush(ppager);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** CREATING NOTES:
|
||||
** pit note -c message
|
||||
**
|
||||
** EDITING NOTES:
|
||||
** pit note -e [number] message
|
||||
**
|
||||
** DELETING NOTES:
|
||||
** pit note -d [number]
|
||||
**
|
||||
** LISTING NOTES:
|
||||
** pit note
|
||||
*/
|
||||
void pit_note(char *argv[])
|
||||
{
|
||||
char **arg = &argv[1];
|
||||
@@ -175,11 +157,7 @@ void pit_note(char *argv[])
|
||||
number = pit_arg_number(++arg, NULL);
|
||||
if (!number) --arg;
|
||||
opt.note.message = pit_arg_string(++arg, "note message");
|
||||
if (is_zero((char *)&opt.note, sizeof(opt.note))) {
|
||||
die("nothing to update");
|
||||
} else {
|
||||
note_update(number, &opt);
|
||||
}
|
||||
note_update(number, &opt);
|
||||
break;
|
||||
case 'd': /* pit note -d [number] */
|
||||
number = pit_arg_number(++arg, NULL);
|
||||
|
||||
@@ -44,8 +44,9 @@ typedef struct _Note {
|
||||
} Note, *PNote;
|
||||
|
||||
typedef struct _Action {
|
||||
int subject_id; /* Reference to the specific Project, Task, or Note. */
|
||||
char subject[16]; /* Project, Task, or Note. */
|
||||
int project_id; /* Project id (always set). */
|
||||
int task_id; /* Task id (set for task or note related actions). */
|
||||
int note_id; /* Note id (set for note related actions only). */
|
||||
char username[32]; /* Who added the log message? */
|
||||
char message[255]; /* Log message. */
|
||||
time_t created_at; /* When log message was added? */
|
||||
|
||||
33
src/pager.c
33
src/pager.c
@@ -36,7 +36,7 @@ static void print_projects(PPager ppager)
|
||||
char **pentry;
|
||||
char format[64];
|
||||
|
||||
sprintf(format, "%%c %%%dd: (%%-%ds) [%%-%ds] %%-%ds (%%d task%%s)\n",
|
||||
sprintf(format, "%%c %%%dd: (%%-%ds) |%%-%ds| %%-%ds (%%d task%%s)\n",
|
||||
ppager->max.project.id, ppager->max.project.username, ppager->max.project.status, ppager->max.project.name
|
||||
);
|
||||
for_each_entry(ppager, pentry) {
|
||||
@@ -79,7 +79,7 @@ static void print_tasks_with_date(PPager ppager)
|
||||
char **pentry;
|
||||
char format[64];
|
||||
|
||||
sprintf(format, "%%%dc %%%dd: (%%-%ds) [%%-%ds] [%%-%ds] %%-%ds %%-%ds (%%d note%%s)\n",
|
||||
sprintf(format, "%%%dc %%%dd: (%%-%ds) |%%-%ds| |%%-%ds| %%-%ds %%-%ds (%%d note%%s)\n",
|
||||
ppager->indent, ppager->max.task.id, ppager->max.task.username, ppager->max.task.status, ppager->max.task.priority, ppager->max.task.date, ppager->max.task.name
|
||||
);
|
||||
for_each_entry(ppager, pentry) {
|
||||
@@ -102,7 +102,7 @@ static void print_tasks_with_time(PPager ppager)
|
||||
char **pentry;
|
||||
char format[64];
|
||||
|
||||
sprintf(format, "%%%dc %%%dd: (%%-%ds) [%%-%ds] [%%-%ds] %%%ds %%-%ds (%%d note%%s)\n",
|
||||
sprintf(format, "%%%dc %%%dd: (%%-%ds) |%%-%ds| |%%-%ds| %%%ds %%-%ds (%%d note%%s)\n",
|
||||
ppager->indent, ppager->max.task.id, ppager->max.task.username, ppager->max.task.status, ppager->max.task.priority, ppager->max.task.time, ppager->max.task.name
|
||||
);
|
||||
for_each_entry(ppager, pentry) {
|
||||
@@ -125,7 +125,7 @@ static void print_tasks_with_date_and_time(PPager ppager)
|
||||
char **pentry;
|
||||
char format[64];
|
||||
|
||||
sprintf(format, "%%%dc %%%dd: (%%-%ds) [%%-%ds] [%%-%ds] %%-%ds %%%ds %%-%ds (%%d note%%s)\n",
|
||||
sprintf(format, "%%%dc %%%dd: (%%-%ds) |%%-%ds| |%%-%ds| %%-%ds %%%ds %%-%ds (%%d note%%s)\n",
|
||||
ppager->indent, ppager->max.task.id, ppager->max.task.username, ppager->max.task.status, ppager->max.task.priority, ppager->max.task.date, ppager->max.task.time, ppager->max.task.name
|
||||
);
|
||||
for_each_entry(ppager, pentry) {
|
||||
@@ -165,6 +165,13 @@ void pit_pager_print(PPager ppager, char *entry)
|
||||
|
||||
for_each_entry(ppager, pentry) {
|
||||
switch(ppager->type) {
|
||||
case PAGER_PROJECT:
|
||||
sprintf(str, "%d", PROJECT(id));
|
||||
ppager->max.project.id = max(ppager->max.project.id, strlen(str));
|
||||
ppager->max.project.username = max(ppager->max.project.username, strlen(PROJECT(username)));
|
||||
ppager->max.project.name = max(ppager->max.project.name, strlen(PROJECT(name)));
|
||||
ppager->max.project.status = max(ppager->max.project.status, strlen(PROJECT(status)));
|
||||
break;
|
||||
case PAGER_TASK:
|
||||
sprintf(str, "%d", TASK(id));
|
||||
ppager->max.task.id = max(ppager->max.task.id, strlen(str));
|
||||
@@ -179,21 +186,14 @@ void pit_pager_print(PPager ppager, char *entry)
|
||||
ppager->max.task.time = max(ppager->max.task.time, strlen(format_time(TASK(time))));
|
||||
}
|
||||
break;
|
||||
case PAGER_PROJECT:
|
||||
sprintf(str, "%d", ((PProject)*pentry)->id);
|
||||
ppager->max.project.id = max(ppager->max.project.id, strlen(str));
|
||||
ppager->max.project.username = max(ppager->max.project.username, strlen(((PProject)*pentry)->username));
|
||||
ppager->max.project.name = max(ppager->max.project.name, strlen(((PProject)*pentry)->name));
|
||||
ppager->max.project.status = max(ppager->max.project.status, strlen(((PProject)*pentry)->status));
|
||||
break;
|
||||
case PAGER_ACTION:
|
||||
ppager->max.action.username = max(ppager->max.action.username, strlen(((PAction)*pentry)->username));
|
||||
ppager->max.action.subject = max(ppager->max.action.subject, strlen(((PAction)*pentry)->subject));
|
||||
break;
|
||||
case PAGER_NOTE:
|
||||
sprintf(str, "%d", NOTE(id));
|
||||
ppager->max.note.id = max(ppager->max.note.id, strlen(str));
|
||||
ppager->max.note.username = max(ppager->max.note.username, strlen(((PNote)*pentry)->username));
|
||||
ppager->max.note.username = max(ppager->max.note.username, strlen(NOTE(username)));
|
||||
break;
|
||||
case PAGER_ACTION:
|
||||
ppager->max.action.username = max(ppager->max.action.username, strlen(ACTION(username)));
|
||||
ppager->max.action.message = max(ppager->max.action.message, strlen(ACTION(message)));
|
||||
break;
|
||||
default:
|
||||
die("invalid pager type: %d\n", ppager->type);
|
||||
@@ -246,3 +246,4 @@ void pit_pager_free(PPager ppager)
|
||||
#undef TASK
|
||||
#undef PROJECT
|
||||
#undef ACTION
|
||||
#undef NOTE
|
||||
|
||||
@@ -29,7 +29,7 @@ typedef struct _Pager {
|
||||
} task;
|
||||
struct {
|
||||
int username;
|
||||
int subject;
|
||||
int message;
|
||||
} action;
|
||||
struct {
|
||||
int id;
|
||||
|
||||
@@ -54,7 +54,7 @@ void pit_version();
|
||||
void pit_db_load();
|
||||
void pit_db_save();
|
||||
void pit_db_initialize();
|
||||
void pit_action(int id, char *subject, char *message);
|
||||
void pit_action(PAction pa);
|
||||
void pit_task_list(POptions po, PProject pp);
|
||||
void pit_task_delete(int id, PProject pp);
|
||||
void pit_note_list(PTask pt);
|
||||
|
||||
@@ -3,23 +3,6 @@
|
||||
#include <stdio.h>
|
||||
#include "pit.h"
|
||||
|
||||
/*
|
||||
** CREATING PROJECTS:
|
||||
** pit project -c name [-s status]
|
||||
**
|
||||
** EDITING PROJECTS:
|
||||
** pit project -e [number] [-n name] [-s status]
|
||||
**
|
||||
** DELETING PROJECTS:
|
||||
** pit project -d [number]
|
||||
**
|
||||
** VIEWING PROJECT:
|
||||
** pit project [[-q] number]
|
||||
**
|
||||
** LISTING PROJECTS:
|
||||
** pit project -q [number | [-n name] [-s status]]
|
||||
*/
|
||||
|
||||
static bool project_already_exist(char *name)
|
||||
{
|
||||
pit_db_load();
|
||||
@@ -45,40 +28,40 @@ static int project_find_current(int id, PProject *ppp)
|
||||
|
||||
static void project_log_create(PProject pp, POptions po)
|
||||
{
|
||||
char str[256];
|
||||
Action a = { pp->id, 0 };
|
||||
|
||||
sprintf(str, "created project %d: %s (status: %s)", pp->id, po->project.name, po->project.status);
|
||||
pit_action(pp->id, "project", str);
|
||||
sprintf(a.message, "created project %d: %s (status: %s)", pp->id, po->project.name, po->project.status);
|
||||
pit_action(&a);
|
||||
}
|
||||
|
||||
static void project_log_update(PProject pp, POptions po)
|
||||
{
|
||||
char str[256];
|
||||
Action a = { pp->id, 0 };
|
||||
bool empty = TRUE;
|
||||
|
||||
sprintf(str, "updated project %d:", pp->id);
|
||||
sprintf(a.message, "updated project %d:", pp->id);
|
||||
if (po->project.name) {
|
||||
sprintf(str + strlen(str), " (name: %s", po->project.name);
|
||||
sprintf(a.message + strlen(a.message), " (name: %s", po->project.name);
|
||||
empty = FALSE;
|
||||
} else {
|
||||
sprintf(str + strlen(str), " %s (", pp->name);
|
||||
sprintf(a.message + strlen(a.message), " %s (", pp->name);
|
||||
}
|
||||
if (po->project.status) {
|
||||
sprintf(str + strlen(str), "%sstatus: %s)", (empty ? "" : ", "), po->project.status);
|
||||
sprintf(a.message + strlen(a.message), "%sstatus: %s)", (empty ? "" : ", "), po->project.status);
|
||||
}
|
||||
strcat(str, ")");
|
||||
pit_action(pp->id, "project", str);
|
||||
strcat(a.message, ")");
|
||||
pit_action(&a);
|
||||
}
|
||||
|
||||
static void project_log_delete(int id, char *name, int number_of_tasks)
|
||||
{
|
||||
char str[256];
|
||||
Action a = { id, 0 };
|
||||
|
||||
sprintf(str, "deleted project %d: %s", id, name);
|
||||
sprintf(a.message, "deleted project %d: %s", id, name);
|
||||
if (number_of_tasks > 0) {
|
||||
sprintf(str + strlen(str), " with %d task%s", number_of_tasks, (number_of_tasks == 1 ? "" : "s"));
|
||||
sprintf(a.message + strlen(a.message), " with %d task%s", number_of_tasks, (number_of_tasks == 1 ? "" : "s"));
|
||||
}
|
||||
pit_action(id, "project", str);
|
||||
pit_action(&a);
|
||||
}
|
||||
|
||||
static void project_list(POptions po)
|
||||
@@ -147,6 +130,7 @@ static void project_update(int id, POptions po)
|
||||
|
||||
if (po->project.name) strncpy(pp->name, po->project.name, sizeof(pp->name) - 1);
|
||||
if (po->project.status) strncpy(pp->status, po->project.status, sizeof(pp->status) - 1);
|
||||
strncpy(pp->username, current_user(), sizeof(pp->username) - 1);
|
||||
pit_table_mark(projects, pp->id);
|
||||
|
||||
project_log_update(pp, po);
|
||||
@@ -203,6 +187,22 @@ static void project_parse_options(char **arg, POptions po)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** CREATING PROJECTS:
|
||||
** pit project -c name [-s status]
|
||||
**
|
||||
** EDITING PROJECTS:
|
||||
** pit project -e [number] [-n name] [-s status]
|
||||
**
|
||||
** DELETING PROJECTS:
|
||||
** pit project -d [number]
|
||||
**
|
||||
** VIEWING PROJECT:
|
||||
** pit project [[-q] number]
|
||||
**
|
||||
** LISTING PROJECTS:
|
||||
** pit project -q [number | [-n name] [-s status]]
|
||||
*/
|
||||
void pit_project(char *argv[])
|
||||
{
|
||||
char **arg = &argv[1];
|
||||
|
||||
214
src/task.c
214
src/task.c
@@ -3,23 +3,6 @@
|
||||
#include <stdio.h>
|
||||
#include "pit.h"
|
||||
|
||||
/*
|
||||
** CREATING TASKS:
|
||||
** pit task -c name [-s status] [-p priority] [-d date] [-t time]
|
||||
**
|
||||
** EDITING TASKS:
|
||||
** pit task -e [number] [-n name] [-s status] [-p priority] [-d date] [-t time]
|
||||
**
|
||||
** DELETING TASKS:
|
||||
** pit task -d [number]
|
||||
**
|
||||
** VIEWING TASK:
|
||||
** pit task [[-q] number]
|
||||
**
|
||||
** LISTING TASKS:
|
||||
** pit task -q [number | [-n name] [-s status] [-p priority] [-d date] [-t time]]
|
||||
*/
|
||||
|
||||
static int task_find_current(int id, PTask *ppt)
|
||||
{
|
||||
if (id) {
|
||||
@@ -34,81 +17,65 @@ static int task_find_current(int id, PTask *ppt)
|
||||
|
||||
static void task_log_create(PTask pt, POptions po)
|
||||
{
|
||||
char str[256];
|
||||
Action a = { pt->project_id, pt->id, 0 };
|
||||
|
||||
sprintf(str, "created task %d: %s (status: %s, priority: %s", pt->id, po->task.name, po->task.status, po->task.priority);
|
||||
if (po->task.date > 0) sprintf(str + strlen(str), ", date: %s", format_date(po->task.date));
|
||||
if (po->task.time > 0) sprintf(str + strlen(str), ", time: %s", format_time(po->task.time));
|
||||
sprintf(str + strlen(str), ", project: %d)", pt->project_id);
|
||||
pit_action(pt->id, "task", str);
|
||||
sprintf(a.message, "created task %d: %s (status: %s, priority: %s", pt->id, po->task.name, po->task.status, po->task.priority);
|
||||
if (po->task.date > 0) sprintf(a.message + strlen(a.message), ", date: %s", format_date(po->task.date));
|
||||
if (po->task.time > 0) sprintf(a.message + strlen(a.message), ", time: %s", format_time(po->task.time));
|
||||
sprintf(a.message + strlen(a.message), ", project: %d)", pt->project_id);
|
||||
pit_action(&a);
|
||||
}
|
||||
|
||||
static void task_log_update(PTask pt, POptions po)
|
||||
{
|
||||
char str[256];
|
||||
Action a = { pt->project_id, pt->id, 0 };
|
||||
bool empty = TRUE;
|
||||
|
||||
sprintf(str, "updated task %d:", pt->id);
|
||||
sprintf(a.message, "updated task %d:", pt->id);
|
||||
if (po->task.name) {
|
||||
sprintf(str + strlen(str), " (name: %s", po->task.name);
|
||||
sprintf(a.message + strlen(a.message), " (name: %s", po->task.name);
|
||||
empty = FALSE;
|
||||
} else {
|
||||
sprintf(str + strlen(str), " %s (", pt->name);
|
||||
sprintf(a.message + strlen(a.message), " %s (", pt->name);
|
||||
}
|
||||
if (po->task.status) {
|
||||
sprintf(str + strlen(str), "%sstatus: %s", (empty ? "" : ", "), po->task.status);
|
||||
sprintf(a.message + strlen(a.message), "%sstatus: %s", (empty ? "" : ", "), po->task.status);
|
||||
empty = FALSE;
|
||||
}
|
||||
if (po->task.priority) {
|
||||
sprintf(str + strlen(str), "%spriority: %s", (empty ? "" : ", "), po->task.priority);
|
||||
sprintf(a.message + strlen(a.message), "%spriority: %s", (empty ? "" : ", "), po->task.priority);
|
||||
empty = FALSE;
|
||||
}
|
||||
if (po->task.date) {
|
||||
if (po->task.date < 0) {
|
||||
sprintf(str + strlen(str), "%sdate: none", (empty ? "" : ", "));
|
||||
sprintf(a.message + strlen(a.message), "%sdate: none", (empty ? "" : ", "));
|
||||
} else {
|
||||
sprintf(str + strlen(str), "%sdate: %s", (empty ? "" : ", "), format_date(po->task.date));
|
||||
sprintf(a.message + strlen(a.message), "%sdate: %s", (empty ? "" : ", "), format_date(po->task.date));
|
||||
}
|
||||
empty = FALSE;
|
||||
}
|
||||
if (po->task.time) {
|
||||
if (po->task.time < 0) {
|
||||
sprintf(str + strlen(str), "%stime: none", (empty ? "" : ", "));
|
||||
sprintf(a.message + strlen(a.message), "%stime: none", (empty ? "" : ", "));
|
||||
} else {
|
||||
sprintf(str + strlen(str), "%stime: %s", (empty ? "" : ", "), format_time(po->task.time));
|
||||
sprintf(a.message + strlen(a.message), "%stime: %s", (empty ? "" : ", "), format_time(po->task.time));
|
||||
}
|
||||
empty = FALSE;
|
||||
}
|
||||
strcat(str, ")");
|
||||
pit_action(pt->id, "task", str);
|
||||
strcat(a.message, ")");
|
||||
pit_action(&a);
|
||||
}
|
||||
|
||||
static void task_log_delete(int id, char *name, int number_of_notes)
|
||||
static void task_log_delete(int project_id, int id, char *name, int number_of_notes)
|
||||
{
|
||||
char str[256];
|
||||
Action a = { project_id, id, 0 };
|
||||
|
||||
sprintf(str, "deleted task %d: %s", id, name);
|
||||
sprintf(a.message, "deleted task %d: %s", id, name);
|
||||
if (number_of_notes > 0) {
|
||||
sprintf(str + strlen(str), " with %d note%s", number_of_notes, (number_of_notes == 1 ? "" : "s"));
|
||||
}
|
||||
pit_action(id, "task", str);
|
||||
}
|
||||
|
||||
void pit_task_list(POptions po, PProject pp)
|
||||
{
|
||||
if (!tasks) pit_db_load();
|
||||
|
||||
if (tasks->number_of_records > 0) {
|
||||
PPager ppager = pit_pager_initialize(PAGER_TASK, (pp ? 4 : 0), tasks->number_of_records);
|
||||
if (!pp) pp = (PProject)pit_table_current(projects);
|
||||
|
||||
for_each_task(pt) {
|
||||
if (pp && pt->project_id != pp->id)
|
||||
continue;
|
||||
pit_pager_print(ppager, (char *)pt);
|
||||
}
|
||||
pit_pager_flush(ppager);
|
||||
sprintf(a.message + strlen(a.message), " with %d note%s", number_of_notes, (number_of_notes == 1 ? "" : "s"));
|
||||
}
|
||||
sprintf(a.message + strlen(a.message), " (project: %d)", project_id);
|
||||
pit_action(&a);
|
||||
}
|
||||
|
||||
static void task_show(int id)
|
||||
@@ -173,62 +140,13 @@ static void task_update(int id, POptions po)
|
||||
if (po->task.priority) strncpy(pt->priority, po->task.priority, sizeof(pt->priority) - 1);
|
||||
if (po->task.date) pt->date = max(0, po->task.date);
|
||||
if (po->task.time) pt->time = max(0, po->task.time);
|
||||
strncpy(pt->username, current_user(), sizeof(pt->username) - 1);
|
||||
pit_table_mark(tasks, pt->id);
|
||||
|
||||
task_log_update(pt, po);
|
||||
pit_db_save();
|
||||
}
|
||||
|
||||
/*
|
||||
** A task could be deleted as standalone entity or as part of cascading project
|
||||
** delete. In later case we're going to have 'pp' set and the database loaded.
|
||||
*/
|
||||
void pit_task_delete(int id, PProject pp)
|
||||
{
|
||||
PTask pt;
|
||||
bool standalone = (pp == NULL);
|
||||
|
||||
if (standalone) pit_db_load();
|
||||
id = task_find_current(id, &pt);
|
||||
if (standalone) pp = (PProject)pit_table_find(projects, pt->project_id);
|
||||
|
||||
if (pp) {
|
||||
/*
|
||||
** First delete task notes if any.
|
||||
*/
|
||||
if (pt->number_of_notes > 0) {
|
||||
for_each_note(pn) {
|
||||
if (pn->task_id == id) {
|
||||
pit_note_delete(pn->id, pt);
|
||||
--pn; /* Make the note pointer stay since it now points to the next note. */
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
** Preserve task name and number_of_notes before deleting the task since
|
||||
** we need these for logging.
|
||||
*/
|
||||
char *deleted_name = str2str(pt->name);
|
||||
int deleted_number_of_notes = pt->number_of_notes;
|
||||
|
||||
pt = (PTask)pit_table_delete(tasks, id);
|
||||
if (pt) {
|
||||
pit_table_mark(tasks, 0); /* TODO: find better current task candidate. */
|
||||
task_log_delete(id, deleted_name, deleted_number_of_notes);
|
||||
if (standalone) {
|
||||
pp->number_of_tasks--;
|
||||
pit_db_save();
|
||||
}
|
||||
free(deleted_name);
|
||||
} else {
|
||||
free(deleted_name);
|
||||
die("could not delete task %d", id);
|
||||
}
|
||||
} else {
|
||||
die("could not find project for task %d", id);
|
||||
}
|
||||
}
|
||||
|
||||
static void task_parse_options(char **arg, POptions po)
|
||||
{
|
||||
while(*++arg) {
|
||||
@@ -254,6 +172,88 @@ static void task_parse_options(char **arg, POptions po)
|
||||
}
|
||||
}
|
||||
|
||||
void pit_task_list(POptions po, PProject pp)
|
||||
{
|
||||
if (!tasks) pit_db_load();
|
||||
|
||||
if (tasks->number_of_records > 0) {
|
||||
PPager ppager = pit_pager_initialize(PAGER_TASK, (pp ? 4 : 0), tasks->number_of_records);
|
||||
if (!pp) pp = (PProject)pit_table_current(projects);
|
||||
|
||||
for_each_task(pt) {
|
||||
if (pp && pt->project_id != pp->id)
|
||||
continue;
|
||||
pit_pager_print(ppager, (char *)pt);
|
||||
}
|
||||
pit_pager_flush(ppager);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** A task could be deleted as standalone entity or as part of cascading project
|
||||
** delete. In later case we're going to have 'pp' set and the database loaded.
|
||||
*/
|
||||
void pit_task_delete(int id, PProject pp)
|
||||
{
|
||||
PTask pt;
|
||||
bool standalone = (pp == NULL);
|
||||
|
||||
if (standalone) pit_db_load();
|
||||
id = task_find_current(id, &pt);
|
||||
if (standalone) pp = (PProject)pit_table_find(projects, pt->project_id);
|
||||
|
||||
if (pp) {
|
||||
/*
|
||||
** Preserve task name and number_of_notes before deleting the task since
|
||||
** we need these for logging.
|
||||
*/
|
||||
char *deleted_name = str2str(pt->name);
|
||||
int deleted_number_of_notes = pt->number_of_notes;
|
||||
/*
|
||||
** Delete task notes if any.
|
||||
*/
|
||||
if (pt->number_of_notes > 0) {
|
||||
for_each_note(pn) {
|
||||
if (pn->task_id == id) {
|
||||
pit_note_delete(pn->id, pt);
|
||||
--pn; /* Make the note pointer stay since it now points to the next note. */
|
||||
}
|
||||
}
|
||||
}
|
||||
pt = (PTask)pit_table_delete(tasks, id);
|
||||
if (pt) {
|
||||
pit_table_mark(tasks, 0); /* TODO: find better current task candidate. */
|
||||
task_log_delete(pp->id, id, deleted_name, deleted_number_of_notes);
|
||||
if (standalone) {
|
||||
pp->number_of_tasks--;
|
||||
pit_db_save();
|
||||
}
|
||||
free(deleted_name);
|
||||
} else {
|
||||
free(deleted_name);
|
||||
die("could not delete task %d", id);
|
||||
}
|
||||
} else {
|
||||
die("could not find project for task %d", id);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** CREATING TASKS:
|
||||
** pit task -c name [-s status] [-p priority] [-d date] [-t time]
|
||||
**
|
||||
** EDITING TASKS:
|
||||
** pit task -e [number] [-n name] [-s status] [-p priority] [-d date] [-t time]
|
||||
**
|
||||
** DELETING TASKS:
|
||||
** pit task -d [number]
|
||||
**
|
||||
** VIEWING TASK:
|
||||
** pit task [[-q] number]
|
||||
**
|
||||
** LISTING TASKS:
|
||||
** pit task -q [number | [-n name] [-s status] [-p priority] [-d date] [-t time]]
|
||||
*/
|
||||
void pit_task(char *argv[])
|
||||
{
|
||||
int number = 0;
|
||||
|
||||
Reference in New Issue
Block a user