Skip to content

Commit f766fa7

Browse files
committed
merge
2 parents 3be8d8d + a6727bb commit f766fa7

File tree

5 files changed

+111
-22
lines changed

5 files changed

+111
-22
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ node_modules
1212
# They should be uploaded to GitHub releases instead.
1313
/main.js
1414

15+
# Exclude local settings
16+
data.json
17+
1518
# Exclude sourcemaps
1619
*.map
1720

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/settings.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
export const defaultSettings: SimpleTimeTrackerSettings = {
2-
timestampFormat: "YY-MM-DD hh:mm:ss",
2+
timestampFormat: "YY-MM-DD HH:mm:ss",
3+
editableTimestampFormat: "YYYY-MM-DD HH:mm:ss",
34
csvDelimiter: ",",
45
fineGrainedDurations: true
56
};
67

78
export interface SimpleTimeTrackerSettings {
89

910
timestampFormat: string;
11+
editableTimestampFormat: string;
1012
csvDelimiter: string;
1113
fineGrainedDurations: boolean;
1214

src/tracker.ts

+94-19
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export function loadTracker(json: string): Tracker {
4040
}
4141

4242
export function displayTracker(tracker: Tracker, element: HTMLElement, file: string, getSectionInfo: () => MarkdownSectionInformation, settings: SimpleTimeTrackerSettings): void {
43+
element.classList.add('simple-time-tracker-container');
4344
// add start/stop controls
4445
let running = isRunning(tracker);
4546
let btn = new ButtonComponent(element)
@@ -201,6 +202,14 @@ function formatTimestamp(timestamp: number, settings: SimpleTimeTrackerSettings)
201202
return moment.unix(timestamp).format(settings.timestampFormat);
202203
}
203204

205+
function formatEditableTimestamp(timestamp: number, settings: SimpleTimeTrackerSettings) {
206+
return moment.unix(timestamp).format(settings.editableTimestampFormat);
207+
}
208+
209+
function unformatEditableTimestamp(formatted: string, settings: SimpleTimeTrackerSettings): number {
210+
return moment(formatted, settings.editableTimestampFormat).unix();
211+
}
212+
204213
function formatDuration(totalTime: number, settings: SimpleTimeTrackerSettings): string {
205214
let ret = "";
206215
let duration = moment.duration(totalTime);
@@ -268,18 +277,85 @@ function createTableSection(entry: Entry, settings: SimpleTimeTrackerSettings):
268277
return ret;
269278
}
270279

280+
class EditableField {
281+
cell: HTMLTableCellElement;
282+
label: HTMLSpanElement;
283+
box: TextComponent;
284+
constructor(row: HTMLTableRowElement, indent: number, value: string) {
285+
this.cell = row.createEl("td");
286+
this.label = this.cell.createEl("span", { text: value });
287+
this.label.style.marginLeft = `${indent}em`;
288+
this.box = new TextComponent(this.cell).setValue(value);
289+
this.box.inputEl.classList.add('simple-time-tracker-input');
290+
this.box.inputEl.hide();
291+
}
292+
editing(): boolean {
293+
return this.label.hidden;
294+
}
295+
beginEdit(value: string) {
296+
this.label.hidden = true;
297+
this.box.setValue(value);
298+
this.box.inputEl.show();
299+
}
300+
endEdit(): string {
301+
const value = this.box.getValue();
302+
this.label.setText(value);
303+
this.box.inputEl.hide();
304+
this.label.hidden = false;
305+
return value;
306+
}
307+
}
308+
309+
class EditableTimestampField extends EditableField {
310+
settings: SimpleTimeTrackerSettings;
311+
constructor(row: HTMLTableRowElement, indent: number, value: string, settings: SimpleTimeTrackerSettings) {
312+
if (value) {
313+
const timestamp = Number(value);
314+
value = timestamp > 0 ? formatTimestamp(timestamp, settings) : "";
315+
}
316+
super(row, indent, value);
317+
this.settings = settings;
318+
}
319+
beginEdit(value: string) {
320+
if (value) {
321+
value = formatEditableTimestamp(Number(value), this.settings);
322+
}
323+
super.beginEdit(value);
324+
}
325+
endEdit(): string {
326+
const value = this.box.getValue();
327+
let displayValue = value;
328+
if (value) {
329+
const timestamp = unformatEditableTimestamp(value, this.settings);
330+
displayValue = formatTimestamp(timestamp, this.settings);
331+
}
332+
this.label.setText(displayValue);
333+
this.box.inputEl.hide();
334+
this.label.hidden = false;
335+
return value;
336+
}
337+
getTimestamp(): number {
338+
if (this.box.getValue()) {
339+
return unformatEditableTimestamp(this.box.getValue(), this.settings);
340+
} else {
341+
return null;
342+
}
343+
}
344+
}
345+
346+
function nullableNumberToString(value: number) {
347+
if (value == null) return '';
348+
return String(value);
349+
}
350+
271351
function addEditableTableRow(tracker: Tracker, entry: Entry, table: HTMLTableElement, newSegmentNameBox: TextComponent, running: boolean, file: string, getSectionInfo: () => MarkdownSectionInformation, settings: SimpleTimeTrackerSettings, indent: number) {
272352
let row = table.createEl("tr");
273353

274-
let name = row.createEl("td");
275-
let namePar = name.createEl("span", {text: entry.name});
276-
namePar.style.marginLeft = `${indent}em`;
277-
let nameBox = new TextComponent(name).setValue(entry.name);
278-
nameBox.inputEl.hidden = true;
354+
let nameField = new EditableField(row, indent, entry.name);
355+
let startField = new EditableTimestampField(row, indent, nullableNumberToString(entry.startTime), settings);
356+
let endField = new EditableTimestampField(row, indent, nullableNumberToString(entry.endTime), settings);
279357

280-
row.createEl("td", {text: entry.startTime ? formatTimestamp(entry.startTime, settings) : ""});
281-
row.createEl("td", {text: entry.endTime ? formatTimestamp(entry.endTime, settings) : ""});
282-
row.createEl("td", {text: entry.endTime || entry.subEntries ? formatDuration(getDuration(entry), settings) : ""});
358+
row.createEl("td", { text: entry.endTime || entry.subEntries ? formatDuration(getDuration(entry), settings) : "" });
283359

284360
let entryButtons = row.createEl("td");
285361
if (!running) {
@@ -297,19 +373,18 @@ function addEditableTableRow(tracker: Tracker, entry: Entry, table: HTMLTableEle
297373
.setTooltip("Edit")
298374
.setIcon("lucide-pencil")
299375
.onClick(async () => {
300-
if (namePar.hidden) {
301-
namePar.hidden = false;
302-
nameBox.inputEl.hidden = true;
376+
if (nameField.editing()) {
377+
entry.name = nameField.endEdit();
378+
startField.endEdit();
379+
entry.startTime = startField.getTimestamp();
380+
endField.endEdit();
381+
entry.endTime = endField.getTimestamp();
382+
await saveTracker(tracker, this.app, file, getSectionInfo());
303383
editButton.setIcon("lucide-pencil");
304-
if (nameBox.getValue()) {
305-
entry.name = nameBox.getValue();
306-
namePar.setText(entry.name);
307-
await saveTracker(tracker, this.app, file, getSectionInfo());
308-
}
309384
} else {
310-
namePar.hidden = true;
311-
nameBox.inputEl.hidden = false;
312-
nameBox.setValue(entry.name);
385+
nameField.beginEdit(entry.name);
386+
startField.beginEdit(nullableNumberToString(entry.startTime));
387+
endField.beginEdit(nullableNumberToString(entry.endTime));
313388
editButton.setIcon("lucide-check");
314389
}
315390
});

styles.css

+9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
.simple-time-tracker-container {
2+
overflow-x: scroll;
3+
}
4+
15
.simple-time-tracker-support {
26
max-width: 50%;
37
width: 400px;
@@ -62,3 +66,8 @@
6266
.simple-time-tracker-table .clickable-icon {
6367
display: inline;
6468
}
69+
70+
.simple-time-tracker-input {
71+
max-width: 150px;
72+
min-width: 100px;
73+
}

0 commit comments

Comments
 (0)