mirror of
https://github.com/Ellpeck/ObsidianSimpleTimeTracker.git
synced 2024-12-04 14:08:35 +01:00
merge
This commit is contained in:
commit
f766fa7210
5 changed files with 111 additions and 22 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -12,6 +12,9 @@ node_modules
|
||||||
# They should be uploaded to GitHub releases instead.
|
# They should be uploaded to GitHub releases instead.
|
||||||
/main.js
|
/main.js
|
||||||
|
|
||||||
|
# Exclude local settings
|
||||||
|
data.json
|
||||||
|
|
||||||
# Exclude sourcemaps
|
# Exclude sourcemaps
|
||||||
*.map
|
*.map
|
||||||
|
|
||||||
|
|
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "simple-time-tracker",
|
"name": "simple-time-tracker",
|
||||||
"version": "0.1.6",
|
"version": "0.1.7",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "simple-time-tracker",
|
"name": "simple-time-tracker",
|
||||||
"version": "0.1.6",
|
"version": "0.1.7",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^16.11.6",
|
"@types/node": "^16.11.6",
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
export const defaultSettings: SimpleTimeTrackerSettings = {
|
export const defaultSettings: SimpleTimeTrackerSettings = {
|
||||||
timestampFormat: "YY-MM-DD hh:mm:ss",
|
timestampFormat: "YY-MM-DD HH:mm:ss",
|
||||||
|
editableTimestampFormat: "YYYY-MM-DD HH:mm:ss",
|
||||||
csvDelimiter: ",",
|
csvDelimiter: ",",
|
||||||
fineGrainedDurations: true
|
fineGrainedDurations: true
|
||||||
};
|
};
|
||||||
|
@ -7,6 +8,7 @@ export const defaultSettings: SimpleTimeTrackerSettings = {
|
||||||
export interface SimpleTimeTrackerSettings {
|
export interface SimpleTimeTrackerSettings {
|
||||||
|
|
||||||
timestampFormat: string;
|
timestampFormat: string;
|
||||||
|
editableTimestampFormat: string;
|
||||||
csvDelimiter: string;
|
csvDelimiter: string;
|
||||||
fineGrainedDurations: boolean;
|
fineGrainedDurations: boolean;
|
||||||
|
|
||||||
|
|
113
src/tracker.ts
113
src/tracker.ts
|
@ -40,6 +40,7 @@ export function loadTracker(json: string): Tracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function displayTracker(tracker: Tracker, element: HTMLElement, file: string, getSectionInfo: () => MarkdownSectionInformation, settings: SimpleTimeTrackerSettings): void {
|
export function displayTracker(tracker: Tracker, element: HTMLElement, file: string, getSectionInfo: () => MarkdownSectionInformation, settings: SimpleTimeTrackerSettings): void {
|
||||||
|
element.classList.add('simple-time-tracker-container');
|
||||||
// add start/stop controls
|
// add start/stop controls
|
||||||
let running = isRunning(tracker);
|
let running = isRunning(tracker);
|
||||||
let btn = new ButtonComponent(element)
|
let btn = new ButtonComponent(element)
|
||||||
|
@ -201,6 +202,14 @@ function formatTimestamp(timestamp: number, settings: SimpleTimeTrackerSettings)
|
||||||
return moment.unix(timestamp).format(settings.timestampFormat);
|
return moment.unix(timestamp).format(settings.timestampFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatEditableTimestamp(timestamp: number, settings: SimpleTimeTrackerSettings) {
|
||||||
|
return moment.unix(timestamp).format(settings.editableTimestampFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
function unformatEditableTimestamp(formatted: string, settings: SimpleTimeTrackerSettings): number {
|
||||||
|
return moment(formatted, settings.editableTimestampFormat).unix();
|
||||||
|
}
|
||||||
|
|
||||||
function formatDuration(totalTime: number, settings: SimpleTimeTrackerSettings): string {
|
function formatDuration(totalTime: number, settings: SimpleTimeTrackerSettings): string {
|
||||||
let ret = "";
|
let ret = "";
|
||||||
let duration = moment.duration(totalTime);
|
let duration = moment.duration(totalTime);
|
||||||
|
@ -268,18 +277,85 @@ function createTableSection(entry: Entry, settings: SimpleTimeTrackerSettings):
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class EditableField {
|
||||||
|
cell: HTMLTableCellElement;
|
||||||
|
label: HTMLSpanElement;
|
||||||
|
box: TextComponent;
|
||||||
|
constructor(row: HTMLTableRowElement, indent: number, value: string) {
|
||||||
|
this.cell = row.createEl("td");
|
||||||
|
this.label = this.cell.createEl("span", { text: value });
|
||||||
|
this.label.style.marginLeft = `${indent}em`;
|
||||||
|
this.box = new TextComponent(this.cell).setValue(value);
|
||||||
|
this.box.inputEl.classList.add('simple-time-tracker-input');
|
||||||
|
this.box.inputEl.hide();
|
||||||
|
}
|
||||||
|
editing(): boolean {
|
||||||
|
return this.label.hidden;
|
||||||
|
}
|
||||||
|
beginEdit(value: string) {
|
||||||
|
this.label.hidden = true;
|
||||||
|
this.box.setValue(value);
|
||||||
|
this.box.inputEl.show();
|
||||||
|
}
|
||||||
|
endEdit(): string {
|
||||||
|
const value = this.box.getValue();
|
||||||
|
this.label.setText(value);
|
||||||
|
this.box.inputEl.hide();
|
||||||
|
this.label.hidden = false;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EditableTimestampField extends EditableField {
|
||||||
|
settings: SimpleTimeTrackerSettings;
|
||||||
|
constructor(row: HTMLTableRowElement, indent: number, value: string, settings: SimpleTimeTrackerSettings) {
|
||||||
|
if (value) {
|
||||||
|
const timestamp = Number(value);
|
||||||
|
value = timestamp > 0 ? formatTimestamp(timestamp, settings) : "";
|
||||||
|
}
|
||||||
|
super(row, indent, value);
|
||||||
|
this.settings = settings;
|
||||||
|
}
|
||||||
|
beginEdit(value: string) {
|
||||||
|
if (value) {
|
||||||
|
value = formatEditableTimestamp(Number(value), this.settings);
|
||||||
|
}
|
||||||
|
super.beginEdit(value);
|
||||||
|
}
|
||||||
|
endEdit(): string {
|
||||||
|
const value = this.box.getValue();
|
||||||
|
let displayValue = value;
|
||||||
|
if (value) {
|
||||||
|
const timestamp = unformatEditableTimestamp(value, this.settings);
|
||||||
|
displayValue = formatTimestamp(timestamp, this.settings);
|
||||||
|
}
|
||||||
|
this.label.setText(displayValue);
|
||||||
|
this.box.inputEl.hide();
|
||||||
|
this.label.hidden = false;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
getTimestamp(): number {
|
||||||
|
if (this.box.getValue()) {
|
||||||
|
return unformatEditableTimestamp(this.box.getValue(), this.settings);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function nullableNumberToString(value: number) {
|
||||||
|
if (value == null) return '';
|
||||||
|
return String(value);
|
||||||
|
}
|
||||||
|
|
||||||
function addEditableTableRow(tracker: Tracker, entry: Entry, table: HTMLTableElement, newSegmentNameBox: TextComponent, running: boolean, file: string, getSectionInfo: () => MarkdownSectionInformation, settings: SimpleTimeTrackerSettings, indent: number) {
|
function addEditableTableRow(tracker: Tracker, entry: Entry, table: HTMLTableElement, newSegmentNameBox: TextComponent, running: boolean, file: string, getSectionInfo: () => MarkdownSectionInformation, settings: SimpleTimeTrackerSettings, indent: number) {
|
||||||
let row = table.createEl("tr");
|
let row = table.createEl("tr");
|
||||||
|
|
||||||
let name = row.createEl("td");
|
let nameField = new EditableField(row, indent, entry.name);
|
||||||
let namePar = name.createEl("span", {text: entry.name});
|
let startField = new EditableTimestampField(row, indent, nullableNumberToString(entry.startTime), settings);
|
||||||
namePar.style.marginLeft = `${indent}em`;
|
let endField = new EditableTimestampField(row, indent, nullableNumberToString(entry.endTime), settings);
|
||||||
let nameBox = new TextComponent(name).setValue(entry.name);
|
|
||||||
nameBox.inputEl.hidden = true;
|
|
||||||
|
|
||||||
row.createEl("td", {text: entry.startTime ? formatTimestamp(entry.startTime, settings) : ""});
|
row.createEl("td", { text: entry.endTime || entry.subEntries ? formatDuration(getDuration(entry), settings) : "" });
|
||||||
row.createEl("td", {text: entry.endTime ? formatTimestamp(entry.endTime, settings) : ""});
|
|
||||||
row.createEl("td", {text: entry.endTime || entry.subEntries ? formatDuration(getDuration(entry), settings) : ""});
|
|
||||||
|
|
||||||
let entryButtons = row.createEl("td");
|
let entryButtons = row.createEl("td");
|
||||||
if (!running) {
|
if (!running) {
|
||||||
|
@ -297,19 +373,18 @@ function addEditableTableRow(tracker: Tracker, entry: Entry, table: HTMLTableEle
|
||||||
.setTooltip("Edit")
|
.setTooltip("Edit")
|
||||||
.setIcon("lucide-pencil")
|
.setIcon("lucide-pencil")
|
||||||
.onClick(async () => {
|
.onClick(async () => {
|
||||||
if (namePar.hidden) {
|
if (nameField.editing()) {
|
||||||
namePar.hidden = false;
|
entry.name = nameField.endEdit();
|
||||||
nameBox.inputEl.hidden = true;
|
startField.endEdit();
|
||||||
editButton.setIcon("lucide-pencil");
|
entry.startTime = startField.getTimestamp();
|
||||||
if (nameBox.getValue()) {
|
endField.endEdit();
|
||||||
entry.name = nameBox.getValue();
|
entry.endTime = endField.getTimestamp();
|
||||||
namePar.setText(entry.name);
|
|
||||||
await saveTracker(tracker, this.app, file, getSectionInfo());
|
await saveTracker(tracker, this.app, file, getSectionInfo());
|
||||||
}
|
editButton.setIcon("lucide-pencil");
|
||||||
} else {
|
} else {
|
||||||
namePar.hidden = true;
|
nameField.beginEdit(entry.name);
|
||||||
nameBox.inputEl.hidden = false;
|
startField.beginEdit(nullableNumberToString(entry.startTime));
|
||||||
nameBox.setValue(entry.name);
|
endField.beginEdit(nullableNumberToString(entry.endTime));
|
||||||
editButton.setIcon("lucide-check");
|
editButton.setIcon("lucide-check");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
.simple-time-tracker-container {
|
||||||
|
overflow-x: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
.simple-time-tracker-support {
|
.simple-time-tracker-support {
|
||||||
max-width: 50%;
|
max-width: 50%;
|
||||||
width: 400px;
|
width: 400px;
|
||||||
|
@ -62,3 +66,8 @@
|
||||||
.simple-time-tracker-table .clickable-icon {
|
.simple-time-tracker-table .clickable-icon {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.simple-time-tracker-input {
|
||||||
|
max-width: 150px;
|
||||||
|
min-width: 100px;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue