Skip to content

Commit 6ed3a59

Browse files
authored
Merge pull request #3440 from obsidian-tasks-group/status-report-sample-tasks
Status report sample tasks
2 parents 59d99f9 + 961013e commit 6ed3a59

14 files changed

+219
-6
lines changed

docs/Getting Started/Statuses/Check your Statuses.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,28 @@ The sections are:
3333
- **Loaded Settings**
3434
- This has a **Mermaid diagram** showing transitions between your statuses.
3535
- View the report in Live Preview or Reading Mode, to see the diagram.
36+
- **Sample Tasks**
37+
- This has sample task lines for each valid status.
38+
- View the report in Live Preview or Reading Mode, to check they work with your Theme or CSS snippets.
39+
- **Search the Sample Tasks**
40+
- This has a Tasks search showing all the tasks in this file, grouped by their status type and status name.
3641

3742
## Example statuses report
3843

44+
### Table and diagram sections
45+
3946
Here is an example report, that is generated from the problem statuses shown in [[Recurring Tasks and Custom Statuses#When DONE is not followed by TODO or IN_PROGRESS|When DONE is not followed by TODO or IN_PROGRESS]]:
4047

4148
![Example statuses report](../../images/settings-statuses-report.png)<br>
4249
*Example statuses report*
50+
51+
### Sample tasks sections
52+
53+
Since Tasks X.Y.Z, there will also be **Sample Tasks** and **Search the Sample Tasks** sections.
54+
55+
Their appearance depends on your choice of Theme or CSS snippet.
56+
57+
Here is what it might look like with the **Minimal theme**, and **Colorful Headings** enabled in the **Minimal Theme Settings plugin**:
58+
59+
![Example statuses report samples](../../images/settings-statuses-report-samples.png)<br>
60+
*Example statuses report samples*

docs/What is New/Changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ _In recent [Tasks releases](https://github.com/obsidian-tasks-group/obsidian-tas
1212

1313
## 7.x releases
1414

15+
- X.Y.Z:
16+
- [[Check your Statuses]] report now contains samples of each status, and a convenient search to test them.
1517
- 7.19.0:
1618
- New setting to [[Recurring Tasks#Remove scheduled date on recurrence|remove scheduled date on recurrence]].
1719
- 7.16.0:
Loading

src/Statuses/StatusRegistryReport.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { StatusSettings } from '../Config/StatusSettings';
22
import { i18n } from '../i18n/i18n';
33
import type { StatusRegistry } from './StatusRegistry';
4-
import { tabulateStatusSettings } from './StatusSettingsReport';
4+
import { sampleTaskLinesForValidStatuses, tabulateStatusSettings } from './StatusSettingsReport';
55

66
export function createStatusRegistryReport(
77
statusSettings: StatusSettings,
@@ -17,6 +17,7 @@ export function createStatusRegistryReport(
1717
const detailed = true;
1818
const settingsTable = tabulateStatusSettings(statusSettings);
1919
const mermaidText = statusRegistry.mermaidDiagram(detailed);
20+
const sampleTasksText = sampleTaskLinesForValidStatuses(statusSettings);
2021
return `# ${buttonName}
2122
2223
## ${i18n.t('reports.statusRegistry.about.title')}
@@ -46,5 +47,34 @@ ${settingsTable}
4647
<!-- ${i18n.t('reports.statusRegistry.loadedSettings.switchToLivePreview')} -->
4748
4849
${i18n.t('reports.statusRegistry.loadedSettings.settingsActuallyUsed')}
49-
${mermaidText}`;
50+
${mermaidText}
51+
52+
## ${i18n.t('reports.statusRegistry.sampleTasks.title')}
53+
54+
${i18n.t('reports.statusRegistry.sampleTasks.line1')}
55+
56+
${i18n.t('reports.statusRegistry.sampleTasks.line2')}
57+
58+
${i18n.t('reports.statusRegistry.sampleTasks.line3')}
59+
60+
> [!Tip] ${i18n.t('reports.statusRegistry.sampleTasks.tip.line1')}
61+
> ${i18n.t('reports.statusRegistry.sampleTasks.tip.line2', {
62+
url: 'https://publish.obsidian.md/tasks/How+To/Style+custom+statuses',
63+
})}
64+
65+
${sampleTasksText.join('\n')}
66+
67+
## ${i18n.t('reports.statusRegistry.searchSampleTasks.title')}
68+
69+
${i18n.t('reports.statusRegistry.searchSampleTasks.line1')}
70+
71+
\`\`\`tasks
72+
path includes {{query.file.path}}
73+
group by status.type
74+
group by status.name
75+
sort by function task.lineNumber
76+
hide postpone button
77+
short mode
78+
\`\`\`
79+
`;
5080
}

src/Statuses/StatusSettingsReport.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { StatusSettings } from '../Config/StatusSettings';
22
import { MarkdownTable } from '../lib/MarkdownTable';
33
import { i18n } from '../i18n/i18n';
4-
import type { StatusConfiguration } from './StatusConfiguration';
5-
import { StatusType } from './StatusConfiguration';
4+
import { GlobalFilter } from '../Config/GlobalFilter';
5+
import { type StatusConfiguration, StatusType } from './StatusConfiguration';
66
import { Status } from './Status';
7+
import { StatusRegistry } from './StatusRegistry';
78

89
function getFirstIndex(statusConfigurations: StatusConfiguration[], wantedSymbol: string) {
910
return statusConfigurations.findIndex((s) => s.symbol === wantedSymbol);
@@ -114,3 +115,28 @@ export function tabulateStatusSettings(statusSettings: StatusSettings) {
114115
});
115116
return table.markdown;
116117
}
118+
119+
/**
120+
* Generates a list of Markdown lines, containing sample tasks based on the given status settings.
121+
*
122+
* @param {StatusSettings} statusSettings - The settings object containing custom and core statuses.
123+
*
124+
* @returns {string[]} An array of markdown strings representing sample tasks.
125+
* Each task includes a symbol, an introductory text, and the name of the status.
126+
* Only the actually registered symbols are used; duplicate and empty symbols are ignored.
127+
* The Global Filter will be added, if it is non-empty.
128+
*/
129+
export function sampleTaskLinesForValidStatuses(statusSettings: StatusSettings) {
130+
const statusRegistry = new StatusRegistry();
131+
StatusSettings.applyToStatusRegistry(statusSettings, statusRegistry);
132+
const registeredStatuses: StatusConfiguration[] = statusRegistry.registeredStatuses;
133+
134+
return registeredStatuses.map((status, index) => {
135+
const globalFilter = GlobalFilter.getInstance();
136+
const globalFilterIfSet = globalFilter.isEmpty() ? '' : globalFilter.get() + ' ';
137+
const intro = `Sample task ${index + 1}`;
138+
const symbol = `status symbol=${getPrintableSymbol(status.symbol)}`;
139+
const name = `status name='${status.name}'`;
140+
return `- [${status.symbol}] ${globalFilterIfSet}${intro}: ${symbol} ${name}`;
141+
});
142+
}

src/i18n/locales/be.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,20 @@
6464
"line3": "Глядзіце [Recurring Tasks and Custom Statuses]({{helpURL}})."
6565
}
6666
},
67+
"sampleTasks": {
68+
"line1": "",
69+
"line2": "",
70+
"line3": "",
71+
"tip": {
72+
"line1": "",
73+
"line2": ""
74+
},
75+
"title": ""
76+
},
77+
"searchSampleTasks": {
78+
"line1": "",
79+
"title": ""
80+
},
6781
"statusSettings": {
6882
"comment": {
6983
"line1": "Пераключыцеся ў рэжым папярэдняга прагляду ў рэальным часе або рэжым чытання, каб убачыць табліцу.",

src/i18n/locales/en.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,20 @@
6464
"line3": "See [Recurring Tasks and Custom Statuses]({{helpURL}})."
6565
}
6666
},
67+
"sampleTasks": {
68+
"line1": "Here is one example task line for each of the statuses actually used by tasks, for you to experiment with.",
69+
"line2": "The status symbols and names in the task descriptions were correct when this file was created.",
70+
"line3": "If you have modified the sample tasks since they were created, you can see the current status types and names in the group headings in the Tasks search below.",
71+
"tip": {
72+
"line1": "Tip: If all your checkboxes look the same...",
73+
"line2": "If all the checkboxes look the same in Reading Mode or Live Preview, see [Style custom statuses]({{url}}) for how to select a theme or CSS snippet to style your statuses."
74+
},
75+
"title": "Sample Tasks"
76+
},
77+
"searchSampleTasks": {
78+
"line1": "This Tasks search shows all the tasks in this file, grouped by their status type and status name.",
79+
"title": "Search the Sample Tasks"
80+
},
6781
"statusSettings": {
6882
"comment": {
6983
"line1": "Switch to Live Preview or Reading Mode to see the table.",

src/i18n/locales/ru.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,20 @@
6464
"line3": "См. [Recurring Tasks and Custom Statuses]({{helpURL}})."
6565
}
6666
},
67+
"sampleTasks": {
68+
"line1": "",
69+
"line2": "",
70+
"line3": "",
71+
"tip": {
72+
"line1": "",
73+
"line2": ""
74+
},
75+
"title": ""
76+
},
77+
"searchSampleTasks": {
78+
"line1": "",
79+
"title": ""
80+
},
6781
"statusSettings": {
6882
"comment": {
6983
"line1": "Переключитесь в режим Live Preview или Reading Mode, чтобы увидеть таблицу.",

src/i18n/locales/uk.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,20 @@
6464
"line3": "Див. [Повторювані задачі та користувацькі статуси]({{helpURL}})."
6565
}
6666
},
67+
"sampleTasks": {
68+
"line1": "",
69+
"line2": "",
70+
"line3": "",
71+
"tip": {
72+
"line1": "",
73+
"line2": ""
74+
},
75+
"title": ""
76+
},
77+
"searchSampleTasks": {
78+
"line1": "",
79+
"title": ""
80+
},
6781
"statusSettings": {
6882
"comment": {
6983
"line1": "Перейдіть у режим Live Preview або режим читання, щоб побачити таблицю.",

src/i18n/locales/zh_cn.json

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,20 @@
6464
"line3": "请参阅[重复任务和自定义状态]({{helpURL}})。"
6565
}
6666
},
67+
"sampleTasks": {
68+
"line1": "",
69+
"line2": "",
70+
"line3": "",
71+
"tip": {
72+
"line1": "",
73+
"line2": ""
74+
},
75+
"title": ""
76+
},
77+
"searchSampleTasks": {
78+
"line1": "",
79+
"title": ""
80+
},
6781
"statusSettings": {
6882
"comment": {
6983
"line1": "切换到实时预览或阅读模式以查看表格.",
@@ -242,4 +256,4 @@
242256
"heading": "任务状态"
243257
}
244258
}
245-
}
259+
}

tests/Statuses/StatusRegistryReport.test.StatusRegistryReport_should_create_a_report.approved.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,35 @@ classDef NON_TASK stroke:#99e,stroke-width:3px;
6161
6262
linkStyle default stroke:gray
6363
```
64+
65+
66+
## Sample Tasks
67+
68+
Here is one example task line for each of the statuses actually used by tasks, for you to experiment with.
69+
70+
The status symbols and names in the task descriptions were correct when this file was created.
71+
72+
If you have modified the sample tasks since they were created, you can see the current status types and names in the group headings in the Tasks search below.
73+
74+
> [!Tip] Tip: If all your checkboxes look the same...
75+
> If all the checkboxes look the same in Reading Mode or Live Preview, see [Style custom statuses](https://publish.obsidian.md/tasks/How+To/Style+custom+statuses) for how to select a theme or CSS snippet to style your statuses.
76+
77+
- [ ] Sample task 1: status symbol=`space` status name='Todo'
78+
- [x] Sample task 2: status symbol=`x` status name='Done'
79+
- [/] Sample task 3: status symbol=`/` status name='In Progress'
80+
- [-] Sample task 4: status symbol=`-` status name='Cancelled'
81+
- [Q] Sample task 5: status symbol=`Q` status name='Question'
82+
- [A] Sample task 6: status symbol=`A` status name='Answer'
83+
84+
## Search the Sample Tasks
85+
86+
This Tasks search shows all the tasks in this file, grouped by their status type and status name.
87+
88+
```tasks
89+
path includes {{query.file.path}}
90+
group by status.type
91+
group by status.name
92+
sort by function task.lineNumber
93+
hide postpone button
94+
short mode
95+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- [ ] Sample task 1: status symbol=`space` status name='Todo'
2+
- [x] Sample task 2: status symbol=`x` status name='Done'
3+
- [/] Sample task 3: status symbol=`/` status name='A slash'
4+
- [p] Sample task 4: status symbol=`p` status name='A p'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- [ ] #task Sample task 1: status symbol=`space` status name='Todo'
2+
- [x] #task Sample task 2: status symbol=`x` status name='Done'
3+
- [/] #task Sample task 3: status symbol=`/` status name='A slash'
4+
- [p] #task Sample task 4: status symbol=`p` status name='A p'

tests/Statuses/StatusSettingsReport.test.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
import { StatusSettings } from '../../src/Config/StatusSettings';
2-
import { tabulateStatusSettings } from '../../src/Statuses/StatusSettingsReport';
2+
import { sampleTaskLinesForValidStatuses, tabulateStatusSettings } from '../../src/Statuses/StatusSettingsReport';
33
import type { StatusCollection } from '../../src/Statuses/StatusCollection';
44
import { verifyWithFileExtension } from '../TestingTools/ApprovalTestHelpers';
55
import { coreStatusesData, createStatuses } from '../TestingTools/StatusesTestHelpers';
66
import { initializeI18n } from '../../src/i18n/i18n';
7+
import { GlobalFilter } from '../../src/Config/GlobalFilter';
78

89
beforeAll(async () => {
910
await initializeI18n();
1011
});
1112

13+
afterEach(() => {
14+
GlobalFilter.getInstance().reset();
15+
});
16+
1217
describe('StatusSettingsReport', () => {
1318
it('should tabulate StatusSettings', () => {
1419
const statusSettings = new StatusSettings();
@@ -36,4 +41,26 @@ describe('StatusSettingsReport', () => {
3641
const markdown = tabulateStatusSettings(statusSettings);
3742
verifyWithFileExtension(markdown, '.md');
3843
});
44+
45+
const customStatusesDataForSampleLines: StatusCollection = [
46+
['/', 'A slash', 'x', 'IN_PROGRESS'],
47+
['/', 'In Progress DUPLICATE - SHOULD NOT BE IN SAMPLE TASK LINES', 'x', 'IN_PROGRESS'],
48+
['', 'EMPTY STATUS SYMBOL - SHOULD NOT BE IN SAMPLE TASK LINES', '', 'TODO'],
49+
['p', 'A p', 'q', 'TODO'],
50+
];
51+
52+
it('should create set of sample task lines, excluding duplicate and empty symbols', () => {
53+
const { statusSettings } = createStatuses(coreStatusesData, customStatusesDataForSampleLines);
54+
55+
const taskLines = sampleTaskLinesForValidStatuses(statusSettings);
56+
verifyWithFileExtension(taskLines.join('\n'), '.md');
57+
});
58+
59+
it('should create set of sample task lines include global filter', () => {
60+
GlobalFilter.getInstance().set('#task');
61+
const { statusSettings } = createStatuses(coreStatusesData, customStatusesDataForSampleLines);
62+
63+
const taskLines = sampleTaskLinesForValidStatuses(statusSettings);
64+
verifyWithFileExtension(taskLines.join('\n'), '.md');
65+
});
3966
});

0 commit comments

Comments
 (0)