docs: expand Readme and adjust code comments
This commit is contained in:
parent
8588fb9a04
commit
1e0cc319b8
82
README.md
82
README.md
|
@ -99,7 +99,7 @@ To stop time-tracking completely, simply move to the root of all tasks.
|
||||||
+ match by task name prefix: if one or more tasks match, filter / activate (tries case-sensitive then case-insensitive)
|
+ match by task name prefix: if one or more tasks match, filter / activate (tries case-sensitive then case-insensitive)
|
||||||
+ no match: create & activate task
|
+ no match: create & activate task
|
||||||
- `.2` - set view depth to `2`, which can be substituted for any number (how many subtask levels to show, default 1)
|
- `.2` - set view depth to `2`, which can be substituted for any number (how many subtask levels to show, default 1)
|
||||||
- `/[TEXT]` - like `.`, but never creates a task
|
- `/[TEXT]` - like `.`, but never creates a task and filters beyond currently visible tasks
|
||||||
- `||TASK` - create and activate a new task procedure (where subtasks automatically depend on the previously created task)
|
- `||TASK` - create and activate a new task procedure (where subtasks automatically depend on the previously created task)
|
||||||
- `|[TASK]` - (un)mark current task as procedure or create a sibling task depending on the current one and move up
|
- `|[TASK]` - (un)mark current task as procedure or create a sibling task depending on the current one and move up
|
||||||
|
|
||||||
|
@ -109,12 +109,13 @@ Dots and slashes can be repeated to move to parent tasks.
|
||||||
- `::[PROP]` - Sort by property PROP (multiple space-separated values allowed)
|
- `::[PROP]` - Sort by property PROP (multiple space-separated values allowed)
|
||||||
- `([TIME]` - insert timetracking with the specified offset in minutes (empty: list tracked times)
|
- `([TIME]` - insert timetracking with the specified offset in minutes (empty: list tracked times)
|
||||||
- `)[TIME]` - stop timetracking with the specified offset in minutes - convenience helper to move to root (empty: stop now)
|
- `)[TIME]` - stop timetracking with the specified offset in minutes - convenience helper to move to root (empty: stop now)
|
||||||
- `>[TEXT]` - complete active task and move up, with optional state description
|
- `>[TEXT]` - complete active task and move up, with optional status description
|
||||||
- `<[TEXT]` - close active task and move up, with optional state description
|
- `<[TEXT]` - close active task and move up, with optional status description
|
||||||
- `!TEXT` - set state for current task from text and move up
|
- `!TEXT` - set status for current task from text and move up (empty to open)
|
||||||
- `,TEXT` - add text note (comment / description)
|
- `,TEXT` - add text note (comment / description)
|
||||||
- TBI: `*[INT]` - set priority - can also be used in task, with any digit
|
- TBI: `*[INT]` - set priority - can also be used in task creation, with any digit
|
||||||
- `@` - undoes last action (moving in place or upwards or waiting a minute confirms pending actions)
|
- TBI: status history and creation with attribution
|
||||||
|
- `&` - undo last action (moving in place or upwards confirms pending actions)
|
||||||
- `wss://...` - switch or subscribe to relay (prefix with space to forcibly add a new one)
|
- `wss://...` - switch or subscribe to relay (prefix with space to forcibly add a new one)
|
||||||
|
|
||||||
Property Filters:
|
Property Filters:
|
||||||
|
@ -123,6 +124,8 @@ Property Filters:
|
||||||
- `+TAG` - add tag filter
|
- `+TAG` - add tag filter
|
||||||
- `-TAG` - remove tag filters
|
- `-TAG` - remove tag filters
|
||||||
- `?STATUS` - filter by status (type or description) - plain `?` to reset, `??` to show all
|
- `?STATUS` - filter by status (type or description) - plain `?` to reset, `??` to show all
|
||||||
|
- `@AUTHOR` - filter by author (`@` for self, id prefix, name prefix)
|
||||||
|
- TBI: Filter by time
|
||||||
|
|
||||||
Status descriptions can be used for example for Kanban columns or review flows.
|
Status descriptions can be used for example for Kanban columns or review flows.
|
||||||
An active tag or status filter will also set that attribute for newly created tasks.
|
An active tag or status filter will also set that attribute for newly created tasks.
|
||||||
|
@ -148,6 +151,11 @@ An active tag or status filter will also set that attribute for newly created ta
|
||||||
|
|
||||||
For debugging: `props`, `alltags`, `descriptions`
|
For debugging: `props`, `alltags`, `descriptions`
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
- TBI = To Be Implemented
|
||||||
|
- `. TASK` - create and enter a new task even if the name matches an existing one
|
||||||
|
|
||||||
## Nostr reference
|
## Nostr reference
|
||||||
|
|
||||||
Mostr mainly uses the following NIPs:
|
Mostr mainly uses the following NIPs:
|
||||||
|
@ -164,17 +172,26 @@ Considering to use Calendar: https://github.com/nostr-protocol/nips/blob/master/
|
||||||
|
|
||||||
## Plans
|
## Plans
|
||||||
|
|
||||||
- Remove state filter when moving up?
|
- Local Database Cache, Negentropy Reconciliation
|
||||||
|
-> Offline Use!
|
||||||
|
- Scheduling
|
||||||
|
- Remove status filter when moving up?
|
||||||
- Task markdown support? - colored
|
- Task markdown support? - colored
|
||||||
- Time tracking: Ability to postpone task and add planned timestamps (calendar entry)
|
- Time tracking: Ability to postpone task and add planned timestamps (calendar entry)
|
||||||
- Parse Hashtag tags from task name
|
- Parse Hashtag tags from task name
|
||||||
- Unified Filter object
|
- Unified Filter object
|
||||||
-> include subtasks of matched tasks
|
-> include subtasks of matched tasks
|
||||||
- Relay Switching
|
|
||||||
- Speedup: Offline caching & Expiry (no need to fetch potential years of history)
|
- Speedup: Offline caching & Expiry (no need to fetch potential years of history)
|
||||||
+ Fetch most recent tasks first
|
+ Fetch most recent tasks first
|
||||||
+ Relay: compress tracked time for old tasks, filter closed tasks
|
+ Relay: compress tracked time for old tasks, filter closed tasks
|
||||||
+ Relay: filter out task state updates within few seconds, also on client side
|
+ Relay: filter out task status updates within few seconds, also on client side
|
||||||
|
|
||||||
|
### Command
|
||||||
|
|
||||||
|
- Open Command characters: `_^\=$%~'"`, `{}[]`
|
||||||
|
- Remove colon from task creation syntax
|
||||||
|
- reassign undo to `&` and use `@` for people
|
||||||
|
- maybe use `;` for sorting instead of `::`
|
||||||
|
|
||||||
### Conceptual
|
### Conceptual
|
||||||
|
|
||||||
|
@ -182,9 +199,10 @@ The following features are not ready to be implemented
|
||||||
because they need conceptualization.
|
because they need conceptualization.
|
||||||
Suggestions welcome!
|
Suggestions welcome!
|
||||||
|
|
||||||
|
- Special commands: help, exit, tutorial, change log level
|
||||||
|
- Duplicate task (subtasks? timetracking?)
|
||||||
- What if I want to postpone a procedure, i.e. make it pending, or move it across kanban, does this make sense?
|
- What if I want to postpone a procedure, i.e. make it pending, or move it across kanban, does this make sense?
|
||||||
- Priorities
|
- Dependencies (change from tags to properties so they can be added later? or maybe as a status?)
|
||||||
- Dependencies (change from tags to properties so they can be added later? or maybe as a state?)
|
|
||||||
- Templates
|
- Templates
|
||||||
- Ownership
|
- Ownership
|
||||||
- Combined formatting and recursion specifiers
|
- Combined formatting and recursion specifiers
|
||||||
|
@ -194,11 +212,45 @@ Suggestions welcome!
|
||||||
|
|
||||||
### Interfaces
|
### Interfaces
|
||||||
|
|
||||||
- TUI: Clear terminal? Refresh on empty prompt after timeout?
|
- TUI: Clear Terminal? Refresh on empty prompt after timeout?
|
||||||
- Kanban, GANTT, Calendar
|
- Kanban, GANTT, Calendar
|
||||||
- Web Interface, Messenger integrations
|
- Web Interface, Messenger integrations
|
||||||
|
|
||||||
## Notes
|
## Exemplary Workflows
|
||||||
|
|
||||||
- TBI = To Be Implemented
|
- Freelancer
|
||||||
- `. TASK` - create and enter a new task even if the name matches an existing one
|
- Family Chore management
|
||||||
|
- Inter-Disciplinary Project Team -> Company with multiple projects and multiple relays
|
||||||
|
+ Permissions via status or assignment (reassignment?)
|
||||||
|
+ Tasks can be blocked while having a status (e.g. kanban column)
|
||||||
|
+ A meeting can be worked on (tracked) before it starts
|
||||||
|
+ Schedule for multiple people
|
||||||
|
- Tracking Daily Routines / Habits
|
||||||
|
|
||||||
|
### Contexts
|
||||||
|
|
||||||
|
A context is a custom set of filters such as status, tags, assignee
|
||||||
|
so that the visible tasks are always relevant
|
||||||
|
and newly created tasks are less of a hassle to type out
|
||||||
|
since they will automatically take on that context.
|
||||||
|
By automating these contexts based on triggers, scripts or time,
|
||||||
|
relevant tasks can be surfaced automatically.
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
In the morning, your groggy brain is good at divergent thinking,
|
||||||
|
and you like to do sports in the morning.
|
||||||
|
So for that time, mostr can show you tasks tagged for divergent thinking,
|
||||||
|
since you are easily distracted filter out those that require the internet,
|
||||||
|
as well as anything sportsy.
|
||||||
|
After you come back from sports and had breakfast,
|
||||||
|
for example detected through a period of inactivity on your device,
|
||||||
|
you are ready for work, so the different work projects are shown and you delve into one.
|
||||||
|
After 90 minutes you reach a natural low in your focus,
|
||||||
|
so mostr surfaces break activities -
|
||||||
|
such as a short walk, a small workout, some instrument practice
|
||||||
|
or simply grabbing a snack and drink.
|
||||||
|
After lunch you like to take an extended afternoon break,
|
||||||
|
so your call list pops up -
|
||||||
|
you can give a few people a call as you make a market run,
|
||||||
|
before going for siesta.
|
||||||
|
|
|
@ -7,6 +7,7 @@ pub fn some_non_empty(str: &str) -> Option<String> {
|
||||||
if str.is_empty() { None } else { Some(str.to_string()) }
|
if str.is_empty() { None } else { Some(str.to_string()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO as macro so that log comes from appropriate module
|
||||||
pub fn or_print<T, U: Display>(result: Result<T, U>) -> Option<T> {
|
pub fn or_print<T, U: Display>(result: Result<T, U>) -> Option<T> {
|
||||||
match result {
|
match result {
|
||||||
Ok(value) => Some(value),
|
Ok(value) => Some(value),
|
||||||
|
|
|
@ -400,7 +400,7 @@ async fn main() {
|
||||||
tasks.move_up();
|
tasks.move_up();
|
||||||
}
|
}
|
||||||
|
|
||||||
Some('@') => {
|
Some('@') | Some('&') => {
|
||||||
tasks.undo();
|
tasks.undo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
17
src/tasks.rs
17
src/tasks.rs
|
@ -28,6 +28,7 @@ pub(crate) struct Tasks {
|
||||||
tasks: TaskMap,
|
tasks: TaskMap,
|
||||||
/// History of active tasks by PubKey
|
/// History of active tasks by PubKey
|
||||||
history: HashMap<PublicKey, BTreeSet<Event>>,
|
history: HashMap<PublicKey, BTreeSet<Event>>,
|
||||||
|
|
||||||
/// The task properties currently visible
|
/// The task properties currently visible
|
||||||
properties: Vec<String>,
|
properties: Vec<String>,
|
||||||
/// The task properties sorted by
|
/// The task properties sorted by
|
||||||
|
@ -349,9 +350,10 @@ impl Tasks {
|
||||||
}
|
}
|
||||||
let res: Vec<&Task> = self.resolve_tasks(self.view.iter());
|
let res: Vec<&Task> = self.resolve_tasks(self.view.iter());
|
||||||
if res.len() > 0 {
|
if res.len() > 0 {
|
||||||
// Currently ignores filter when it matches nothing
|
// Currently ignores filtered view when it matches nothing
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
// TODO use ChildrenIterator
|
||||||
self.resolve_tasks(self.children_of(self.position)).into_iter()
|
self.resolve_tasks(self.children_of(self.position)).into_iter()
|
||||||
.filter(|t| {
|
.filter(|t| {
|
||||||
// TODO apply filters in transit
|
// TODO apply filters in transit
|
||||||
|
@ -705,7 +707,7 @@ impl Tasks {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn track_at(&mut self, time: Timestamp) -> EventId {
|
pub(crate) fn track_at(&mut self, time: Timestamp) -> EventId {
|
||||||
info!("{} from {}", self.position.map_or(String::from("Stopping time-tracking"), |id| format!("Tracking \"{}\"", self.get_task_title(&id))), time.to_human_datetime()); // TODO omit seconds
|
info!("{} from {}", self.position.map_or(String::from("Stopping time-tracking"), |id| format!("Tracking \"{}\"", self.get_task_title(&id))), time.to_human_datetime());
|
||||||
let pos = self.get_position();
|
let pos = self.get_position();
|
||||||
let tracking = build_tracking(pos);
|
let tracking = build_tracking(pos);
|
||||||
// TODO this can lead to funny deletions
|
// TODO this can lead to funny deletions
|
||||||
|
@ -723,6 +725,7 @@ impl Tasks {
|
||||||
self.submit(tracking.custom_created_at(time))
|
self.submit(tracking.custom_created_at(time))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sign and queue the event to the relay, returning its id
|
||||||
fn submit(&mut self, builder: EventBuilder) -> EventId {
|
fn submit(&mut self, builder: EventBuilder) -> EventId {
|
||||||
let event = self.sender.submit(builder).unwrap();
|
let event = self.sender.submit(builder).unwrap();
|
||||||
let id = event.id;
|
let id = event.id;
|
||||||
|
@ -829,7 +832,7 @@ impl Tasks {
|
||||||
self.sorting = vec;
|
self.sorting = vec;
|
||||||
info!("Now sorting by {:?}", self.sorting);
|
info!("Now sorting by {:?}", self.sorting);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_sorting_property(&mut self, property: String) {
|
pub(crate) fn add_sorting_property(&mut self, property: String) {
|
||||||
// TODO reverse order if already present
|
// TODO reverse order if already present
|
||||||
self.sorting.push_front(property);
|
self.sorting.push_front(property);
|
||||||
|
@ -843,9 +846,11 @@ pub trait PropertyCollection<T> {
|
||||||
fn add_or_remove(&mut self, value: T);
|
fn add_or_remove(&mut self, value: T);
|
||||||
fn add_or_remove_at(&mut self, value: T, index: usize);
|
fn add_or_remove_at(&mut self, value: T, index: usize);
|
||||||
}
|
}
|
||||||
impl <T> PropertyCollection<T> for Vec<T>
|
impl<T> PropertyCollection<T> for Vec<T>
|
||||||
where T: Display, T: Eq, T: Clone {
|
where
|
||||||
fn remove_at(&mut self, index: usize) {
|
T: Display + Eq + Clone,
|
||||||
|
{
|
||||||
|
fn remove_at(&mut self, index: usize) {
|
||||||
let col = self.remove(index);
|
let col = self.remove(index);
|
||||||
info!("Removed property column \"{col}\"");
|
info!("Removed property column \"{col}\"");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue