Repository: obsidian-tasks-group/obsidian-tasks (ts)

Issue:
Enable users to visualise the Status settings, and see any problems
### ⚠️ Please check that this feature request hasn't been suggested before.

- [X] I searched previous [Ideas in Discussions](https://github.com/obsidian-tasks-group/obsidian-tasks/discussions/categories/ideas-any-new-feature-requests-go-in-issues-please?discussions_q=category%3A%22Ideas%3A+Any+New+Feature+Requests+go+in+Issues+please%22+-label%3A%22status%3A+released%22+-label%3Aduplicate+sort%3Atop) didn't find any similar feature requests.
- [X] I searched previous [Issues](https://github.com/obsidian-tasks-group/obsidian-tasks/issues?q=is%3Aopen+is%3Aissue+label%3A%22type%3A+enhancement%22+sort%3Acomments-desc) didn't find any similar feature requests.
- [X] I am only requesting a single feature. Multiple changes should be split into individual requests, with links between them.
- [X] I believe my requested feature will be generally applicable to other users, not just me: it is not uniquely tied to my personal workflow.

### 🔖 Feature description

From replying to Tasks Issues and Features, it would be really useful to have a way to visualise a user's status settings, and even have a report of any issues in the settings.

### ✔️ Solution

### Visualising the Statuses

Now that I'm using the tests to generate Mermaid diagrams of statuses, for use in the docs, I'd love to make this available for users too.

I've been experimenting with this in my own vault, and it looks promising. I'll attach the diff below...

For ease of implementation, I've gone for creating a time-stamped file in the root of the vault.

Here is an example, from my main vault:

<img src="https://github.com/obsidian-tasks-group/obsidian-tasks/assets/4840096/6399d6c2-8b2a-4ce2-ac6f-34fbb9f44782" width="600">

### Reporting on any potential Issues

I'd like to also add a table of all the statuses in the user's settings, and include warnings such as:

- Duplicate symbols (which will not be shown in the diagram, and not added to the `StatusRegistry` - hence the table will need to be generated from the Settings)
- Next Symbol is not recognised
- DONE is not followed by TODO
- When #2089 and #2304 are fixed: there is no TODO status following on from a DONE status


### ❓ Alternatives

I experimented with displaying warnings in the Status Settings pane, without any success - such as making any problem status rows red.

A bonus option would be to find a way to let users know that there is at least one thing that needs checking, so please click the button to generate the report.


### 📝 Additional Context

The edit I'm using to generate reports like the image above:

```diff
Index: src/Config/SettingsTab.ts
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/Config/SettingsTab.ts b/src/Config/SettingsTab.ts
--- a/src/Config/SettingsTab.ts	(revision 11a958c88cb4270659a542b7c9ef9031f947c536)
+++ b/src/Config/SettingsTab.ts	(date 1697885636743)
@@ -569,6 +569,47 @@
         });
         addAllUnknownStatuses.infoEl.remove();
 
+        /* -------------------- 'Create file with Mermaid diagram of Statuses' button -------------------- */
+        const createMermaidDiagram = new Setting(containerEl).addButton((button) => {
+            button.setButtonText('Create file with Mermaid diagram of Statuses').onClick(async () => {
+                const detailed = true;
+                const mermaidText = StatusRegistry.getInstance().mermaidDiagram(detailed);
+
+                // Create a new file unique file and insert the mermaid text
+                const now = window.moment();
+                const formattedDateTime = now.format('YYYY-MM-DD HH-mm-ss');
+                const filename = `Tasks Plugin Diagram of Statuses ${formattedDateTime}.md`;
+
+                const fileContent = `
+# Diagram of Tasks Plugin Statuses
+
+This file was created by the Obsidian Tasks plugin, to help visualise the
+task statuses in this vault.
+
+You can delete this file any time.
+
+<!-- Switch to Live Preview or Reading Mode to see the diagram. -->
+
+${mermaidText}
+`;
+
+                // Ideas
+                // - Actually make it a plugin report, that reports any issues in settings with duplicate symbols.
+                // - Show any 'next status symbols' that are not known to the plugin.
+                // - Show any status transitions that won't work with recurring tasks currently, as DONE not followed by TODO.
+
+                const file = await app.vault.create(filename, fileContent);
+
+                // And open the new file
+                const leaf = this.app.workspace.getLeaf(true);
+                await leaf.openFile(file);
+            });
+            button.setTooltip(
+                'Create a new file in the root of the vault, containing a Mermaid diagram of the current status settings.',
+            );
+        });
+        createMermaidDiagram.infoEl.remove();
+
         /* -------------------- 'Reset Custom Status Types to Defaults' button -------------------- */
         const clearCustomStatuses = new Setting(containerEl).addButton((button) => {
             button
```


Pull request:
feat: Enable visualisation of the Status settings
<!--- Provide a general summary of your changes in the Title above -->

# Description

From replying to Tasks Issues and Features, it would be really useful to have a way to visualise a user's status settings, and even have a report of any issues in the settings.

This is what I've done so far:

- Add a button called `Review and check your Statuses` to the Tasks Custom Status settings.
- When clicked, it creates and opens a new markdown file, in the root of the vault.
- For simplicity, the file has a time-stamp in the name, so repeated running generates different files.
- The markdown file shows a Mermaid diagram of the Tasks Statuses actually loaded in the vault.

I plan to add some error checking info in a later PR.

_Note: I'm planning on changing this some more, so am holding off writing the documentation for now._

## Motivation and Context

<!--- Why is this change required? What problem does it solve? -->
<!--- If it fixes an open issue, please link to the issue here. -->

Fixes #2354 - good enough for a first implementation I feel.


## How has this been tested?

<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, tests ran to see how -->
<!--- your change affects other areas of the code, etc. -->

- Added new tests
- Ran existing ones
- Lots of manual testing in the demo vault, with a variety of different Status combinations.


## Screenshots (if appropriate)

The new button, with its current tooltip text shown:

![image](https://github.com/obsidian-tasks-group/obsidian-tasks/assets/4840096/1eb2eed5-f232-43a2-85a5-ddcdcf3c60f8)

An example output file, opened automatically and viewed in Obsidian's Liew Preview mode:


![image](https://github.com/obsidian-tasks-group/obsidian-tasks/assets/4840096/f6ccfcc7-7491-43ab-b9bd-fe2fa8ec9cb9)


## Types of changes

<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->

Changes visible to users:

- [x] **New feature** (prefix: `feat` - non-breaking change which adds functionality)

Internal changes:

- [x] **Tests** (prefix: `test` - additions and improvements to unit tests and the smoke tests)

## Checklist

<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->

- [x] My code follows the code style of this project and passes `yarn run lint`.
- [x] My change requires a change to the documentation.
- [ ] I have [updated the documentation](https://publish.obsidian.md/tasks-contributing/Documentation/About+Documentation) accordingly.
- [x] My change has adequate [Unit Test coverage](https://publish.obsidian.md/tasks-contributing/Testing/About+Testing).

## Terms

<!--
By submitting this pull request, you must agree to follow our
[contributing guide](https://publish.obsidian.md/tasks-contributing) and
[Code of Conduct](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CODE_OF_CONDUCT.md).
Put an x in the boxes to confirm you agree.
-->

- [x] My contribution follow this project's [contributing guide](https://publish.obsidian.md/tasks-contributing)
- [x] I agree to follow this project's [Code of Conduct](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CODE_OF_CONDUCT.md)


Patch:
diff --git a/resources/sample_vaults/Tasks-Demo/.gitignore b/resources/sample_vaults/Tasks-Demo/.gitignore
new file mode 100644
index 00000000..3688c1a7
--- /dev/null
+++ b/resources/sample_vaults/Tasks-Demo/.gitignore
@@ -0,0 +1,1 @@
+Tasks Plugin - Review and check your Statuses*
diff --git a/src/Config/SettingsTab.ts b/src/Config/SettingsTab.ts
index c9e91765..781e20ee 100644
--- a/src/Config/SettingsTab.ts
+++ b/src/Config/SettingsTab.ts
@@ -4,6 +4,7 @@ import type TasksPlugin from '../main';
 import { StatusRegistry } from '../StatusRegistry';
 import { Status } from '../Status';
 import type { StatusCollection } from '../StatusCollection';
+import { createStatusRegistryReport } from '../StatusRegistryReport';
 import * as Themes from './Themes';
 import { type HeadingState, TASK_FORMATS } from './Settings';
 import { getSettings, isFeatureEnabled, updateGeneralSetting, updateSettings } from './Settings';
@@ -569,6 +570,36 @@ export class SettingsTab extends PluginSettingTab {
         });
         addAllUnknownStatuses.infoEl.remove();
 
+        /* -------------------- 'Review and check your Statuses' button -------------------- */
+        const createMermaidDiagram = new Setting(containerEl).addButton((button) => {
+            const buttonName = 'Review and check your Statuses';
+            button
+                .setButtonText(buttonName)
+                .setCta()
+                .onClick(async () => {
+                    // Generate a new file unique file name, in the root of the vault
+                    const now = window.moment();
+                    const formattedDateTime = now.format('YYYY-MM-DD HH-mm-ss');
+                    const filename = `Tasks Plugin - ${buttonName} ${formattedDateTime}.md`;
+
+                    // Create the report
+                    const version = this.plugin.manifest.version;
+                    const statusRegistry = StatusRegistry.getInstance();
+                    const fileContent = createStatusRegistryReport(statusRegistry, buttonName, version);
+
+                    // Save the file
+                    const file = await app.vault.create(filename, fileContent);
+
+                    // And open the new file
+                    const leaf = this.app.workspace.getLeaf(true);
+                    await leaf.openFile(file);
+                });
+            button.setTooltip(
+                'Create a new file in the root of the vault, containing a Mermaid diagram of the current status settings.',
+            );
+        });
+        createMermaidDiagram.infoEl.remove();
+
         /* -------------------- 'Reset Custom Status Types to Defaults' button -------------------- */
         const clearCustomStatuses = new Setting(containerEl).addButton((button) => {
             button
diff --git a/src/StatusRegistryReport.ts b/src/StatusRegistryReport.ts
new file mode 100644
index 00000000..d421d9c4
--- /dev/null
+++ b/src/StatusRegistryReport.ts
@@ -0,0 +1,19 @@
+import type { StatusRegistry } from './StatusRegistry';
+
+export function createStatusRegistryReport(statusRegistry: StatusRegistry, buttonName: string, versionString: string) {
+    // Ideas for further improvement
+    // - Actually make it an informative report, that shows any issues in settings with duplicate symbols.
+    // - Show any 'next status symbols' that are not known to the plugin.
+    // - Show any status transitions that won't work with recurring tasks currently, as DONE not followed by TODO.
+
+    const detailed = true;
+    const mermaidText = statusRegistry.mermaidDiagram(detailed);
+    return `# ${buttonName}
+
+This file was created by the Obsidian Tasks plugin (version ${versionString}) to help visualise the task statuses in this vault.
+
+You can delete this file any time.
+
+<!-- Switch to Live Preview or Reading Mode to see the diagram. -->
+${mermaidText}`;
+}


Test patch:
diff --git a/tests/StatusRegistryReport.test.StatusRegistryReport_should_create_a_report.approved.md b/tests/StatusRegistryReport.test.StatusRegistryReport_should_create_a_report.approved.md
new file mode 100644
index 00000000..e6afd77d
--- /dev/null
+++ b/tests/StatusRegistryReport.test.StatusRegistryReport_should_create_a_report.approved.md
@@ -0,0 +1,23 @@
+# Review and check your Statuses
+
+This file was created by the Obsidian Tasks plugin (version x.y.z) to help visualise the task statuses in this vault.
+
+You can delete this file any time.
+
+<!-- Switch to Live Preview or Reading Mode to see the diagram. -->
+
+```mermaid
+flowchart LR
+1["'Todo'<br>[ ] -> [x]<br>(TODO)"]
+2["'In Progress'<br>[/] -> [x]<br>(IN_PROGRESS)"]
+3["'Done'<br>[x] -> [ ]<br>(DONE)"]
+4["'Cancelled'<br>[-] -> [ ]<br>(CANCELLED)"]
+5["'Question'<br>[Q] -> [A]<br>(NON_TASK)"]
+6["'Answer'<br>[A] -> [Q]<br>(NON_TASK)"]
+1 --> 3
+2 --> 3
+3 --> 1
+4 --> 1
+5 --> 6
+6 --> 5
+```
diff --git a/tests/StatusRegistryReport.test.ts b/tests/StatusRegistryReport.test.ts
new file mode 100644
index 00000000..08521620
--- /dev/null
+++ b/tests/StatusRegistryReport.test.ts
@@ -0,0 +1,21 @@
+import { StatusRegistry } from '../src/StatusRegistry';
+import { StatusConfiguration, StatusType } from '../src/StatusConfiguration';
+import { createStatusRegistryReport } from '../src/StatusRegistryReport';
+import { verifyWithFileExtension } from './TestingTools/ApprovalTestHelpers';
+
+describe('StatusRegistryReport', function () {
+    it('should create a report', () => {
+        // Arrange
+        const statusRegistry = new StatusRegistry();
+        statusRegistry.add(new StatusConfiguration('Q', 'Question', 'A', false, StatusType.NON_TASK));
+        statusRegistry.add(new StatusConfiguration('A', 'Answer', 'Q', false, StatusType.NON_TASK));
+        const reportName = 'Review and check your Statuses';
+
+        // Act
+        const version = 'x.y.z'; // lower-case, as the capitalised version would get edited at the next release.
+        const report = createStatusRegistryReport(statusRegistry, reportName, version);
+
+        // Assert
+        verifyWithFileExtension(report, '.md');
+    });
+});