From b969847060e7799c496fc373cae9824df4808efa Mon Sep 17 00:00:00 2001 From: Ji Sang Seo Date: Sat, 6 Apr 2024 16:59:18 +0900 Subject: [PATCH] feature: 'clean' command --- cli/oh-my-task-clean.mjs | 39 +++++++++++++++++ package.json | 6 ++- src/manifest.mjs | 34 ++++++++++++++ src/task/Task.mjs | 10 +++-- src/task/clean.mjs | 95 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 179 insertions(+), 5 deletions(-) create mode 100644 cli/oh-my-task-clean.mjs create mode 100644 src/task/clean.mjs diff --git a/cli/oh-my-task-clean.mjs b/cli/oh-my-task-clean.mjs new file mode 100644 index 0000000..36c5b9e --- /dev/null +++ b/cli/oh-my-task-clean.mjs @@ -0,0 +1,39 @@ +#!/usr/bin/env node + +import { Command } from "commander"; +import { clean } from "../src/task/clean.mjs"; + +async function cleanCommand() { + const program = new Command(); + program + .name("oh-my-task-clean") + .description("Clean project task history from global history") + .option("-c, --complete", "Clean all progresses with state of complete") + .option("-i, --idle", "Clean all progresses with state of idle"); + + program.parse(); + + const options = program.opts(); + + const cleanOptions = { + selection: true, + complete: false, + idle: false, + }; + + if (options.idle) { + cleanOptions.idle = true; + } + + if (options.complete) { + cleanOptions.complete = true; + } + + if (cleanOptions.idle || cleanOptions.complete) { + cleanOptions.selection = false; + } + + await clean(cleanOptions); +} + +await cleanCommand().catch((error) => console.error(error)); diff --git a/package.json b/package.json index c6fb482..de3d726 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "omt-list": "cli/oh-my-task-list.mjs", "omt-select": "cli/oh-my-task-select.mjs", "omt-pr": "cli/oh-my-task-pr.mjs", - "omt-finish": "cli/oh-my-task-finish.mjs" + "omt-finish": "cli/oh-my-task-finish.mjs", + "omt-clean": "cli/oh-my-task-clean.mjs" }, "scripts": { "release": "node ./release.mjs", @@ -24,7 +25,8 @@ "omt-select": "node ./cli/oh-my-task-select.mjs", "omt-pr": "node ./cli/oh-my-task-pr.mjs", "omt-finish": "node ./cli/oh-my-task-finish.mjs", - "omt-git": "node ./cli/oh-my-task-git.mjs" + "omt-git": "node ./cli/oh-my-task-git.mjs", + "omt-clean": "node ./cli/oh-my-task-clean.mjs" }, "keywords": [ "oh-my-task", diff --git a/src/manifest.mjs b/src/manifest.mjs index 2fdf1f5..e159b1e 100644 --- a/src/manifest.mjs +++ b/src/manifest.mjs @@ -196,6 +196,40 @@ export class Manifest { return fs.writeFile(this.historyPath, stringify(historyCollection)); } + async deleteHistory(taskKey) { + const fileContent = await fs + .readFile(this.historyPath, "utf8") + .catch((e) => ""); + + const historyCollection = parse(fileContent) ?? {}; + const { project } = await this.getConfig(); + + if (!historyCollection[project.key]) { + historyCollection[project.key] = {}; + } + + if (historyCollection[project.key][taskKey]) { + delete historyCollection[project.key][taskKey]; + } + return fs.writeFile(this.historyPath, stringify(historyCollection)); + } + + async overwriteHistroy(value) { + const fileContent = await fs + .readFile(this.historyPath, "utf8") + .catch((e) => ""); + + const historyCollection = parse(fileContent) ?? {}; + const { project } = await this.getConfig(); + + if (!historyCollection[project.key]) { + historyCollection[project.key] = {}; + } + + historyCollection[project.key] = value; + return fs.writeFile(this.historyPath, stringify(historyCollection)); + } + /** * Initialize project history (history.yaml). * This method is only used for initializing project. diff --git a/src/task/Task.mjs b/src/task/Task.mjs index 8015595..306f32a 100644 --- a/src/task/Task.mjs +++ b/src/task/Task.mjs @@ -53,14 +53,18 @@ export class Task { const previousStateText = TASK_STATUS_TEXT[this.getProgress()]; const currentStateText = TASK_STATUS_TEXT[TASK_STATUS.WORKING]; - console.log(`Switching to Task ${chalk.blueBright(this.key)}..`); + console.log( + `Switching to Task ${chalk.gray(this.title)}(${chalk.blueBright( + this.key + )})..` + ); this.setProgress(TASK_STATUS.WORKING); console.log( - `Task ${chalk.blueBright( + `Task ${chalk.gray(this.title)}(${chalk.blueBright( this.key - )} progress changed complete (${chalk.gray( + )}) progress changed complete (${chalk.gray( previousStateText )} -> ${chalk.green(currentStateText)})` ); diff --git a/src/task/clean.mjs b/src/task/clean.mjs new file mode 100644 index 0000000..2a5d9cb --- /dev/null +++ b/src/task/clean.mjs @@ -0,0 +1,95 @@ +import * as context from "../context.mjs"; +import { TASK_STATUS, TASK_STATUS_TEXT } from "../status.mjs"; +import * as input from "../input.mjs"; +import chalk from "chalk"; + +export async function clean( + cleanOptions = { + selection: true, + complete: false, + idle: false, + } +) { + let taskCollection = await context.manifest.getHistory(); + + if (cleanOptions.selection) { + const taskList = Object.keys(taskCollection).map((taskKey) => { + return { + name: taskCollection[taskKey].title, + value: taskKey, + }; + }); + + const selectedTask = await input.select("Select Task to clean:", taskList, [ + "name", + ]); + const taskTitle = taskCollection[selectedTask].title; + + await context.manifest.deleteHistory(selectedTask); + + console.log( + `Successfully cleaned task:: ${chalk.gray(taskTitle)}(${chalk.greenBright( + selectedTask + )})` + ); + return; + } + + if (cleanOptions.complete) { + const cleanResult = await batchClean(taskCollection, TASK_STATUS.COMPLETE); + + if (cleanResult.success) { + console.log( + `Total ${chalk.greenBright( + cleanResult.total + )} task with status ${chalk.bgBlueBright( + TASK_STATUS_TEXT[TASK_STATUS.COMPLETE] + )} has been deleted` + ); + } else { + throw new Error("Error occured while running batch clean"); + } + } + + if (cleanOptions.idle) { + const cleanResult = await batchClean(taskCollection, TASK_STATUS.IDLE); + + if (cleanResult.success) { + console.log( + `Total ${chalk.greenBright( + cleanResult.total + )} task with status ${chalk.bgBlueBright( + TASK_STATUS_TEXT[TASK_STATUS.IDLE] + )} has been deleted` + ); + } else { + throw new Error("Error occured while running batch clean"); + } + } +} + +async function batchClean(taskCollection, statusType) { + const reciept = { + success: true, + total: 0, + status: statusType, + }; + + const updatedTaskCollection = { ...taskCollection }; + + const targets = Object.keys(updatedTaskCollection).filter( + (taskKey) => updatedTaskCollection[taskKey].status === statusType + ); + console.log(targets, updatedTaskCollection); + + reciept.total = targets.length; + + targets.forEach((target) => { + delete updatedTaskCollection[target]; + }); + + await context.manifest.overwriteHistroy(updatedTaskCollection); + reciept.success = true; + + return reciept; +}