Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: Ellpeck/ObsidianSimpleTimeTracker
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1.0.1
Choose a base ref
...
head repository: Ellpeck/ObsidianSimpleTimeTracker
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
  • 7 commits
  • 13 files changed
  • 4 contributors

Commits on Aug 9, 2024

  1. moved around async code

    Ellpeck committed Aug 9, 2024
    Copy the full SHA
    321f017 View commit details
  2. 1.0.2

    Ellpeck committed Aug 9, 2024
    Copy the full SHA
    ea4f51b View commit details
  3. Copy the full SHA
    7b189a4 View commit details
  4. 1.0.3

    Ellpeck committed Aug 9, 2024
    1
    Copy the full SHA
    993a7a4 View commit details

Commits on Sep 2, 2024

  1. added funding url

    Ellpeck authored Sep 2, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    7033f28 View commit details

Commits on Nov 14, 2024

  1. updated screenshot link and image to reflect current plugin version (#66

    )
    
    * [fix] updated screenshot link and image to reflect current plugin version #62
    
    replaced outdated screenshot.png with an updated screenshot.jpg showcasing the latest plugin interface. updated the readme to link to the new image, fixing the broken link and ensuring the documentation reflects the current version of the plugin.
    
    * [fix] updated screenshot link in readme.md
    
    replaced the link of screenshot with an absolute link, so the image will be displayed correctly in obsidian plugin store.
    
    ---------
    
    Co-authored-by: Philipp Dalheimer <[email protected]>
    Karamellwuerfel and Philipp Dalheimer authored Nov 14, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    3dc0857 View commit details

