From 12a4b443cabc241dfa2ea67a76210e360043b52c Mon Sep 17 00:00:00 2001 From: Alexander Ivanov Date: Tue, 1 Oct 2024 14:58:56 +0300 Subject: [PATCH 1/5] feat(mcl.commands.add_task): Add initial version of `mcl add_task` command --- packages/mcl/src/main.d | 3 +- packages/mcl/src/src/mcl/commands/package.d | 1 + packages/mcl/src/src/mcl/utils/add_task.d | 64 +++++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 packages/mcl/src/src/mcl/utils/add_task.d diff --git a/packages/mcl/src/main.d b/packages/mcl/src/main.d index b6a12789..fd10e3cb 100644 --- a/packages/mcl/src/main.d +++ b/packages/mcl/src/main.d @@ -16,7 +16,8 @@ alias supportedCommands = imported!`std.traits`.AliasSeq!( cmds.shard_matrix, cmds.host_info, cmds.ci, - cmds.machine_create + cmds.machine_create, + cmds.add_task, ); int main(string[] args) diff --git a/packages/mcl/src/src/mcl/commands/package.d b/packages/mcl/src/src/mcl/commands/package.d index a02a3201..2e630c0b 100644 --- a/packages/mcl/src/src/mcl/commands/package.d +++ b/packages/mcl/src/src/mcl/commands/package.d @@ -7,3 +7,4 @@ public import mcl.commands.shard_matrix : shard_matrix; public import mcl.commands.ci : ci; public import mcl.commands.host_info : host_info; public import mcl.commands.machine_create : machine_create; +public import mcl.commands.add_task : add_task; diff --git a/packages/mcl/src/src/mcl/utils/add_task.d b/packages/mcl/src/src/mcl/utils/add_task.d new file mode 100644 index 00000000..a79a28d4 --- /dev/null +++ b/packages/mcl/src/src/mcl/utils/add_task.d @@ -0,0 +1,64 @@ +module mcl.commands.add_task; + +import std; +import mcl.utils.log : prompt; +import mcl.utils.json : toJSON, fromJSON; +import mcl.utils.env : optional, parseEnv; +import mcl.utils.coda : CodaApiClient, RowValues, CodaCell; + +void addTask() +{ + auto apiToken = environment.get("CODA_API_TOKEN"); + auto coda = CodaApiClient(apiToken); + auto documents = coda.listDocuments(); + auto task_db_document_id = "6vM0kjfQP6"; + auto tables = coda.listTables(task_db_document_id); + auto taskDbRows = coda.listRows(task_db_document_id, tables[0].id); + auto columns = coda.listColumns(task_db_document_id, tables[0].id); + auto summary_column_id = "c-JVJN4NvAgS"; + auto parent_ticket_column_id = "c-5qcLVwbpKP"; + auto assignee_column_id = "c-UN6X8s-5Oo"; + auto status_column_id = "c-o7Utgsgdrl"; + auto priority_column_id = "c-qWRh4X8QSm"; + + // if we need to add another column, find it's id from here: + // foreach (column; columns) + // { + // writeln(column); + // } + + // writeln(params); + RowValues[] rows = [ + RowValues([ + CodaCell(summary_column_id, params.taskName), + CodaCell(parent_ticket_column_id, params.parentTicket), + CodaCell(assignee_column_id, params.userName), + CodaCell(status_column_id, params.status), + CodaCell(priority_column_id, params.priority), + ]) + ]; + + auto resp = coda.insertRows(task_db_document_id, tables[0].id, rows); + assert(resp.length > 0); + writeln("response: ", resp); +} + +Params params; + +export void add_task() +{ + params = parseEnv!Params; + addTask(); +} +struct Params +{ + string parentTicket; + string taskName; + string userName; + string status; + string priority; + + void setup() + { + } +} From 98988bd8d16a12cfcbda26b7d6efbc4c06eba2c1 Mon Sep 17 00:00:00 2001 From: Alexander Ivanov Date: Wed, 2 Oct 2024 14:26:01 +0300 Subject: [PATCH 2/5] feat(mcl.commands.add_task): support milestone and estimate, make some params optional --- packages/mcl/src/src/mcl/utils/add_task.d | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/mcl/src/src/mcl/utils/add_task.d b/packages/mcl/src/src/mcl/utils/add_task.d index a79a28d4..b20932c0 100644 --- a/packages/mcl/src/src/mcl/utils/add_task.d +++ b/packages/mcl/src/src/mcl/utils/add_task.d @@ -20,6 +20,8 @@ void addTask() auto assignee_column_id = "c-UN6X8s-5Oo"; auto status_column_id = "c-o7Utgsgdrl"; auto priority_column_id = "c-qWRh4X8QSm"; + auto time_estimate_column_id = "c-ciqYsdyENp"; + auto milestone_column_id = "c-yIihZAmgKN"; // if we need to add another column, find it's id from here: // foreach (column; columns) @@ -35,6 +37,8 @@ void addTask() CodaCell(assignee_column_id, params.userName), CodaCell(status_column_id, params.status), CodaCell(priority_column_id, params.priority), + CodaCell(time_estimate_column_id, params.estimate), + CodaCell(milestone_column_id, params.milestone), ]) ]; @@ -55,8 +59,10 @@ struct Params string parentTicket; string taskName; string userName; - string status; - string priority; + @optional() string status = "Backlog"; + @optional() string priority = "normal"; + @optional() string milestone; + @optional() string estimate; void setup() { From 89201cd97c119f4a4fecf3c5a3f16434e80c1996 Mon Sep 17 00:00:00 2001 From: Alexander Ivanov Date: Fri, 4 Oct 2024 22:18:45 +0300 Subject: [PATCH 3/5] feat(mcl.commands.add_task): custom args / config logic --- packages/mcl/mcl_config.json | 19 + packages/mcl/src/main.d | 11 +- packages/mcl/src/src/mcl/commands/ci.d | 2 +- packages/mcl/src/src/mcl/commands/ci_matrix.d | 4 +- .../mcl/src/src/mcl/commands/deploy_spec.d | 2 +- packages/mcl/src/src/mcl/commands/get_fstab.d | 2 +- packages/mcl/src/src/mcl/commands/host_info.d | 2 +- .../mcl/src/src/mcl/commands/machine_create.d | 2 +- .../mcl/src/src/mcl/commands/shard_matrix.d | 2 +- packages/mcl/src/src/mcl/utils/add_task.d | 361 +++++++++++++++--- 10 files changed, 352 insertions(+), 55 deletions(-) create mode 100644 packages/mcl/mcl_config.json diff --git a/packages/mcl/mcl_config.json b/packages/mcl/mcl_config.json new file mode 100644 index 00000000..73a9c1c1 --- /dev/null +++ b/packages/mcl/mcl_config.json @@ -0,0 +1,19 @@ +{ + "codaApiToken": "", + "userNames": { + "Peter": "Peter Example", + "Alexander": "Alexander Ivanov" + }, + "defaultUserName": "", + "defaultParentTicket": "Example Base", + "defaultStatus": "Backlog", + "defaultPriority": "normal", + "defaultEstimate": "", + "defaultTshirtSize": "M", + "defaultMilestone": "beta", + "milestoneShortNames": { + "beta": "example: beta", + "month": "example: this month", + "v1": "example: v1" + } +} \ No newline at end of file diff --git a/packages/mcl/src/main.d b/packages/mcl/src/main.d index fd10e3cb..1f7baa27 100644 --- a/packages/mcl/src/main.d +++ b/packages/mcl/src/main.d @@ -27,7 +27,14 @@ int main(string[] args) string cmd = args[1]; LogLevel logLevel = LogLevel.info; - args.getopt("log-level", &logLevel); + + // sorry for that: it breaks my custom `--kind=arg` parsing + // in add_task.d + // probably there is a better method, but at least temporarily + // commented out for our fork + // (alexander): + // + // args.getopt("log-level", &logLevel); setLogLevel(logLevel); @@ -43,7 +50,7 @@ int main(string[] args) { infof("Running %s task", cmd.bold); - command(); + command(args); infof("Execution Succesfull"); return 0; } diff --git a/packages/mcl/src/src/mcl/commands/ci.d b/packages/mcl/src/src/mcl/commands/ci.d index 2575b92b..61d12588 100644 --- a/packages/mcl/src/src/mcl/commands/ci.d +++ b/packages/mcl/src/src/mcl/commands/ci.d @@ -18,7 +18,7 @@ import mcl.utils.json : toJSON; Params params; -export void ci() +export void ci(string[] args) { params = parseEnv!Params; diff --git a/packages/mcl/src/src/mcl/commands/ci_matrix.d b/packages/mcl/src/src/mcl/commands/ci_matrix.d index 764636ad..f457b84d 100755 --- a/packages/mcl/src/src/mcl/commands/ci_matrix.d +++ b/packages/mcl/src/src/mcl/commands/ci_matrix.d @@ -149,7 +149,7 @@ shared static this() params = parseEnv!Params; } -export void ci_matrix() +export void ci_matrix(string[] args) { createResultDirs(); nixEvalForAllSystems().array.printTableForCacheStatus(); @@ -186,7 +186,7 @@ Package[] checkCacheStatus(Package[] packages) return packages; } -export void print_table() +export void print_table(string[] args) { createResultDirs(); diff --git a/packages/mcl/src/src/mcl/commands/deploy_spec.d b/packages/mcl/src/src/mcl/commands/deploy_spec.d index 9ea2fc5e..abdf83e8 100644 --- a/packages/mcl/src/src/mcl/commands/deploy_spec.d +++ b/packages/mcl/src/src/mcl/commands/deploy_spec.d @@ -13,7 +13,7 @@ import mcl.utils.json : tryDeserializeFromJsonFile, writeJsonFile; import mcl.commands.ci_matrix : flakeAttr, params, nixEvalJobs, SupportedSystem; -export void deploy_spec() +export void deploy_spec(string[] args) { const deploySpecFile = resultDir.buildPath("cachix-deploy-spec.json"); diff --git a/packages/mcl/src/src/mcl/commands/get_fstab.d b/packages/mcl/src/src/mcl/commands/get_fstab.d index 032f79f3..d063b7ed 100755 --- a/packages/mcl/src/src/mcl/commands/get_fstab.d +++ b/packages/mcl/src/src/mcl/commands/get_fstab.d @@ -13,7 +13,7 @@ import mcl.utils.nix : queryStorePath, nix; import mcl.utils.string : camelCaseToCapitalCase; import mcl.utils.process : execute; -export void get_fstab() +export void get_fstab(string[] args) { const params = parseEnv!Params; const machineStorePath = getCachixDeploymentStorePath(params); diff --git a/packages/mcl/src/src/mcl/commands/host_info.d b/packages/mcl/src/src/mcl/commands/host_info.d index 1e45ff40..051cd8f7 100644 --- a/packages/mcl/src/src/mcl/commands/host_info.d +++ b/packages/mcl/src/src/mcl/commands/host_info.d @@ -62,7 +62,7 @@ string[string] getProcInfo(string fileOrData, bool file = true) return r; } -export void host_info() +export void host_info(string[] args) { const params = parseEnv!Params; diff --git a/packages/mcl/src/src/mcl/commands/machine_create.d b/packages/mcl/src/src/mcl/commands/machine_create.d index 37a7e6f1..67cbca4d 100755 --- a/packages/mcl/src/src/mcl/commands/machine_create.d +++ b/packages/mcl/src/src/mcl/commands/machine_create.d @@ -377,7 +377,7 @@ void createMachineConfiguration() Params params; -export void machine_create() +export void machine_create(string[] args) { params = parseEnv!Params; createMachineConfiguration(); diff --git a/packages/mcl/src/src/mcl/commands/shard_matrix.d b/packages/mcl/src/src/mcl/commands/shard_matrix.d index 77cdc486..b4307844 100644 --- a/packages/mcl/src/src/mcl/commands/shard_matrix.d +++ b/packages/mcl/src/src/mcl/commands/shard_matrix.d @@ -18,7 +18,7 @@ import mcl.utils.json : toJSON; import mcl.utils.nix : nix; import mcl.utils.path : createResultDirs, resultDir, rootDir; -export void shard_matrix() +export void shard_matrix(string[] args) { const params = parseEnv!Params; auto matrix = generateShardMatrix(); diff --git a/packages/mcl/src/src/mcl/utils/add_task.d b/packages/mcl/src/src/mcl/utils/add_task.d index b20932c0..16da5351 100644 --- a/packages/mcl/src/src/mcl/utils/add_task.d +++ b/packages/mcl/src/src/mcl/utils/add_task.d @@ -6,65 +6,336 @@ import mcl.utils.json : toJSON, fromJSON; import mcl.utils.env : optional, parseEnv; import mcl.utils.coda : CodaApiClient, RowValues, CodaCell; -void addTask() + +export void add_task(string[] args) { - auto apiToken = environment.get("CODA_API_TOKEN"); - auto coda = CodaApiClient(apiToken); - auto documents = coda.listDocuments(); - auto task_db_document_id = "6vM0kjfQP6"; - auto tables = coda.listTables(task_db_document_id); - auto taskDbRows = coda.listRows(task_db_document_id, tables[0].id); - auto columns = coda.listColumns(task_db_document_id, tables[0].id); - auto summary_column_id = "c-JVJN4NvAgS"; - auto parent_ticket_column_id = "c-5qcLVwbpKP"; - auto assignee_column_id = "c-UN6X8s-5Oo"; - auto status_column_id = "c-o7Utgsgdrl"; - auto priority_column_id = "c-qWRh4X8QSm"; - auto time_estimate_column_id = "c-ciqYsdyENp"; - auto milestone_column_id = "c-yIihZAmgKN"; - - // if we need to add another column, find it's id from here: - // foreach (column; columns) - // { - // writeln(column); - // } + TaskManager taskManager = new TaskManager(); + taskManager.tryLoadConfig("mcl_config.json"); - // writeln(params); - RowValues[] rows = [ - RowValues([ - CodaCell(summary_column_id, params.taskName), - CodaCell(parent_ticket_column_id, params.parentTicket), - CodaCell(assignee_column_id, params.userName), - CodaCell(status_column_id, params.status), - CodaCell(priority_column_id, params.priority), - CodaCell(time_estimate_column_id, params.estimate), - CodaCell(milestone_column_id, params.milestone), - ]) - ]; - - auto resp = coda.insertRows(task_db_document_id, tables[0].id, rows); - assert(resp.length > 0); - writeln("response: ", resp); + // writeln("config: ", taskManager.config); + // writeln(args); + + foreach(i, arg; args.enumerate(0)) { + // writeln(" arg ", i, " ", arg); + if (i < 2) { + continue; // ignore mcl and `add_task` command args + } + else if (i == 2) + { + taskManager.params.taskName = arg; + } + else + { + taskManager.processArg(arg); + } + } + // writeln("original params struct: ", taskManager.params); + taskManager.resolveParams(); + taskManager.addTaskToCoda(); +} + +struct TaskConfig { + string codaApiToken; + string[string] userNames; + string defaultUserName; + string defaultParentTicket; + string defaultStatus; + string defaultPriority; + string defaultEstimate; + string defaultTshirtSize; + string defaultMilestone; + string[string] milestoneShortNames; } -Params params; +class TaskManager { + Params params; + Params resolvedParams; + TaskConfig config; + + void tryLoadConfig(string filename) { + import std.file : readText; + import std.process: environment; + import std.json: parseJSON, JSONValue; + import std.stdio: stderr; + try + { + string raw = readText(filename); + JSONValue jsonConfig = parseJSON(raw); + this.config = jsonConfig.fromJSON!TaskConfig; + } + catch(Throwable) + { + stderr.writeln("read file error: ignoring and using $CODA_API_TOKEN and empty other fields by default"); + this.config.codaApiToken = environment.get("CODA_API_TOKEN", ""); + } + } + + string translateToUserName(string nameArg) { + return this.config.userNames.get(nameArg, nameArg); + } + + string translateMilestone(string name) { + return this.config.milestoneShortNames.get(name, name); + } -export void add_task() + // TODO: track cases of implicitly parsed args + // (like "backlog" => status) + // so in the end if we have + // implicit args, we might prompt the user + // maybe based on option in the config/ENV he can + // opt-in/opt-out of this prompt + Arg parseArg(string input) { + // writeln("parseArg ", input); + auto raw = input.toLower(); + + if (raw == "highest" || + raw == "high" || + raw == "normal" || + raw == "low") + { + Arg result = { kind: "priority", value: raw }; + return result; + } + else if (raw.startsWith("--priority=")) + { + // use `input`: with original casing! + Arg result = { kind: "priority", value: input["--priority=".length..$] }; + return result; + } + else if (raw == "backlog") + { + Arg result = { kind: "status", value: "Backlog" }; + return result; + } + else if (raw == "ready" || raw == "ready to start") + { + Arg result = { kind: "status", value: "Ready to Start" }; + return result; + } + else if (raw == "progress" || raw == "in progress") + { + Arg result = { kind: "status", value: "In progress" }; + return result; + } + else if (raw == "review" || raw == "code review") + { + Arg result = { kind: "status", value: "Code review" }; + return result; + } + else if (raw == "done") + { + Arg result = { kind: "status", value: "Done" }; + return result; + } + else if (raw == "paused") + { + Arg result = { kind: "status", value: "Paused" }; + return result; + } + else if (raw == "cancelled") + { + Arg result = { kind: "status", value: "Cancelled" }; + return result; + } + else if (raw == "blocked") + { + Arg result = { kind: "status", value: "blocked" }; + return result; + } + else if (raw.startsWith("--status=")) + { + // use `input`: with original casing! + Arg result = { kind: "status", value: input["--status=".length..$] }; + return result; + } + else if (raw in this.config.milestoneShortNames) + { + auto milestone = this.translateMilestone(raw); + Arg result = { kind: "milestone", value: milestone }; + return result; + } + else if (raw.startsWith("--milestone=")) + { + // use `input`: with original casing! + auto milestone = this.translateMilestone(input["--milestone=".length..$]); + Arg result = { kind: "milestone", value: milestone }; + return result; + } + else if (raw == "s" || + raw == "m" || + raw == "l" || + raw == "xl") + { + Arg result = { kind: "tshirt-size", value: raw.toUpper() }; + return result; + } + else if (raw.startsWith("--tshirt-size=")) + { + Arg result = { kind: "tshirt-size", value: input["--tshirt-size=".length..$] }; + return result; + } + // TODO: eventually special detection of ints or `int` (Peter's idea) + // as time estimates too + else if (raw.startsWith("--estimate=")) + { + // use `input`: with original casing! + Arg result = { kind: "estimate", value: input["--estimate=".length..$] }; + return result; + } + else + { + throw new TaskArgException(format!"can't parse %s"(raw)); + } + } + + void processArg(string raw) + { + if (raw[0] == '@') + { + this.params.userName = this.translateToUserName(raw[1..$]); + } + else + { + auto arg = this.parseArg(raw); + switch (arg.kind) { + case "priority": + { + this.params.priority = arg.value; + break; + } + case "status": + { + this.params.status = arg.value; + break; + } + case "milestone": + { + this.params.milestone = arg.value; + break; + } + case "estimate": + { + this.params.estimate = arg.value; + break; + } + case "tshirt-size": + { + this.params.tshirtSize = arg.value; + break; + } + default: + { + throw new TaskArgException(format!"unsupported arg kind %s"(arg.kind)); + } + } + } + } + + string argOrConfigOrDefault(string arg, string configDefault, string globalDefault) + { + if (arg.length > 0) + { + return arg; + } + else if (configDefault.length > 0) + { + return configDefault; + } + else + { + return globalDefault; + } + } + + void resolveParams() { + // resolves each param: + // first tries in explicit command args (initial `.params`) + // then in default equivalents from the config + // finally either leaves empty or uses a general default + + this.resolvedParams.userName = this.argOrConfigOrDefault(this.params.userName, this.translateToUserName(this.config.defaultUserName), ""); + this.resolvedParams.taskName = this.params.taskName; + this.resolvedParams.parentTicket = this.argOrConfigOrDefault(this.params.parentTicket, this.config.defaultParentTicket, ""); + this.resolvedParams.status = this.argOrConfigOrDefault(this.params.status, this.config.defaultStatus, "Backlog"); + this.resolvedParams.priority = this.argOrConfigOrDefault(this.params.priority, this.config.defaultPriority, "normal"); + this.resolvedParams.estimate = this.argOrConfigOrDefault(this.params.estimate, this.config.defaultEstimate, ""); + this.resolvedParams.tshirtSize = this.argOrConfigOrDefault(this.params.tshirtSize, this.config.defaultTshirtSize, "M"); + this.resolvedParams.milestone = this.argOrConfigOrDefault(this.params.milestone, this.translateMilestone(this.config.defaultMilestone), ""); + } + + void addTaskToCoda() + { + writeln("resolved params: ", this.resolvedParams); + writeln("preparing to send to coda"); + + auto coda = CodaApiClient(this.config.codaApiToken); + auto documents = coda.listDocuments(); + auto task_db_document_id = "6vM0kjfQP6"; + auto tables = coda.listTables(task_db_document_id); + auto taskDbRows = coda.listRows(task_db_document_id, tables[0].id); + auto columns = coda.listColumns(task_db_document_id, tables[0].id); + auto summary_column_id = "c-JVJN4NvAgS"; + auto parent_ticket_column_id = "c-5qcLVwbpKP"; + auto assignee_column_id = "c-UN6X8s-5Oo"; + auto status_column_id = "c-o7Utgsgdrl"; + auto priority_column_id = "c-qWRh4X8QSm"; + auto time_estimate_column_id = "c-ciqYsdyENp"; + auto tshirt_size_column_id = "c-6_I4159qaL"; + auto milestone_column_id = "c-yIihZAmgKN"; + + // if we need to add another column, find it's id from here: + // foreach (column; columns) + // { + // writeln(column); + // } + + RowValues[] rows = [ + RowValues([ + CodaCell(summary_column_id, params.taskName), + CodaCell(parent_ticket_column_id, this.resolvedParams.parentTicket), + CodaCell(assignee_column_id, this.resolvedParams.userName), + CodaCell(status_column_id, this.resolvedParams.status), + CodaCell(priority_column_id, this.resolvedParams.priority), + CodaCell(time_estimate_column_id, params.estimate), + CodaCell(tshirt_size_column_id, params.tshirtSize), + CodaCell(milestone_column_id, params.milestone), + ]) + ]; + + // writeln("sending ", rows); + + auto resp = coda.insertRows(task_db_document_id, tables[0].id, rows); + assert(resp.length > 0); + // writeln("response: ", resp); + } +} + +class TaskArgException : Exception { - params = parseEnv!Params; - addTask(); + this(string msg, string file = __FILE__, size_t line = __LINE__) { + super(msg, file, line); + } } + struct Params { string parentTicket; string taskName; string userName; - @optional() string status = "Backlog"; - @optional() string priority = "normal"; - @optional() string milestone; - @optional() string estimate; + string status; + string priority; + string milestone; + string estimate; + string tshirtSize; + void setup() { } } + +// TODO enum kind +struct Arg { + string kind; + string value; +} From 0170524b92db85de6ae8bb2bd550b51fbaedca50 Mon Sep 17 00:00:00 2001 From: Alexander Ivanov Date: Mon, 7 Oct 2024 12:20:51 +0300 Subject: [PATCH 4/5] feat(mcl.commands.add_task): add help for add_task --- packages/mcl/src/main.d | 8 ++++--- packages/mcl/src/src/mcl/commands/package.d | 2 +- packages/mcl/src/src/mcl/utils/add_task.d | 26 +++++++++++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/packages/mcl/src/main.d b/packages/mcl/src/main.d index 1f7baa27..6672bca2 100644 --- a/packages/mcl/src/main.d +++ b/packages/mcl/src/main.d @@ -5,7 +5,6 @@ import std.logger : infof, errorf, LogLevel; import mcl.utils.path : rootDir; import mcl.utils.tui : bold; - import cmds = mcl.commands; alias supportedCommands = imported!`std.traits`.AliasSeq!( @@ -73,8 +72,11 @@ int wrongUsage(string error) { writefln("Error: %s.", error); writeln("Usage:\n"); - static foreach (cmd; supportedCommands) + static foreach (cmd; supportedCommands) { writefln(" mcl %s", __traits(identifier, cmd)); - + static if (__traits(identifier, cmd) == "add_task") { + cmds.writeAddTaskHelp(); + } + } return 1; } diff --git a/packages/mcl/src/src/mcl/commands/package.d b/packages/mcl/src/src/mcl/commands/package.d index 2e630c0b..51c3c1d1 100644 --- a/packages/mcl/src/src/mcl/commands/package.d +++ b/packages/mcl/src/src/mcl/commands/package.d @@ -7,4 +7,4 @@ public import mcl.commands.shard_matrix : shard_matrix; public import mcl.commands.ci : ci; public import mcl.commands.host_info : host_info; public import mcl.commands.machine_create : machine_create; -public import mcl.commands.add_task : add_task; +public import mcl.commands.add_task : add_task, writeAddTaskHelp; diff --git a/packages/mcl/src/src/mcl/utils/add_task.d b/packages/mcl/src/src/mcl/utils/add_task.d index 16da5351..cc349e0e 100644 --- a/packages/mcl/src/src/mcl/utils/add_task.d +++ b/packages/mcl/src/src/mcl/utils/add_task.d @@ -20,6 +20,11 @@ export void add_task(string[] args) if (i < 2) { continue; // ignore mcl and `add_task` command args } + else if (arg == "--help") + { + writeAddTaskHelp(); + return; + } else if (i == 2) { taskManager.params.taskName = arg; @@ -34,6 +39,27 @@ export void add_task(string[] args) taskManager.addTaskToCoda(); } +export void writeAddTaskHelp() { + writeln(" mcl add_task [ ..]"); + writeln(" is `@` (might be a shorter name if registered in mcl_config.json)"); + writeln(" is highest / high / normal / low"); + writeln(" is backlog / ready (for ready to start) / progress (for in progress) / done / blocker / paused / cancelled"); + writeln(" is project-specific, but can be auto-recognized based on shorter names in mcl_config.json"); + writeln(" is time(days) estimate, needs explicit `--estimate=..` for now"); + writeln(" is S / M / L / XL"); + writeln(""); + writeln(" for all you can also pass explicit flag like `--priority="); + writeln(""); + writeln(" examples (with a hypothetical mcl_config.json):"); + writeln(" mcl add_task \"test task\" @Paul low progress beta M"); + writeln(" mcl add_task \"test task 2\" @Paul v1 L"); + writeln(" mcl add_task \"test task 3\" @John done normal M beta"); + writeln(" mcl add_task \"test task 4\" M backlog @John"); + writeln(" mcl add_task \"test task 5\""); + writeln(" mcl add_task \"test task 6\" @Paul --priority=low backlog"); + writeln(" mcl add_task \"test task 7\" @Paul --priority=low --status=backlog"); +} + struct TaskConfig { string codaApiToken; string[string] userNames; From 9a678420d3db3a1e01af771f5679d6f9cf70a895 Mon Sep 17 00:00:00 2001 From: Alexander Ivanov Date: Thu, 5 Dec 2024 20:43:27 +0200 Subject: [PATCH 5/5] fix: update some coda status names --- packages/mcl/src/src/mcl/utils/add_task.d | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/mcl/src/src/mcl/utils/add_task.d b/packages/mcl/src/src/mcl/utils/add_task.d index cc349e0e..12438b7b 100644 --- a/packages/mcl/src/src/mcl/utils/add_task.d +++ b/packages/mcl/src/src/mcl/utils/add_task.d @@ -43,7 +43,7 @@ export void writeAddTaskHelp() { writeln(" mcl add_task [ ..]"); writeln(" is `@` (might be a shorter name if registered in mcl_config.json)"); writeln(" is highest / high / normal / low"); - writeln(" is backlog / ready (for ready to start) / progress (for in progress) / done / blocker / paused / cancelled"); + writeln(" is backlog / next (for next up) / worked (for worked on) / done / blocked / paused / cancelled"); writeln(" is project-specific, but can be auto-recognized based on shorter names in mcl_config.json"); writeln(" is time(days) estimate, needs explicit `--estimate=..` for now"); writeln(" is S / M / L / XL"); @@ -51,7 +51,7 @@ export void writeAddTaskHelp() { writeln(" for all you can also pass explicit flag like `--priority="); writeln(""); writeln(" examples (with a hypothetical mcl_config.json):"); - writeln(" mcl add_task \"test task\" @Paul low progress beta M"); + writeln(" mcl add_task \"test task\" @Paul low worked beta M"); writeln(" mcl add_task \"test task 2\" @Paul v1 L"); writeln(" mcl add_task \"test task 3\" @John done normal M beta"); writeln(" mcl add_task \"test task 4\" M backlog @John"); @@ -133,14 +133,14 @@ class TaskManager { Arg result = { kind: "status", value: "Backlog" }; return result; } - else if (raw == "ready" || raw == "ready to start") + else if (raw == "next" || raw == "next up") { - Arg result = { kind: "status", value: "Ready to Start" }; + Arg result = { kind: "status", value: "Next Up" }; return result; } - else if (raw == "progress" || raw == "in progress") + else if (raw == "worked" || raw == "worked on") { - Arg result = { kind: "status", value: "In progress" }; + Arg result = { kind: "status", value: "Worked On" }; return result; } else if (raw == "review" || raw == "code review") @@ -165,7 +165,7 @@ class TaskManager { } else if (raw == "blocked") { - Arg result = { kind: "status", value: "blocked" }; + Arg result = { kind: "status", value: "Blocked" }; return result; } else if (raw.startsWith("--status="))