Skip to content

Commit f94572d

Browse files
committed
There should be an option to put the global filter at the end
Fixes obsidian-tasks-group#147
1 parent 292f684 commit f94572d

File tree

4 files changed

+133
-18
lines changed

4 files changed

+133
-18
lines changed

β€Žsrc/Feature.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,19 @@ export class Feature {
1717
false,
1818
);
1919

20+
static readonly APPEND_GLOBAL_FILTER = new Feature(
21+
'APPEND_GLOBAL_FILTER',
22+
0,
23+
'Enabling this places the global filter at the end of the task description. Some plugins, such as Day Planner,\n' +
24+
'might require this, or you might prefer how it looks. If you change this when tasks are modified using the\n' +
25+
'Task edit box they will have the tag moved to the beginning or end of the description.',
26+
'Creates / Supports tasks with the global filter at end',
27+
false,
28+
false,
29+
);
30+
2031
static get values(): Feature[] {
21-
return [this.TASK_STATUS_MENU];
32+
return [this.TASK_STATUS_MENU, this.TASK_STATUS_MENU];
2233
}
2334

2435
static get settingsFlags(): FeatureFlag {

β€Žsrc/Task.ts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import type { Status } from './Status';
55
import { replaceTaskWithTasks } from './File';
66
import { LayoutOptions } from './LayoutOptions';
77
import { Recurrence } from './Recurrence';
8-
import { getSettings } from './Settings';
8+
import { getSettings, isFeatureEnabled } from './Settings';
99
import { Urgency } from './Urgency';
10+
import { Feature } from './Feature';
1011

1112
/**
1213
* When sorting, make sure low always comes after none. This way any tasks with low will be below any exiting
@@ -180,7 +181,14 @@ export class Task {
180181
return null;
181182
}
182183

183-
let description = body;
184+
// Global filter is applied via edit or to string and no
185+
// longer needs to be on the description. If this happens
186+
// there may be a double space. So all double spaces are made
187+
// single like the UI processing.
188+
let description = body
189+
.replace(globalFilter, '')
190+
.replace(' ', ' ')
191+
.trim();
184192
const indentation = regexMatch[1];
185193

186194
// Get the status of the task.
@@ -356,6 +364,8 @@ export class Task {
356364
}): Promise<HTMLLIElement> {
357365
let taskAsString = this.toString(layoutOptions);
358366
const { globalFilter, removeGlobalFilter } = getSettings();
367+
368+
// Hide the global filter when rendering the query results.
359369
if (removeGlobalFilter) {
360370
taskAsString = taskAsString.replace(globalFilter, '').trim();
361371
}
@@ -439,15 +449,25 @@ export class Task {
439449
}
440450

441451
/**
442-
*
452+
* Returns a string representation of the task. This is the entire body after the
453+
* markdown task prefix. ( - [ ] )
443454
*
444455
* @param {LayoutOptions} [layoutOptions]
445456
* @return {*} {string}
446457
* @memberof Task
447458
*/
448459
public toString(layoutOptions?: LayoutOptions): string {
449460
layoutOptions = layoutOptions ?? new LayoutOptions();
450-
let taskString = this.description;
461+
462+
let taskString = this.description.trim();
463+
const { globalFilter } = getSettings();
464+
465+
if (isFeatureEnabled(Feature.APPEND_GLOBAL_FILTER.internalName)) {
466+
taskString = `${taskString} ${globalFilter}`.trim();
467+
} else {
468+
// Default is to have filter at front.
469+
taskString = `${globalFilter} ${taskString}`.trim();
470+
}
451471

452472
if (!layoutOptions.hidePriority) {
453473
let priority: string = '';
@@ -513,7 +533,7 @@ export class Task {
513533
public toFileLineString(): string {
514534
return `${this.indentation}- [${
515535
this.status.indicator
516-
}] ${this.toString()}`;
536+
}] ${this.toString().trim()}`;
517537
}
518538

519539
/**

β€Žsrc/ui/EditTask.svelte

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
import { Status } from '../Status';
44
import { onMount } from 'svelte';
55
import { Recurrence } from '../Recurrence';
6-
import { getSettings } from '../Settings';
6+
import { getSettings, isFeatureEnabled } from '../Settings';
77
import { Priority, Task } from '../Task';
88
import { StatusRegistry } from '../StatusRegistry';
9+
import { Feature } from 'Feature';
910
1011
export let task: Task;
1112
export let onSubmit: (updatedTasks: Task[]) => void | Promise<void>;
@@ -158,9 +159,17 @@
158159
159160
const _onSubmit = () => {
160161
const { globalFilter } = getSettings();
162+
161163
let description = editableTask.description.trim();
164+
165+
// Check to see if the global filter was added by user.
162166
if (!description.includes(globalFilter)) {
163-
description = globalFilter + ' ' + description;
167+
if (isFeatureEnabled(Feature.APPEND_GLOBAL_FILTER.internalName)) {
168+
description = `${description} ${globalFilter}`;
169+
} else {
170+
// Default is to have filter at front.
171+
description = `${globalFilter} ${description}`;
172+
}
164173
}
165174
166175
let startDate: moment.Moment | null = null;

β€Žtests/Task.test.ts

Lines changed: 85 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
import moment from 'moment';
55
import { Status } from '../src/Status';
66
import { Task } from '../src/Task';
7-
import { getSettings, updateSettings } from '../src/Settings';
7+
import { getSettings, toggleFeature, updateSettings } from '../src/Settings';
8+
import { Feature } from '../src/Feature';
89

910
jest.mock('obsidian');
1011
window.moment = moment;
@@ -192,40 +193,36 @@ describe('parsing tags', () => {
192193
{
193194
markdownTask:
194195
'- [x] #someglobaltasktag this is a done task #tagone πŸ—“ 2021-09-12 βœ… 2021-06-20',
195-
expectedDescription:
196-
'#someglobaltasktag this is a done task #tagone',
196+
expectedDescription: 'this is a done task #tagone',
197197
extractedTags: ['#tagone'],
198198
globalFilter: '#someglobaltasktag',
199199
},
200200
{
201201
markdownTask:
202202
'- [x] #someglobaltasktag this is a done task #tagone #tagtwo πŸ—“ 2021-09-12 βœ… 2021-06-20',
203-
expectedDescription:
204-
'#someglobaltasktag this is a done task #tagone #tagtwo',
203+
expectedDescription: 'this is a done task #tagone #tagtwo',
205204
extractedTags: ['#tagone', '#tagtwo'],
206205
globalFilter: '#someglobaltasktag',
207206
},
208207
{
209208
markdownTask:
210209
'- [ ] #someglobaltasktag this is a normal task #tagone πŸ—“ 2021-09-12 βœ… 2021-06-20',
211-
expectedDescription:
212-
'#someglobaltasktag this is a normal task #tagone',
210+
expectedDescription: 'this is a normal task #tagone',
213211
extractedTags: ['#tagone'],
214212
globalFilter: '#someglobaltasktag',
215213
},
216214
{
217215
markdownTask:
218216
'- [ ] #someglobaltasktag this is a normal task #tagone #tagtwo πŸ—“ 2021-09-12 βœ… 2021-06-20',
219-
expectedDescription:
220-
'#someglobaltasktag this is a normal task #tagone #tagtwo',
217+
expectedDescription: 'this is a normal task #tagone #tagtwo',
221218
extractedTags: ['#tagone', '#tagtwo'],
222219
globalFilter: '#someglobaltasktag',
223220
},
224221
{
225222
markdownTask:
226223
'- [ ] #someglobaltasktag this is a normal task #tagone #tag/with/depth #tagtwo πŸ—“ 2021-09-12 βœ… 2021-06-20',
227224
expectedDescription:
228-
'#someglobaltasktag this is a normal task #tagone #tag/with/depth #tagtwo',
225+
'this is a normal task #tagone #tag/with/depth #tagtwo',
229226
extractedTags: ['#tagone', '#tag/with/depth', '#tagtwo'],
230227
globalFilter: '#someglobaltasktag',
231228
},
@@ -275,6 +272,13 @@ describe('parsing tags', () => {
275272
);
276273
});
277274

275+
type GlobalFilterParsingExpectations = {
276+
location: string;
277+
scenario: string;
278+
initialTask: string;
279+
expectedTask: string;
280+
};
281+
278282
describe('to string', () => {
279283
it('retains the block link', () => {
280284
// Arrange
@@ -311,6 +315,77 @@ describe('to string', () => {
311315
// Assert
312316
expect(task.toFileLineString()).toStrictEqual(line);
313317
});
318+
319+
test.each<GlobalFilterParsingExpectations>([
320+
{
321+
location: 'append',
322+
scenario: 'at front',
323+
initialTask:
324+
'- [x] #globalfilter this is a done task #tagone #journal/daily πŸ“… 2021-09-12 βœ… 2021-06-20',
325+
expectedTask:
326+
'- [x] this is a done task #tagone #journal/daily #globalfilter πŸ“… 2021-09-12 βœ… 2021-06-20',
327+
},
328+
{
329+
location: 'append',
330+
scenario: 'at end',
331+
initialTask:
332+
'- [x] this is a done task #tagone #journal/daily #globalfilter πŸ“… 2021-09-12 βœ… 2021-06-20',
333+
expectedTask:
334+
'- [x] this is a done task #tagone #journal/daily #globalfilter πŸ“… 2021-09-12 βœ… 2021-06-20',
335+
},
336+
{
337+
location: 'append',
338+
scenario: 'in middle',
339+
initialTask:
340+
'- [x] this is a done task #globalfilter #tagone #journal/daily πŸ“… 2021-09-12 βœ… 2021-06-20',
341+
expectedTask:
342+
'- [x] this is a done task #tagone #journal/daily #globalfilter πŸ“… 2021-09-12 βœ… 2021-06-20',
343+
},
344+
{
345+
location: 'prepend',
346+
scenario: 'at front',
347+
initialTask:
348+
'- [x] #globalfilter this is a done task #tagone #journal/daily πŸ“… 2021-09-12 βœ… 2021-06-20',
349+
expectedTask:
350+
'- [x] #globalfilter this is a done task #tagone #journal/daily πŸ“… 2021-09-12 βœ… 2021-06-20',
351+
},
352+
{
353+
location: 'prepend',
354+
scenario: 'at end',
355+
initialTask:
356+
'- [x] this is a done task #tagone #journal/daily #globalfilter πŸ“… 2021-09-12 βœ… 2021-06-20',
357+
expectedTask:
358+
'- [x] #globalfilter this is a done task #tagone #journal/daily πŸ“… 2021-09-12 βœ… 2021-06-20',
359+
},
360+
{
361+
location: 'prepend',
362+
scenario: 'in middle',
363+
initialTask:
364+
'- [x] this is a done task #globalfilter #tagone #journal/daily πŸ“… 2021-09-12 βœ… 2021-06-20',
365+
expectedTask:
366+
'- [x] #globalfilter this is a done task #tagone #journal/daily πŸ“… 2021-09-12 βœ… 2021-06-20',
367+
},
368+
])(
369+
'should $location global filter when $scenario',
370+
({ location, initialTask, expectedTask }) => {
371+
// Arrange
372+
const originalSettings = getSettings();
373+
updateSettings({ globalFilter: '#globalfilter' });
374+
if (location === 'append') {
375+
toggleFeature(Feature.APPEND_GLOBAL_FILTER.internalName, true);
376+
}
377+
// Act
378+
const task = constructTaskFromLine(initialTask);
379+
380+
// Assert
381+
expect(task).not.toBeNull();
382+
expect(task?.toFileLineString()).toStrictEqual(expectedTask);
383+
384+
// Cleanup
385+
updateSettings(originalSettings);
386+
toggleFeature(Feature.APPEND_GLOBAL_FILTER.internalName, false);
387+
},
388+
);
314389
});
315390

316391
describe('toggle done', () => {

0 commit comments

Comments
Β (0)