今日やるリストを表示するPageMenu
今日やるリストを表示するPage Menu
次に取るべき行動の一覧を表示するPage Menuだと、直近の次に取るべき行動から1年後にやるものまで全部一緒くたにでてきてしまい、非常に見づらかった
今日やるリストだけを表示するようにして、使い勝手を上げてみる
interfaceのアイデア
Page Menuを使う
Page Menuを押したらリストが出る
Page Menuを押したら「今日やるリストを出す」「1週間以内にやることを出す」などのいくつかのボタンがある
それらを押すと、その範囲に絞った結果が表示される
どこに表示すればいいだろうか?
これ実装したいtakker.icon
いろんな期間のタスクを見れるとよい
とりあえず今日やるリストまでは作れたので、これをしばらく使ってから様子見かな
今日やるリストをclipboardに貼り付けるUserScriptを取り込んでみる?
Reloadの下にCopy Allボタンをつける
これを押すと、今日やることがリスト形式でコピーされる
code:format.txt
やり残していること
xxx
今日やること
yyy
明日やること
zzz
今週やること
www
独自のUIを組み立てる
こっちでやりたくなってきた
takker-workflow@0.0.1/next-action-viewer
以下、「Page Menuを使う」案を採用して作成したUserScriptとなる
実装したいこと
↑のUIにする
これはtakker-workflow@0.0.1中のtoolとして新しく作り直したほうがよさそうだな
projectごとに区切り線で分けるのをやめる
全然使わなった
2022-03-25
22:16:37 group()のテストを書く
これをやったら終わり
23:02:29 終了
結構間違えていた
22:15:29 コピペ機能もできた
期間を細かく分け過ぎな気もするが
とりあえずこれで使ってみる
21:54:37 merged
21:52:53 readLinksBulkにバグが有ったので直す
13:36:47 函数を切り出した
今日やるリストをclipboardに貼り付けるUserScriptでも使いたかった
2022-03-15
05:48:05 いいかんじ!
https://gyazo.com/368c4d5a0ea6c8d666135a0e7bc34aa2
完了したやつを外すの忘れてた
05:48:55 直した
05:42:59 script.tsの型チェック終了
05:25:00 E2Eテストやる
実際にuserscriptを動かしてみることをかっこよく言ってみただけtakker.icon
05:19:07 締切 & いつ頃やるかの両方があったときのテストもいれた
05:12:48 parserのテスト終了
2022-03-14
18:49:42 parserを作っていたが、単に探して羅列するだけならそんな必要ないことに気づいた
たとえば2022-03-14にやるタスクを表示するなら、@2022-03-14と~2022-03-14と@2022-w12のいずれかの文字列を含むリンクを表示すればいい
あ、だめだ。それだと期限切れのタスクを表示できない……
一旦期限切れは無視するか?
過去1週間分の日付を列挙して力業で検索するという手段もある
バグ
[⬜️@2022-03-18 ~を!に置き換える]がタスクとして認識されない
これをテストケースに加えて、テストが通るようにコードを修正しよう
09:22:13 今やったら認識された
serverのDB更新にラグがあっただけだろうか?
まあいいや
https://scrapbox-bundler.vercel.app/?url=https://scrapbox.io/api/code/takker/今日やるリストを表示するPageMenu/script.ts&bundle&minify&run&output=newtab&reload
code:script.ts
import { setup } from "./mod.ts";
setup("takker-memex", "takker");
code:type_check.sh
deno cache -r=https://scrapbox.io https://scrapbox.io/api/code/takker/今日やるリストを表示するPageMenu/mod.ts
code:mod.ts
/// <reference no-default-lib="true" />
/// <reference lib="esnext" />
/// <reference lib="dom" />
import { classify, Category, list, Task } from "../takker99%2Ftakker-scheduler/workflow.ts";
import {
useStatusBar,
openInTheSameTab,
encodeTitleURI,
toTitleLc,
} from "../scrapbox-userscript-std/dom.ts";
import type { Scrapbox } from "../scrapbox-jp%2Ftypes/mod.ts";
declare const scrapbox: Scrapbox;
const id = "today-next-action";
let loading = false;
let initialized: Promise<void>;
const dummyImage = "/assets/img/favicon/apple-touch-icon.png";
entory point
code:mod.ts
export function setup(projects: string[]) {
PageMenuのアイコンをFont Awesome 5 FreeにするためにStyleを追加している
code:mod.ts
const selector = head style[data-userscript-name="${id}"];
document.querySelector(selector)?.remove?.();
const style = document.createElement("style");
style.dataset.userscriptName = id;
style.textContent = `a#${id}.tool-btn:hover {
text-decoration: none;
}
a#${id}.tool-btn::before {
position: absolute;
content: "\\f0ae";
font: 900 20px/46px "Font Awesome 5 Free";
}
a#${id}.tool-btn img {
opacity: 0;
}
a#${id}.tool-btn ~ ul a::before {
position: absolute;
font-family: "Font Awesome 5 Free";
font-weight: 900;
}
a#${id}.tool-btn ~ ul img {
opacity: 0;
margin-right: 0;
}`;
document.head.append(style);
Page Menuを入れる
code:mod.ts
if (!document.getElementById(id)) {
scrapbox.PageMenu.addMenu({
title: id,
image: dummyImage,
onClick: async () => {
initialized ??= load(projects);
await initialized;
},
});
}
}
今日やることを取得する
code:mod.ts
/** 一度取得したTaskを貯めておく場所
*
* reloadでresetされる
*/
const tasks: {
project: string;
title: string;
task: Task;
}[] = [];
async function load(projects: string[]) {
scrapbox.PageMenu(id).removeAllItems();
loading = true;
// 再読み込み用
scrapbox.PageMenu(id).addItem({
title: "Reload",
onClick: () => {
if (loading) return;
load(projects);
},
});
// コピペ用
scrapbox.PageMenu(id).addItem({
title: "Copy missed and today actions",
onClick: async () => {
const today = new Date();
const titles = tasks.map(({ task, title }) => {
const category = classify(task, today);
return { category, title };
});
const text = [
"今日やること",
...titles.flatMap(
({ category, title }) => category === "today" ? [ [${title}]] : []
),
"",
"やり残していること",
...titles.flatMap(
({ category, title }) => category === "missed" ? [ [${title}]] : []
),
"",
].join("\n");
try {
await navigator.clipboard.writeText(text);
} catch(e: unknown) {
if (!(e instanceof Error)) throw e;
console.error(e);
alert(${e.name} ${e.message});
}
},
});
const buttons: string, string, Category[] = [
"Copy tomorrow actions", "明日やること", "tomorrow",
"Copy this week actions", "今週やること", "in week",
"Copy next week actions", "来週やること", "in next week",
"Copy this month actions", "今月やること", "in month",
"Copy next month actions", "来月やること", "in next month",
"Copy this year actions", "今年やること", "in year",
"Copy next year actions", "来年やること", "in next year",
"Copy someday actions", "いつかやること", "someday",
"Copy no period actions", "時間情報なし", "no startAt",
]
for (const button, section, cat of buttons) {
scrapbox.PageMenu(id).addItem({
title: button,
onClick: async () => {
const today = new Date();
const titles = tasks.map(({ task, title }) => {
const category = classify(task, today);
return { category, title };
});
const text = [
section,
...titles.flatMap(
({ category, title }) => category === cat ? [ [${title}]] : []
),
"",
].join("\n");
try {
await navigator.clipboard.writeText(text);
} catch(e: unknown) {
if (!(e instanceof Error)) throw e;
console.error(e);
alert(${e.name} ${e.message});
}
},
});
}
const { render, dispose } = useStatusBar();
try {
const titleLcs = new Set<string>(); // 重複除外用
const today = new Date();
for (const project of projects) {
render(
{ type: "spinner" },
{ type: "text", text: Searching "/${project}" for next actions...},
);
for await (const { task, title } of list(project)) {
const titleLc = toTitleLc(title);
if (titleLcs.has(titleLc)) continue;
titleLcs.add(titleLc);
if (task.status === "✅") continue;
if (task.status === "❌") continue;
tasks.push({ project, title, task });
const category = classify(task, today);
if (
category !== "missed" &&
category !== "today"
) continue;
scrapbox.PageMenu(id).addItem({
title,
onClick: () => {
if (project !== scrapbox.Project.name) {
const path = `https://scrapbox.io/${
project
}/${encodeTitleURI(title)}`;
window.open(path);
return;
}
openInTheSameTab(project, title);
},
});
}
if (project === projectsprojects.length - 1) continue;
scrapbox.PageMenu(id).addSeparator();
}
render(
{ type: "check-circle" },
{ type: "text", text: Found actions.},
);
} catch(e: unknown) {
render(
{ type: "exclamation-triangle" },
{ type: "text", text: e instanceof Error ?
${e.name} ${e.message} :
Unknown error! (see developper console),
},
);
console.error(e);
} finally {
loading = false;
setTimeout(() => dispose(), 1000);
}
}
タスクをstartAtに応じて振り分ける
takker-workflow@0.0.1/classifyに移動した
次に取るべき行動を取得する
takker-workflow@0.0.1/listに移した
タスクの書式解析など
別ページに切り出したほうがいいかも
Githubに入れる……までしなくてもいいか
2022-03-18 13:51:14 切り出した
takker-workflow@0.0.1/parse
#2022-04-09 10:33:42
#2022-04-08 22:49:29
#2022-03-25 09:11:17
#2022-03-22 18:41:43
#2022-03-18 05:54:23
#2022-03-15 04:27:47
#2022-03-14 13:48:05
#2022-03-10 19:35:24
#2022-03-09 12:01:34