Commits on Nov 15, 2024

  1. add total today (#64)

    * add total today
    
    * not change format semicolons
    
    * Add settings for show total today
    henriwasd authored Nov 15, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    1831b25 View commit details
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Super Simple Time Tracker
Multi-purpose time trackers for your notes!

![A screenshot of the plugin in action, where you can see an active time tracker for a project](https://raw.githubusercontent.com/Ellpeck/ObsidianSimpleTimeTracker/master/screenshot.png)
![A screenshot of the plugin in action, where you can see an active time tracker for a project](https://raw.githubusercontent.com/Ellpeck/ObsidianSimpleTimeTracker/master/screenshot.jpg)

# 🤔 Usage
To get started tracking your time with Super Simple Time Tracker, open up the note that you want to track your time in. Move the cursor to the area you want the tracker to reside in, and then open your command palette and execute the `Super Simple Time Tracker: Insert Time Tracker` command.
3 changes: 2 additions & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
"id": "simple-time-tracker",
"name": "Super Simple Time Tracker",
"version": "1.0.1",
"version": "1.0.3",
"minAppVersion": "1.2.8",
"description": "Multi-purpose time trackers for your notes!",
"author": "Ellpeck",
"authorUrl": "https://ellpeck.de",
"fundingUrl": "https://ellpeck.de/support",
"isDesktopOnly": false
}
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "simple-time-tracker",
"version": "1.0.1",
"version": "1.0.3",
"description": "Multi-purpose time trackers for your notes!",
"main": "main.js",
"scripts": {
Binary file added screenshot.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed screenshot.png
Binary file not shown.
8 changes: 4 additions & 4 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { MarkdownRenderChild, Plugin, TFile } from "obsidian";
import { defaultSettings, SimpleTimeTrackerSettings } from "./settings";
import { SimpleTimeTrackerSettingsTab } from "./settings-tab";
import { displayTracker, Entry, formatDuration, formatTimestamp, getDuration, getRunningEntry, getTotalDuration, isRunning, loadAllTrackers, loadTracker, orderedEntries } from "./tracker";
import { displayTracker, Entry, formatDuration, formatTimestamp, getDuration, getDurationToday, getRunningEntry, getTotalDuration, getTotalDurationToday, isRunning, loadAllTrackers, loadTracker, orderedEntries } from "./tracker";

export default class SimpleTimeTrackerPlugin extends Plugin {

public api = {
// verbatim versions of the functions found in tracker.ts with the same parameters
loadTracker, loadAllTrackers, getDuration, getTotalDuration, getRunningEntry, isRunning,
loadTracker, loadAllTrackers, getDuration, getTotalDuration, getDurationToday, getTotalDurationToday, getRunningEntry, isRunning,

// modified versions of the functions found in tracker.ts, with the number of required arguments reduced
formatTimestamp: (timestamp: string) => formatTimestamp(timestamp, this.settings),
@@ -21,7 +21,7 @@ export default class SimpleTimeTrackerPlugin extends Plugin {

this.addSettingTab(new SimpleTimeTrackerSettingsTab(this.app, this));

this.registerMarkdownCodeBlockProcessor("simple-time-tracker", async (s, e, i) => {
this.registerMarkdownCodeBlockProcessor("simple-time-tracker", (s, e, i) => {
e.empty();
let component = new MarkdownRenderChild(e);
let tracker = loadTracker(s);
@@ -37,7 +37,7 @@ export default class SimpleTimeTrackerPlugin extends Plugin {
}
}));

await displayTracker(tracker, e, getFile, () => i.getSectionInfo(e), this.settings, component);
displayTracker(tracker, e, getFile, () => i.getSectionInfo(e), this.settings, component);
i.addChild(component);
});

23 changes: 17 additions & 6 deletions src/settings-tab.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {App, PluginSettingTab, Setting} from "obsidian";
import { App, PluginSettingTab, Setting } from "obsidian";
import SimpleTimeTrackerPlugin from "./main";
import {defaultSettings} from "./settings";
import { defaultSettings } from "./settings";

export class SimpleTimeTrackerSettingsTab extends PluginSettingTab {

@@ -13,14 +13,14 @@ export class SimpleTimeTrackerSettingsTab extends PluginSettingTab {

display(): void {
this.containerEl.empty();
this.containerEl.createEl("h2", {text: "Super Simple Time Tracker Settings"});
this.containerEl.createEl("h2", { text: "Super Simple Time Tracker Settings" });

new Setting(this.containerEl)
.setName("Timestamp Display Format")
.setDesc(createFragment(f => {
f.createSpan({text: "The way that timestamps in time tracker tables should be displayed. Uses "});
f.createEl("a", {text: "moment.js", href: "https://momentjs.com/docs/#/parsing/string-format/"});
f.createSpan({text: " syntax."});
f.createSpan({ text: "The way that timestamps in time tracker tables should be displayed. Uses " });
f.createEl("a", { text: "moment.js", href: "https://momentjs.com/docs/#/parsing/string-format/" });
f.createSpan({ text: " syntax." });
}))
.addText(t => {
t.setValue(String(this.plugin.settings.timestampFormat));
@@ -74,6 +74,17 @@ export class SimpleTimeTrackerSettingsTab extends PluginSettingTab {
});
});

new Setting(this.containerEl)
.setName('Show Total Today')
.setDesc('Whether the total time spent today should be displayed in the tracker table.')
.addToggle(t => {
t.setValue(this.plugin.settings.showToday);
t.onChange(async v => {
this.plugin.settings.showToday = v;
await this.plugin.saveSettings();
});
});

this.containerEl.createEl("hr");
this.containerEl.createEl("p", { text: "Need help using the plugin? Feel free to join the Discord server!" });
this.containerEl.createEl("a", { href: "https://link.ellpeck.de/discordweb" }).createEl("img", {
5 changes: 3 additions & 2 deletions src/settings.ts
Original file line number Diff line number Diff line change
@@ -4,7 +4,8 @@ export const defaultSettings: SimpleTimeTrackerSettings = {
csvDelimiter: ",",
fineGrainedDurations: true,
reverseSegmentOrder: false,
timestampDurations: false
timestampDurations: false,
showToday: false,
};

export interface SimpleTimeTrackerSettings {
@@ -15,5 +16,5 @@ export interface SimpleTimeTrackerSettings {
fineGrainedDurations: boolean;
reverseSegmentOrder: boolean;
timestampDurations: boolean;

showToday: boolean;
}
50 changes: 42 additions & 8 deletions src/tracker.ts
Original file line number Diff line number Diff line change
@@ -69,7 +69,7 @@ export async function loadAllTrackers(fileName: string): Promise<{ section: Mark

type GetFile = () => string;

export async function displayTracker(tracker: Tracker, element: HTMLElement, getFile: GetFile, getSectionInfo: () => MarkdownSectionInformation, settings: SimpleTimeTrackerSettings, component: MarkdownRenderChild): Promise<void> {
export function displayTracker(tracker: Tracker, element: HTMLElement, getFile: GetFile, getSectionInfo: () => MarkdownSectionInformation, settings: SimpleTimeTrackerSettings, component: MarkdownRenderChild): void {

element.addClass("simple-time-tracker-container");
// add start/stop controls
@@ -101,6 +101,12 @@ export async function displayTracker(tracker: Tracker, element: HTMLElement, get
let total = totalDiv.createEl("span", { cls: "simple-time-tracker-timer-time", text: "0s" });
totalDiv.createEl("span", { text: "Total" });

if (settings.showToday) {
let totalTodayDiv = timer.createEl("div", { cls: "simple-time-tracker-timer" })
let totalToday = totalTodayDiv.createEl("span", { cls: "simple-time-tracker-timer-time", text: "0s" })
totalTodayDiv.createEl("span", { text: "Today" })
}

if (tracker.entries.length > 0) {
// add table
let table = element.createEl("table", { cls: "simple-time-tracker-table" });
@@ -112,7 +118,7 @@ export async function displayTracker(tracker: Tracker, element: HTMLElement, get
createEl("th"));

for (let entry of orderedEntries(tracker.entries, settings))
await addEditableTableRow(tracker, entry, table, newSegmentNameBox, running, getFile, getSectionInfo, settings, 0, component);
addEditableTableRow(tracker, entry, table, newSegmentNameBox, running, getFile, getSectionInfo, settings, 0, component);

// add copy buttons
let buttons = element.createEl("div", { cls: "simple-time-tracker-bottom" });
@@ -145,13 +151,40 @@ export function getDuration(entry: Entry): number {
}
}

export function getDurationToday(entry: Entry): number {
if (entry.subEntries) {
return getTotalDurationToday(entry.subEntries)
} else {
let today = moment().startOf('day')
let endTime = entry.endTime ? moment(entry.endTime) : moment()
let startTime = moment(entry.startTime)

if (endTime.isBefore(today)) {
return 0
}

if (startTime.isBefore(today)) {
startTime = today
}

return endTime.diff(startTime)
}
}

export function getTotalDuration(entries: Entry[]): number {
let ret = 0;
for (let entry of entries)
ret += getDuration(entry);
return ret;
}

export function getTotalDurationToday(entries: Entry[]): number {
let ret = 0
for (let entry of entries)
ret += getDurationToday(entry)
return ret
}

export function isRunning(tracker: Tracker): boolean {
return !!getRunningEntry(tracker.entries);
}
@@ -339,7 +372,7 @@ function createTableSection(entry: Entry, settings: SimpleTimeTrackerSettings):
return ret;
}

async function addEditableTableRow(tracker: Tracker, entry: Entry, table: HTMLTableElement, newSegmentNameBox: TextComponent, trackerRunning: boolean, getFile: GetFile, getSectionInfo: () => MarkdownSectionInformation, settings: SimpleTimeTrackerSettings, indent: number, component: MarkdownRenderChild): Promise<void> {
function addEditableTableRow(tracker: Tracker, entry: Entry, table: HTMLTableElement, newSegmentNameBox: TextComponent, trackerRunning: boolean, getFile: GetFile, getSectionInfo: () => MarkdownSectionInformation, settings: SimpleTimeTrackerSettings, indent: number, component: MarkdownRenderChild): void {
let entryRunning = getRunningEntry(tracker.entries) == entry;
let row = table.createEl("tr");

@@ -349,7 +382,7 @@ async function addEditableTableRow(tracker: Tracker, entry: Entry, table: HTMLTa

row.createEl("td", { text: entry.endTime || entry.subEntries ? formatDuration(getDuration(entry), settings) : "" });

await renderNameAsMarkdown(nameField.label, getFile, component);
renderNameAsMarkdown(nameField.label, getFile, component);

let expandButton = new ButtonComponent(nameField.label)
.setClass("clickable-icon")
@@ -394,7 +427,7 @@ async function addEditableTableRow(tracker: Tracker, entry: Entry, table: HTMLTa
await saveTracker(tracker, getFile(), getSectionInfo());
editButton.setIcon("lucide-pencil");

await renderNameAsMarkdown(nameField.label, getFile, component);
renderNameAsMarkdown(nameField.label, getFile, component);
} else {
nameField.beginEdit(entry.name);
expandButton.buttonEl.style.display = "none";
@@ -426,7 +459,7 @@ async function addEditableTableRow(tracker: Tracker, entry: Entry, table: HTMLTa

if (entry.subEntries && !entry.collapsed) {
for (let sub of orderedEntries(entry.subEntries, settings))
await addEditableTableRow(tracker, sub, table, newSegmentNameBox, trackerRunning, getFile, getSectionInfo, settings, indent + 1, component);
addEditableTableRow(tracker, sub, table, newSegmentNameBox, trackerRunning, getFile, getSectionInfo, settings, indent + 1, component);
}
}

@@ -437,8 +470,9 @@ function showConfirm(message: string): Promise<boolean> {
});
}

async function renderNameAsMarkdown(label: HTMLSpanElement, getFile: GetFile, component: Component): Promise<void> {
await MarkdownRenderer.renderMarkdown(label.innerHTML, label, getFile(), component);
function renderNameAsMarkdown(label: HTMLSpanElement, getFile: GetFile, component: Component): void {
// we don't have to wait here since async code only occurs when a file needs to be loaded (like a linked image)
void MarkdownRenderer.renderMarkdown(label.innerHTML, label, getFile(), component);
// rendering wraps it in a paragraph
label.innerHTML = label.querySelector("p").innerHTML;
}
3 changes: 2 additions & 1 deletion test-vault/.obsidian/plugins/simple-time-tracker/data.json
Original file line number Diff line number Diff line change
@@ -4,5 +4,6 @@
"csvDelimiter": ",",
"fineGrainedDurations": true,
"reverseSegmentOrder": false,
"timestampDurations": true
"timestampDurations": true,
"showToday": true
}
2 changes: 1 addition & 1 deletion test-vault/test-markdown.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Tested for #tag, *italic*, [link](test2), etc:
```simple-time-tracker
{"entries":[{"name":"`Segment 1`","startTime":"2022-09-27T19:51:18.000Z","endTime":"2022-09-27T19:51:24.000Z"},{"name":"Segment 2","startTime":"2022-09-27T19:51:25.000Z","endTime":"2022-09-27T19:51:26.000Z"},{"name":"#tag Seqment 3 *add* #tag1 text","startTime":null,"endTime":null,"subEntries":[{"name":"Part 1 #tagp1","startTime":"2024-03-17T11:16:00.382Z","endTime":"2024-03-17T11:16:15.966Z","subEntries":null},{"name":"Part 3","startTime":"2024-03-17T11:17:08.000Z","endTime":"2024-03-17T11:17:24.000Z","subEntries":null}],"collapsed":true},{"name":"#tag3 Segment 4","startTime":null,"endTime":null,"subEntries":[{"name":"Part 1 #tag4","startTime":"2024-03-17T12:22:04.000Z","endTime":"2024-03-17T12:22:16.000Z","subEntries":null},{"name":"#tag5 Part 2 *italic*","startTime":"2024-03-17T12:22:20.000Z","endTime":"2024-03-17T12:22:24.000Z","subEntries":null}],"collapsed":true},{"name":"*italic* Segment 5 #tag6 [test2](test2)","startTime":"2024-03-17T12:40:37.000Z","endTime":"2024-03-17T12:40:45.000Z","subEntries":null},{"name":"Segment 6","startTime":"2024-03-27T13:20:56.000Z","endTime":"2024-08-09T16:27:18.029Z","subEntries":null}]}
{"entries":[{"name":"`Segment 1`","startTime":"2022-09-27T19:51:18.000Z","endTime":"2022-09-27T19:51:24.000Z"},{"name":"Segment 2","startTime":"2022-09-27T19:51:25.000Z","endTime":"2022-09-27T19:51:26.000Z"},{"name":"#tag Seqment 3 *add* #tag1 text","startTime":null,"endTime":null,"subEntries":[{"name":"Part 1 #tagp1","startTime":"2024-03-17T11:16:00.382Z","endTime":"2024-03-17T11:16:15.966Z"},{"name":"Part 3","startTime":"2024-03-17T11:17:08.000Z","endTime":"2024-03-17T11:17:24.000Z"}]},{"name":"#tag3 Segment 4","startTime":null,"endTime":null,"subEntries":[{"name":"Part 1 #tag4","startTime":"2024-03-17T12:22:04.000Z","endTime":"2024-03-17T12:22:16.000Z"},{"name":"#tag5 Part 2 *italic*","startTime":"2024-03-17T12:22:20.000Z","endTime":"2024-03-17T12:22:24.000Z"}]},{"name":"*italic* Segment 5 #tag6 [test2](test2)","startTime":"2024-03-17T12:40:37.000Z","endTime":"2024-03-17T12:40:45.000Z"},{"name":"Segment 6","startTime":"2024-03-27T13:20:56.000Z","endTime":"2024-08-09T16:27:18.029Z"}]}
```

4 changes: 3 additions & 1 deletion versions.json
Original file line number Diff line number Diff line change
@@ -13,5 +13,7 @@
"0.2.1": "1.3.0",
"0.2.2": "1.3.0",
"1.0.0": "1.3.0",
"1.0.1": "1.3.0"
"1.0.1": "1.3.0",
"1.0.2": "1.3.0",
"1.0.3": "1.3.0"
}