diff --git a/main.ts b/main.ts index aaf275c..bcec360 100644 --- a/main.ts +++ b/main.ts @@ -5,6 +5,7 @@ import { TodoItem, TodoItemStatus } from './model/TodoItem'; import { TodoIndex } from './model/TodoIndex'; import { TodoPluginSettings, DEFAULT_SETTINGS } from './model/TodoPluginSettings'; import { SettingsTab } from './ui/SettingsTab'; +import { DateFormatter } from 'util/DateFormatter'; export default class TodoPlugin extends Plugin { private todoIndex: TodoIndex; @@ -23,6 +24,7 @@ export default class TodoPlugin extends Plugin { this.registerView(VIEW_TYPE_TODO, (leaf: WorkspaceLeaf) => { const todos: TodoItem[] = []; const props = { + dateFormatter: new DateFormatter(this.settings.dateFormat), todos: todos, openFile: (filePath: string) => { const file = this.app.vault.getAbstractFileByPath(filePath) as TFile; @@ -65,6 +67,12 @@ export default class TodoPlugin extends Plugin { async updateSettings(settings: TodoPluginSettings): Promise { this.settings = settings; + this.view.setProps((currentProps: TodoItemViewProps) => { + return { + ...currentProps, + dateFormatter: new DateFormatter(this.settings.dateFormat), + }; + }); await this.saveData(this.settings); this.todoIndex.setSettings(settings); } diff --git a/styles.css b/styles.css index bc23372..514415c 100644 --- a/styles.css +++ b/styles.css @@ -33,6 +33,18 @@ div.todo-item-view-item p { margin: 0; } +div.todo-item-view-item span.due-date { + padding: 5px 8px 5px 8px; + background-color: #fbb034; + font-size: 0.6em; + border-color: #fbb034; + border-radius: 12px; +} + +div.todo-item-view-item span.due-date.overdue { + background-color: #ff2400; +} + div.todo-item-view-item-checkbox { flex-basis: 25px; flex-shrink: 0; diff --git a/ui/TodoItemView.ts b/ui/TodoItemView.ts index 33beaf5..f379b95 100644 --- a/ui/TodoItemView.ts +++ b/ui/TodoItemView.ts @@ -3,6 +3,7 @@ import { ItemView, MarkdownRenderer, WorkspaceLeaf } from 'obsidian'; import { VIEW_TYPE_TODO } from '../constants'; import { TodoItem, TodoItemStatus } from '../model/TodoItem'; import { RenderIcon, Icon } from '../ui/icons'; +import { DateFormatter } from '../util/DateFormatter'; enum TodoItemViewPane { Today, @@ -11,6 +12,7 @@ enum TodoItemViewPane { Someday, } export interface TodoItemViewProps { + dateFormatter: DateFormatter; todos: TodoItem[]; openFile: (filePath: string) => void; toggleTodo: (todo: TodoItem, newStatus: TodoItemStatus) => void; @@ -118,6 +120,14 @@ export class TodoItemView extends ItemView { }); el.createDiv('todo-item-view-item-description', (el) => { MarkdownRenderer.renderMarkdown(todo.description, el, todo.sourceFilePath, this); + if (todo.actionDate) { + el.createSpan('due-date', (el) => { + if (todo.actionDate.startOf('day') < DateTime.now().startOf('day')) { + el.classList.add('overdue'); + } + el.setText(this.props.dateFormatter.formatDate(todo.actionDate)); + }); + } }); el.createDiv('todo-item-view-item-link', (el) => { el.appendChild(RenderIcon(Icon.Reveal, 'Open file')); diff --git a/util/DateFormatter.test.ts b/util/DateFormatter.test.ts new file mode 100644 index 0000000..a10c16d --- /dev/null +++ b/util/DateFormatter.test.ts @@ -0,0 +1,11 @@ +import { DateTime } from 'luxon'; +import { DateFormatter } from './DateFormatter'; + +test('Formatting dates works', () => { + const firstDateFormatter = new DateFormatter('yyyy-MM-dd'); + const date = DateTime.fromISO('2021-12-29'); + expect(firstDateFormatter.formatDate(date)).toBe('2021-12-29'); + + const secondDateFormatter = new DateFormatter('yyyy LLL dd'); + expect(secondDateFormatter.formatDate(date)).toBe('2021 Dec 29'); +}); diff --git a/util/DateFormatter.ts b/util/DateFormatter.ts new file mode 100644 index 0000000..0e4914c --- /dev/null +++ b/util/DateFormatter.ts @@ -0,0 +1,13 @@ +import { DateTime } from 'luxon'; + +export class DateFormatter { + private dateFormat: string; + + constructor(dateFormat: string) { + this.dateFormat = dateFormat; + } + + public formatDate(date: DateTime): string { + return date.toFormat(this.dateFormat); + } +}