feat(todo): show archived tasks from done.txt in a collapsible section
All checks were successful
CI / verify (push) Successful in 1m8s
All checks were successful
CI / verify (push) Successful in 1m8s
This commit is contained in:
@@ -23,6 +23,7 @@ type Prop = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const TODO_PATH = "todo.txt"
|
const TODO_PATH = "todo.txt"
|
||||||
|
const DONE_PATH = "done.txt"
|
||||||
|
|
||||||
const FluxNote = defineAsyncComponent(() => import("@/components/FluxNote.vue"))
|
const FluxNote = defineAsyncComponent(() => import("@/components/FluxNote.vue"))
|
||||||
|
|
||||||
@@ -58,6 +59,34 @@ watch(
|
|||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const doneFile = computed(() => store.files.find((f) => f.path === DONE_PATH))
|
||||||
|
const doneSha = computed(() => doneFile.value?.sha ?? "")
|
||||||
|
const donePath = computed(() => doneFile.value?.path ?? DONE_PATH)
|
||||||
|
|
||||||
|
// Reuse useTodoTxtCommit as a read-only loader. We never call its `mutate`,
|
||||||
|
// so nothing is ever written to done.txt from this view — the file is
|
||||||
|
// produced by an external tool.
|
||||||
|
const { items: doneItems, syncContent: syncDoneContent } = useTodoTxtCommit({
|
||||||
|
user: props.user,
|
||||||
|
repo: props.repo,
|
||||||
|
path: donePath,
|
||||||
|
initialContent: "",
|
||||||
|
initialSha: doneSha,
|
||||||
|
debounceMs: 1000
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
doneSha,
|
||||||
|
async (newSha) => {
|
||||||
|
if (!newSha) return
|
||||||
|
const base64 = await queryFileContent(props.user, props.repo, newSha)
|
||||||
|
if (base64) {
|
||||||
|
syncDoneContent(decodeBase64ToUTF8(base64), newSha)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
// Rank `A` = 65 .. `Z` = 90; absent priority is Infinity so it sorts last
|
// Rank `A` = 65 .. `Z` = 90; absent priority is Infinity so it sorts last
|
||||||
// regardless of locale collation quirks.
|
// regardless of locale collation quirks.
|
||||||
const priorityRank = (p?: string): number =>
|
const priorityRank = (p?: string): number =>
|
||||||
@@ -75,6 +104,10 @@ const taskEntries = computed(() => {
|
|||||||
return out
|
return out
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const archivedTasks = computed(() =>
|
||||||
|
doneItems.value.filter((line): line is Task => !isBlank(line))
|
||||||
|
)
|
||||||
|
|
||||||
const allProjects = computed(() => {
|
const allProjects = computed(() => {
|
||||||
const set = new Set<string>()
|
const set = new Set<string>()
|
||||||
items.value.forEach((line) => {
|
items.value.forEach((line) => {
|
||||||
@@ -431,6 +464,15 @@ const createTodoFile = async () => {
|
|||||||
>
|
>
|
||||||
Your todo list is empty. Add a task above.
|
Your todo list is empty. Add a task above.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<details v-if="doneFile" class="todo-archive">
|
||||||
|
<summary>Archived ({{ archivedTasks.length }})</summary>
|
||||||
|
<ul class="todo-archive-list">
|
||||||
|
<li v-for="(task, i) in archivedTasks" :key="i">
|
||||||
|
<todo-txt-item :task="task" :can-edit="false" />
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</details>
|
||||||
</template>
|
</template>
|
||||||
</flux-note>
|
</flux-note>
|
||||||
</div>
|
</div>
|
||||||
@@ -531,5 +573,37 @@ const createTodoFile = async () => {
|
|||||||
.todo-filter-chip {
|
.todo-filter-chip {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.todo-archive {
|
||||||
|
margin-top: 1rem;
|
||||||
|
|
||||||
|
> summary {
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0.7;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
> summary::-webkit-details-marker {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-archive-list {
|
||||||
|
list-style: none;
|
||||||
|
padding-left: 0;
|
||||||
|
margin: 0.5rem 0 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
li {
|
||||||
|
list-style: none;
|
||||||
|
opacity: 0.7;
|
||||||
|
padding-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user