diff --git a/resources/sample_vaults/Tasks-Demo/.gitignore b/resources/sample_vaults/Tasks-Demo/.gitignore
new file mode 100644
index 0000000000..3688c1a792
--- /dev/null
+++ b/resources/sample_vaults/Tasks-Demo/.gitignore
@@ -0,0 +1 @@
+Tasks Plugin - Review and check your Statuses*
diff --git a/src/Config/SettingsTab.ts b/src/Config/SettingsTab.ts
index c9e917651b..781e20ee5d 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 0000000000..d421d9c4cc
--- /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.
+
+
+${mermaidText}`;
+}
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 0000000000..e6afd77da7
--- /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.
+
+
+
+```mermaid
+flowchart LR
+1["'Todo'
[ ] -> [x]
(TODO)"]
+2["'In Progress'
[/] -> [x]
(IN_PROGRESS)"]
+3["'Done'
[x] -> [ ]
(DONE)"]
+4["'Cancelled'
[-] -> [ ]
(CANCELLED)"]
+5["'Question'
[Q] -> [A]
(NON_TASK)"]
+6["'Answer'
[A] -> [Q]
(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 0000000000..08521620ce
--- /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');
+ });
+});