feat: Migration v0 to v1.
Move 'tasklist' table to 'taskslist' for compatibility. Add migration sql script. Add 'taskslist_info' view. Add 'completed_in' to tasks.
This commit is contained in:
12
data.py
12
data.py
@@ -9,7 +9,7 @@ class Task(RowModel):
|
||||
Schema
|
||||
------
|
||||
"""
|
||||
_tablename_ = 'tasklist'
|
||||
_tablename_ = 'taskslist'
|
||||
_cache_ = {}
|
||||
|
||||
taskid = Integer(primary=True)
|
||||
@@ -20,6 +20,7 @@ class Task(RowModel):
|
||||
duration = Integer()
|
||||
started_at = Timestamp()
|
||||
completed_at = Timestamp()
|
||||
completed_in = Integer()
|
||||
_timestamp = Timestamp()
|
||||
|
||||
|
||||
@@ -32,10 +33,12 @@ class TaskProfile(RowModel):
|
||||
_cache_ = {}
|
||||
|
||||
profileid = Integer(primary=True)
|
||||
show_tips = Bool()
|
||||
show_encouragement = Bool()
|
||||
|
||||
|
||||
class TaskInfo(RowModel):
|
||||
_tablename_ = 'tasklist_info'
|
||||
_tablename_ = 'taskslist_info'
|
||||
|
||||
taskid = Integer(primary=True)
|
||||
profileid = Integer()
|
||||
@@ -44,14 +47,17 @@ class TaskInfo(RowModel):
|
||||
duration = Integer()
|
||||
started_at = Timestamp()
|
||||
completed_at = Timestamp()
|
||||
completed_in = Integer()
|
||||
|
||||
last_started = Timestamp()
|
||||
nowid = Integer()
|
||||
order_idx = Integer()
|
||||
is_running = Bool()
|
||||
is_planned = Bool()
|
||||
is_complete = Bool()
|
||||
|
||||
show_tips = Bool()
|
||||
show_encouragement = Bool()
|
||||
|
||||
tasklabel = Integer()
|
||||
|
||||
@property
|
||||
|
||||
95
data/migrationv0-v1.sql
Normal file
95
data/migrationv0-v1.sql
Normal file
@@ -0,0 +1,95 @@
|
||||
BEGIN;
|
||||
-- Tasklist data {{{
|
||||
|
||||
CREATE TABLE taskslist(
|
||||
taskid INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
profileid INTEGER NOT NULL REFERENCES user_profiles(profileid) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
content TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ,
|
||||
duration INTEGER NOT NULL DEFAULT 0,
|
||||
started_at TIMESTAMPTZ,
|
||||
completed_at TIMESTAMPTZ,
|
||||
completed_in INTEGER NOT NULL REFERENCES communities(communityid) ON DELETE SET NULL,
|
||||
_timestamp TIMESTAMPTZ DEFAILT NOW()
|
||||
);
|
||||
CREATE TRIGGER tasklist_timestamp BEFORE UPDATE ON tasklist
|
||||
FOR EACH ROW EXECUTE FUNCTION update_timestamp_column();
|
||||
|
||||
|
||||
CREATE TABLE nowlist(
|
||||
taskid INTEGER PRIMARY KEY REFERENCES taskslist(taskid) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
last_started TIMESTAMPTZ NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE taskplan(
|
||||
taskid INTEGER PRIMARY KEY REFERENCES taskslist(taskid) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
order_idx INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE task_profiles(
|
||||
profileid INTEGER PRIMARY KEY REFERENCES user_profiles(profileid) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
show_tips BOOLEAN,
|
||||
show_encouragement BOOLEAN
|
||||
);
|
||||
|
||||
CREATE VIEW
|
||||
taskslist_info,
|
||||
AS
|
||||
SELECT
|
||||
taskslist.taskid AS taskid,
|
||||
taskslist.profileid AS profileid,
|
||||
taskslist.content AS content,
|
||||
taskslist.created_at AS created_at,
|
||||
taskslist.duration AS duration,
|
||||
taskslist.started_at AS started_at,
|
||||
taskslist.completed_at AS completed_at,
|
||||
taskslist.completed_in AS completed_in,
|
||||
nowlist.last_started AS last_started,
|
||||
taskplan.order_idx AS order_idx,
|
||||
task_profiles.show_tips AS show_tips,
|
||||
task_profiles.show_encouragement AS show_encouragement,
|
||||
(taskslist.completed_at IS NOT NULL) AS is_complete,
|
||||
(nowlist.taskid IS NOT NULL) AS is_running,
|
||||
(taskplan.order_idx IS NOT NULL) AS is_planned,
|
||||
(row_number() OVER (PARITION BY profileid ORDER BY taskid ASC)) AS tasklabel
|
||||
FROM
|
||||
taskslist
|
||||
LEFT JOIN nowlist USING (taskid)
|
||||
LEFT JOIN taskplan USING (taskid)
|
||||
LEFT JOIN task_profiles USING (profileid)
|
||||
WHERE deleted_at IS NULL
|
||||
ORDER BY (profileid, taskid);
|
||||
|
||||
|
||||
-- }}}
|
||||
|
||||
INSERT INTO taskslist (
|
||||
profileid,
|
||||
content,
|
||||
started_at,
|
||||
completed_at
|
||||
) VALUES (
|
||||
SELECT
|
||||
userid,
|
||||
task,
|
||||
started_at,
|
||||
done_at
|
||||
FROM
|
||||
nowlist_tasks
|
||||
);
|
||||
|
||||
INSERT INTO nowlist (
|
||||
taskid,
|
||||
last_started
|
||||
) VALUES (
|
||||
SELECT
|
||||
taskid,
|
||||
CASE WHEN completed_at IS NOT NULL THEN NULL
|
||||
ELSE started_at
|
||||
END
|
||||
FROM
|
||||
taskslist
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
@@ -1,8 +1,9 @@
|
||||
BEGIN;
|
||||
-- Tasklist data {{{
|
||||
|
||||
INSERT INTO version_history (component, from_version, to_version, author) VALUES ('TASKLIST', 0, 1, 'Initial Creation');
|
||||
|
||||
CREATE TABLE tasklist(
|
||||
CREATE TABLE taskslist(
|
||||
taskid INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
profileid INTEGER NOT NULL REFERENCES user_profiles(profileid) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
content TEXT NOT NULL,
|
||||
@@ -11,6 +12,7 @@ CREATE TABLE tasklist(
|
||||
duration INTEGER NOT NULL DEFAULT 0,
|
||||
started_at TIMESTAMPTZ,
|
||||
completed_at TIMESTAMPTZ,
|
||||
completed_in INTEGER NOT NULL REFERENCES communities(communityid) ON DELETE SET NULL,
|
||||
_timestamp TIMESTAMPTZ DEFAILT NOW()
|
||||
);
|
||||
CREATE TRIGGER tasklist_timestamp BEFORE UPDATE ON tasklist
|
||||
@@ -18,18 +20,49 @@ CREATE TRIGGER tasklist_timestamp BEFORE UPDATE ON tasklist
|
||||
|
||||
|
||||
CREATE TABLE nowlist(
|
||||
taskid INTEGER PRIMARY KEY REFERENCES tasklist(taskid) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
taskid INTEGER PRIMARY KEY REFERENCES taskslist(taskid) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
last_started TIMESTAMPTZ NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE taskplan(
|
||||
taskid INTEGER PRIMARY KEY REFERENCES tasklist(taskid) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
taskid INTEGER PRIMARY KEY REFERENCES taskslist(taskid) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
order_idx INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE task_profiles(
|
||||
profileid INTEGER PRIMARY KEY REFERENCES user_profiles(profileid) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
profileid INTEGER PRIMARY KEY REFERENCES user_profiles(profileid) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
show_tips BOOLEAN,
|
||||
show_encouragement BOOLEAN
|
||||
);
|
||||
|
||||
CREATE VIEW
|
||||
taskslist_info,
|
||||
AS
|
||||
SELECT
|
||||
taskslist.taskid AS taskid,
|
||||
taskslist.profileid AS profileid,
|
||||
taskslist.content AS content,
|
||||
taskslist.created_at AS created_at,
|
||||
taskslist.duration AS duration,
|
||||
taskslist.started_at AS started_at,
|
||||
taskslist.completed_at AS completed_at,
|
||||
taskslist.completed_in AS completed_in,
|
||||
nowlist.last_started AS last_started,
|
||||
taskplan.order_idx AS order_idx,
|
||||
task_profiles.show_tips AS show_tips,
|
||||
task_profiles.show_encouragement AS show_encouragement,
|
||||
(taskslist.completed_at IS NOT NULL) AS is_complete,
|
||||
(nowlist.taskid IS NOT NULL) AS is_running,
|
||||
(taskplan.order_idx IS NOT NULL) AS is_planned,
|
||||
(row_number() OVER (PARITION BY profileid ORDER BY taskid ASC)) AS tasklabel
|
||||
FROM
|
||||
taskslist
|
||||
LEFT JOIN nowlist USING (taskid)
|
||||
LEFT JOIN taskplan USING (taskid)
|
||||
LEFT JOIN task_profiles USING (profileid)
|
||||
WHERE deleted_at IS NULL
|
||||
ORDER BY (profileid, taskid);
|
||||
|
||||
|
||||
-- }}}
|
||||
COMMIT;
|
||||
|
||||
12
tasklist.py
12
tasklist.py
@@ -127,24 +127,28 @@ class Tasklist:
|
||||
async def unset_now(self):
|
||||
# Unset the current task and update the duration correctly
|
||||
# Does not put the current task on the plan
|
||||
# TODO: Transaction
|
||||
current = self.get_current()
|
||||
if current is not None:
|
||||
now = utc_now()
|
||||
assert current.is_running or (current.last_started is None)
|
||||
if current.is_running:
|
||||
if current.last_started is not None:
|
||||
duration = (now - current.last_started).total_seconds()
|
||||
duration += current.duration
|
||||
await self.data.tasklist.update_where(taskid=current.taskid).set(duration=duration)
|
||||
await self.data.nowlist.delete_where(taskid=current.taskid)
|
||||
await self.on_update()
|
||||
|
||||
async def complete_tasks(self, *taskids) -> list[TaskInfo]:
|
||||
async def complete_tasks(self, *taskids, communityid: int|None = None) -> list[TaskInfo]:
|
||||
# Remove any tasks which are already complete
|
||||
# TODO: Transaction
|
||||
# TODO: Uncomplete tasks
|
||||
taskids = [id for id in taskids if not self.id_tasks[id].is_complete]
|
||||
if taskids:
|
||||
now = utc_now()
|
||||
await self.data.tasklist.update_where(taskid=taskids).set(completed_at=now)
|
||||
await self.data.tasklist.update_where(taskid=taskids).set(
|
||||
completed_at=now,
|
||||
completed_in=communityid
|
||||
)
|
||||
if self.current in taskids:
|
||||
current = self.get_current()
|
||||
assert current is not None
|
||||
|
||||
@@ -58,8 +58,8 @@ class TaskComponent(cmds.Component):
|
||||
await self.tasker.setup()
|
||||
# TODO: Add the IPC task update callback
|
||||
|
||||
async def get_profile_for(self, user):
|
||||
...
|
||||
async def get_profile_for(self, user: twitchio.PartialUser):
|
||||
return await self.bot.profiles.fetch_profile(user)
|
||||
|
||||
@cmds.command(name='now', aliases=['task', 'check', 'add'])
|
||||
async def cmd_now(self, ctx: cmds.Context, *, args: Optional[str]):
|
||||
@@ -72,7 +72,6 @@ class TaskComponent(cmds.Component):
|
||||
# TODO: Breaking change: check and add should change behaviour.
|
||||
# Check shows the status of the given task (does not allow creation)
|
||||
# Add adds the task(s) to the end of the plan.
|
||||
# TODOTODO: Support newline breaking on multi-tasks!! Although prefer semicolons
|
||||
|
||||
profileid = (await self.get_profile_for(ctx.author)).profileid
|
||||
|
||||
|
||||
Reference in New Issue
Block a user