mirror of
https://github.com/jacobtread/obsidian-timekeep.git
synced 2026-07-22 05:12:14 +00:00
refactor: replace uuid with incremental counters
This commit is contained in:
parent
fa1fedbb01
commit
36e14676dc
35 changed files with 256 additions and 187 deletions
|
|
@ -22,7 +22,6 @@
|
|||
"moment": "^2.30.1",
|
||||
"p-limit": "^7.3.0",
|
||||
"pdfmake": "^0.3.7",
|
||||
"uuid": "^11.0.5",
|
||||
"valibot": "^1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -20,9 +20,6 @@ importers:
|
|||
pdfmake:
|
||||
specifier: ^0.3.7
|
||||
version: 0.3.8
|
||||
uuid:
|
||||
specifier: ^11.0.5
|
||||
version: 11.1.1
|
||||
valibot:
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0(typescript@6.0.2)
|
||||
|
|
@ -927,10 +924,6 @@ packages:
|
|||
unicode-trie@2.0.0:
|
||||
resolution: {integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==}
|
||||
|
||||
uuid@11.1.1:
|
||||
resolution: {integrity: sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==}
|
||||
hasBin: true
|
||||
|
||||
valibot@1.4.0:
|
||||
resolution: {integrity: sha512-iC/x7fVcSyOwlm/VSt7RlHnzNGLGvR9GnxdifUeWoCJo0q4ZZvrVkIHC6faTlkxG47I2Y4UrFquPuVHCrOnrLg==}
|
||||
peerDependencies:
|
||||
|
|
@ -1756,8 +1749,6 @@ snapshots:
|
|||
pako: 0.2.9
|
||||
tiny-inflate: 1.0.3
|
||||
|
||||
uuid@11.1.1: {}
|
||||
|
||||
valibot@1.4.0(typescript@6.0.2):
|
||||
optionalDependencies:
|
||||
typescript: 6.0.2
|
||||
|
|
|
|||
31
src/__mocks__/setupMocks.ts
Normal file
31
src/__mocks__/setupMocks.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import { beforeEach, vi } from "vitest";
|
||||
|
||||
vi.mock(import("@/timekeep/id"), () => {
|
||||
const mockStore = () => {
|
||||
let nextId: number = 1;
|
||||
|
||||
function next() {
|
||||
const value = nextId;
|
||||
nextId++;
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
next: vi.fn().mockImplementation(next),
|
||||
};
|
||||
};
|
||||
|
||||
let timekeepId = mockStore();
|
||||
let timekeepMergerEntries = mockStore();
|
||||
|
||||
// Reset IDs for every test
|
||||
beforeEach(() => {
|
||||
timekeepId = mockStore();
|
||||
timekeepMergerEntries = mockStore();
|
||||
});
|
||||
|
||||
return {
|
||||
timekeepId,
|
||||
timekeepMergerEntries,
|
||||
};
|
||||
});
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
// @vitest-environment happy-dom
|
||||
|
||||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
import { describe, it, expect, vi, beforeEach, afterEach, assert } from "vitest";
|
||||
|
||||
import { createMockContainer } from "@/__mocks__/obsidian";
|
||||
|
|
@ -113,7 +112,7 @@ describe("TimesheetCounters", () => {
|
|||
timekeepStore.setState({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
@ -146,7 +145,7 @@ describe("TimesheetCounters", () => {
|
|||
entries: [
|
||||
// 1h elapsed entry
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
@ -154,7 +153,7 @@ describe("TimesheetCounters", () => {
|
|||
},
|
||||
// 2h entry
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Test",
|
||||
startTime: moment(start).subtract(1, "hour"),
|
||||
endTime: moment(oneHourLater),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import moment from "moment";
|
||||
import { App } from "obsidian";
|
||||
import { v4 } from "uuid";
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from "vitest";
|
||||
|
||||
import { createMockContainer, MockNotice } from "@/__mocks__/obsidian";
|
||||
|
|
@ -185,7 +184,7 @@ describe("TimesheetExportActions", () => {
|
|||
timekeep.setState({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(systemTime),
|
||||
endTime: null,
|
||||
|
|
@ -228,7 +227,7 @@ describe("TimesheetExportActions", () => {
|
|||
timekeep.setState({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(systemTime),
|
||||
endTime: moment(systemTime).add(1, "h"),
|
||||
|
|
@ -282,7 +281,7 @@ describe("TimesheetExportActions", () => {
|
|||
timekeep.setState({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(systemTime),
|
||||
endTime: moment(systemTime).add(1, "h"),
|
||||
|
|
@ -336,7 +335,7 @@ describe("TimesheetExportActions", () => {
|
|||
timekeep.setState({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(systemTime),
|
||||
endTime: moment(systemTime).add(1, "h"),
|
||||
|
|
@ -376,7 +375,7 @@ describe("TimesheetExportActions", () => {
|
|||
timekeep.setState({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(systemTime),
|
||||
endTime: moment(systemTime).add(1, "h"),
|
||||
|
|
@ -441,7 +440,7 @@ describe("TimesheetExportActions", () => {
|
|||
timekeep.setState({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(systemTime),
|
||||
endTime: moment(systemTime).add(1, "h"),
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
import type { App } from "obsidian";
|
||||
|
||||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { createMockContainer } from "@/__mocks__/obsidian";
|
||||
|
|
@ -25,7 +24,7 @@ describe("TimesheetRowContainer", () => {
|
|||
|
||||
const start = moment();
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import moment from "moment";
|
||||
import { App } from "obsidian";
|
||||
import { v4 } from "uuid";
|
||||
import { beforeEach, describe, expect, it, Mock, vi } from "vitest";
|
||||
|
||||
import { createMockContainer } from "@/__mocks__/obsidian";
|
||||
|
|
@ -17,7 +16,7 @@ describe("TimesheetRowContent", () => {
|
|||
const start = moment();
|
||||
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
@ -54,7 +53,7 @@ describe("TimesheetRowContent", () => {
|
|||
|
||||
it("folder row should have a folder icon", () => {
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
|
|
@ -79,7 +78,7 @@ describe("TimesheetRowContent", () => {
|
|||
|
||||
it("folder row or groups should be collapsible", () => {
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
|
|
@ -131,7 +130,7 @@ describe("TimesheetRowContent", () => {
|
|||
|
||||
it("folder row or groups should be expandable", () => {
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
|
|
@ -183,7 +182,7 @@ describe("TimesheetRowContent", () => {
|
|||
|
||||
it("item should be able to be started from clicking the start icon", () => {
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
import type { App } from "obsidian";
|
||||
|
||||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
import { beforeEach, it, describe, Mock, vi, expect, afterEach } from "vitest";
|
||||
|
||||
import type { TimekeepSettings } from "@/settings";
|
||||
|
|
@ -41,7 +40,7 @@ describe("TimesheetRowContentEditing", () => {
|
|||
const start = moment();
|
||||
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
@ -63,7 +62,7 @@ describe("TimesheetRowContentEditing", () => {
|
|||
const start = moment();
|
||||
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
@ -89,7 +88,7 @@ describe("TimesheetRowContentEditing", () => {
|
|||
const start = moment();
|
||||
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: moment(start),
|
||||
|
|
@ -122,7 +121,7 @@ describe("TimesheetRowContentEditing", () => {
|
|||
|
||||
it("clicking the save button on a group should update the timekeep state and call onFinishEditing", () => {
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
|
|
@ -155,7 +154,7 @@ describe("TimesheetRowContentEditing", () => {
|
|||
|
||||
it("clicking the save button on a unstarted entry should update the timekeep state and call onFinishEditing", () => {
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
|
|
@ -188,7 +187,7 @@ describe("TimesheetRowContentEditing", () => {
|
|||
|
||||
it("editing a group entry should hide the start and end time inputs", () => {
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
|
|
@ -218,7 +217,7 @@ describe("TimesheetRowContentEditing", () => {
|
|||
|
||||
it("clicking delete on an entry should open a modal for confirmation", () => {
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
|
|
@ -248,7 +247,7 @@ describe("TimesheetRowContentEditing", () => {
|
|||
|
||||
it("cancelling deletion should do nothing", () => {
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
|
|
@ -292,7 +291,7 @@ describe("TimesheetRowContentEditing", () => {
|
|||
|
||||
it("confirming deletion should remove the entry from the timekeep", () => {
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
|
|
@ -337,7 +336,7 @@ describe("TimesheetRowContentEditing", () => {
|
|||
it("editing a group entry should hide the start and end time inputs", () => {
|
||||
const start = moment();
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: moment(start),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// @vitest-environment happy-dom
|
||||
|
||||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
import { beforeEach, it, describe, expect, afterEach } from "vitest";
|
||||
|
||||
import type { TimekeepSettings } from "@/settings";
|
||||
|
|
@ -50,7 +49,7 @@ describe("TimesheetRunningEntry", () => {
|
|||
timekeep.setState({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
@ -70,7 +69,7 @@ describe("TimesheetRunningEntry", () => {
|
|||
timekeep.setState({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
@ -93,7 +92,7 @@ describe("TimesheetRunningEntry", () => {
|
|||
timekeep.setState({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
@ -120,7 +119,7 @@ describe("TimesheetRunningEntry", () => {
|
|||
timekeep.setState({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// @vitest-environment happy-dom
|
||||
|
||||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
import { beforeEach, it, describe, vi, expect } from "vitest";
|
||||
|
||||
import type { TimekeepSettings } from "@/settings";
|
||||
|
|
@ -65,7 +64,7 @@ describe("TimesheetRunningEntryEditing", () => {
|
|||
vi.setSystemTime(end.toDate());
|
||||
|
||||
const entry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// @vitest-environment happy-dom
|
||||
|
||||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
import { describe, it, vi, beforeEach, afterEach, expect } from "vitest";
|
||||
|
||||
import { createMockContainer } from "@/__mocks__/obsidian";
|
||||
|
|
@ -21,13 +20,13 @@ describe("TimesheetRunningEntry", () => {
|
|||
|
||||
const start = moment();
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Group",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
@ -63,7 +62,7 @@ describe("TimesheetRunningEntry", () => {
|
|||
const end = moment().add(1, "hour");
|
||||
vi.setSystemTime(end.toDate());
|
||||
|
||||
const id = v4();
|
||||
const id = 1;
|
||||
|
||||
timekeep.setState({
|
||||
entries: [
|
||||
|
|
@ -116,7 +115,7 @@ describe("TimesheetRunningEntry", () => {
|
|||
vi.setSystemTime(end.toDate());
|
||||
|
||||
const entry = {
|
||||
id: v4(),
|
||||
id: 3,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
@ -126,13 +125,13 @@ describe("TimesheetRunningEntry", () => {
|
|||
timekeep.setState({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Outer",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Inner",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
|
|
|
|||
|
|
@ -17,13 +17,6 @@ import { defaultTimekeep, type Timekeep } from "@/timekeep/schema";
|
|||
import { TimekeepAutocomplete } from "@/service/autocomplete";
|
||||
import { TimekeepRegistry } from "@/service/registry";
|
||||
|
||||
vi.mock(import("uuid"), async (importOriginal) => {
|
||||
return {
|
||||
...(await importOriginal()),
|
||||
v4: vi.fn(() => "mocked-uuid"),
|
||||
};
|
||||
});
|
||||
|
||||
describe("TimesheetStart", () => {
|
||||
let containerEl: HTMLElement;
|
||||
let vault: MockVault;
|
||||
|
|
@ -73,7 +66,7 @@ describe("TimesheetStart", () => {
|
|||
expect(timekeep.getState()).toEqual({
|
||||
entries: [
|
||||
{
|
||||
id: "mocked-uuid",
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
import type { App } from "obsidian";
|
||||
|
||||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { createMockContainer, MockVault } from "@/__mocks__/obsidian";
|
||||
|
|
@ -59,7 +58,7 @@ describe("TimesheetStatusBar", () => {
|
|||
it("should be able to render a file based status item", () => {
|
||||
const start = moment();
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
@ -77,7 +76,7 @@ describe("TimesheetStatusBar", () => {
|
|||
it("should be able to render a markdown based status item", () => {
|
||||
const start = moment();
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import moment from "moment";
|
||||
import { App } from "obsidian";
|
||||
import { v4 } from "uuid";
|
||||
import { describe, beforeEach, it, expect, vi, afterEach } from "vitest";
|
||||
|
||||
import { createMockContainer, MockVault } from "@/__mocks__/obsidian";
|
||||
|
|
@ -20,7 +19,7 @@ describe("TimesheetStatusBarItem", () => {
|
|||
const oneHourLater = start.add(1, "hour");
|
||||
|
||||
const entry: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import moment from "moment";
|
||||
import { type App } from "obsidian";
|
||||
import { v4 } from "uuid";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { createMockContainer } from "@/__mocks__/obsidian";
|
||||
|
|
@ -38,7 +37,7 @@ describe("TimesheetTable", () => {
|
|||
timekeep.setState({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: moment(start),
|
||||
|
|
@ -54,13 +53,13 @@ describe("TimesheetTable", () => {
|
|||
timekeep.setState({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: moment(start),
|
||||
|
|
@ -89,13 +88,13 @@ describe("TimesheetTable", () => {
|
|||
timekeep.setState({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: moment(start),
|
||||
|
|
@ -112,7 +111,7 @@ describe("TimesheetTable", () => {
|
|||
timekeep.setState({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import fs from "fs/promises";
|
||||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
|
||||
export const output = await fs.readFile("src/export/__fixtures__/csv/tableRows.csv", "utf-8");
|
||||
|
||||
|
|
@ -9,27 +8,27 @@ export const currentTime = moment(start).add(2, "hours");
|
|||
|
||||
export const entries = [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: moment(start).add(1, "hour"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Test 2",
|
||||
startTime: moment(start),
|
||||
endTime: moment(start).add(2, "hour"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 3,
|
||||
name: "Test Group",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 4,
|
||||
name: "Test 3",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import fs from "fs/promises";
|
||||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
|
||||
export const output = await fs.readFile(
|
||||
"src/export/__fixtures__/csv/flattenGroupEntries.csv",
|
||||
|
|
@ -11,27 +10,27 @@ export const currentTime = moment("2020-01-01T00:00:00Z");
|
|||
|
||||
export const entries = [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(currentTime),
|
||||
endTime: moment(currentTime).add(1, "hour"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Test 2",
|
||||
startTime: moment(currentTime),
|
||||
endTime: moment(currentTime).add(2, "hour"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 3,
|
||||
name: "Test Group",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 4,
|
||||
name: "Test 3",
|
||||
startTime: moment(currentTime),
|
||||
endTime: moment(currentTime).add(2, "hour"),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import fs from "fs/promises";
|
||||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
|
||||
export const output = await fs.readFile("src/export/__fixtures__/csv/tableRows.csv", "utf-8");
|
||||
|
||||
|
|
@ -8,14 +7,14 @@ export const currentTime = moment("2020-01-01T00:00:00Z");
|
|||
|
||||
export const entries = [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(currentTime),
|
||||
endTime: moment(currentTime).add(1, "hour"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Test 2",
|
||||
startTime: moment(currentTime),
|
||||
endTime: moment(currentTime).add(2, "hour"),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import fs from "fs/promises";
|
||||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
|
||||
export const output = await fs.readFile("src/export/__fixtures__/markdown/tableRows.md", "utf-8");
|
||||
|
||||
|
|
@ -9,27 +8,27 @@ export const currentTime = moment(start).add(2, "hours");
|
|||
|
||||
export const entries = [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: moment(start).add(1, "hour"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Test 2",
|
||||
startTime: moment(start),
|
||||
endTime: moment(start).add(2, "hour"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 3,
|
||||
name: "Test Group",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 4,
|
||||
name: "Test 3",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import fs from "fs/promises";
|
||||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
|
||||
export const output = await fs.readFile(
|
||||
"src/export/__fixtures__/markdown/flattenGroupEntries.md",
|
||||
|
|
@ -11,27 +10,27 @@ export const currentTime = moment("2020-01-01T00:00:00Z");
|
|||
|
||||
export const entries = [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(currentTime),
|
||||
endTime: moment(currentTime).add(1, "hour"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Test 2",
|
||||
startTime: moment(currentTime),
|
||||
endTime: moment(currentTime).add(2, "hour"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 3,
|
||||
name: "Test Group",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 4,
|
||||
name: "Test 3",
|
||||
startTime: moment(currentTime),
|
||||
endTime: moment(currentTime).add(2, "hour"),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import fs from "fs/promises";
|
||||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
|
||||
export const output = await fs.readFile("src/export/__fixtures__/markdown/tableRows.md", "utf-8");
|
||||
|
||||
|
|
@ -8,14 +7,14 @@ export const currentTime = moment("2020-01-01T00:00:00Z");
|
|||
|
||||
export const entries = [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(currentTime),
|
||||
endTime: moment(currentTime).add(1, "hour"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Test 2",
|
||||
startTime: moment(currentTime),
|
||||
endTime: moment(currentTime).add(2, "hour"),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
|
||||
export const output = [
|
||||
["Test", "20-01-01 13:00:00", "20-01-01 14:00:00", "1.00h"],
|
||||
|
|
@ -13,27 +12,27 @@ export const currentTime = moment(start).add(2, "hours");
|
|||
|
||||
export const entries = [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(start),
|
||||
endTime: moment(start).add(1, "hour"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Test 2",
|
||||
startTime: moment(start),
|
||||
endTime: moment(start).add(2, "hour"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 3,
|
||||
name: "Test Group",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 4,
|
||||
name: "Test 3",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
|
||||
export const output = [
|
||||
["Test", "20-01-01 13:00:00", "20-01-01 14:00:00", "1.00h"],
|
||||
|
|
@ -12,27 +11,27 @@ export const currentTime = moment("2020-01-01T00:00:00Z");
|
|||
|
||||
export const entries = [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(currentTime),
|
||||
endTime: moment(currentTime).add(1, "hour"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Test 2",
|
||||
startTime: moment(currentTime),
|
||||
endTime: moment(currentTime).add(2, "hour"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 3,
|
||||
name: "Test Group",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 4,
|
||||
name: "Test 3",
|
||||
startTime: moment(currentTime),
|
||||
endTime: moment(currentTime).add(2, "hour"),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
|
||||
export const output = [
|
||||
["Test", "20-01-01 13:00:00", "20-01-01 14:00:00", "1.00h"],
|
||||
|
|
@ -10,14 +9,14 @@ export const currentTime = moment("2020-01-01T00:00:00Z");
|
|||
|
||||
export const entries = [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment(currentTime),
|
||||
endTime: moment(currentTime).add(1, "hour"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Test 2",
|
||||
startTime: moment(currentTime),
|
||||
endTime: moment(currentTime).add(2, "hour"),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import moment from "moment";
|
||||
import { Content } from "pdfmake";
|
||||
import { v4 } from "uuid";
|
||||
import { describe, it, expect } from "vitest";
|
||||
|
||||
import { defaultSettings, FontFamily, type TimekeepSettings } from "@/settings";
|
||||
|
|
@ -52,14 +51,14 @@ describe("createPdfDefinition", () => {
|
|||
const timekeep: Timekeep = {
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test Entry 1",
|
||||
startTime: moment("2024-01-01T10:00:00"),
|
||||
endTime: moment("2024-01-01T11:00:00"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Test Entry 2",
|
||||
startTime: moment("2024-01-01T10:00:00"),
|
||||
endTime: moment("2024-01-01T11:00:00"),
|
||||
|
|
@ -84,7 +83,7 @@ describe("createPdfDefinition", () => {
|
|||
|
||||
it("handles nested subEntries with increased depth (margin)", () => {
|
||||
const child = {
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Child",
|
||||
startTime: moment("2024-01-01T10:00:00"),
|
||||
endTime: moment("2024-01-01T11:00:00"),
|
||||
|
|
@ -92,7 +91,7 @@ describe("createPdfDefinition", () => {
|
|||
};
|
||||
|
||||
const parent = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test Entry 1",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
|
|
@ -124,7 +123,7 @@ describe("createPdfDefinition", () => {
|
|||
|
||||
it("handles entries ", () => {
|
||||
const entry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test Entry 1",
|
||||
startTime: moment("2024-01-01T10:00:00"),
|
||||
endTime: moment("2024-01-01T11:00:00"),
|
||||
|
|
@ -149,7 +148,7 @@ describe("createPdfDefinition", () => {
|
|||
|
||||
it("handles entries without startTime", () => {
|
||||
const entry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test Entry 1",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
|
|
@ -174,7 +173,7 @@ describe("createPdfDefinition", () => {
|
|||
|
||||
it("handles entries without endTime", () => {
|
||||
const entry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test Entry 1",
|
||||
startTime: moment("2024-01-01T10:00:00"),
|
||||
endTime: null,
|
||||
|
|
@ -217,20 +216,20 @@ describe("createPdfDefinition", () => {
|
|||
|
||||
it("applies alternating/group row background logic", () => {
|
||||
const parent = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test Entry 1",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Child",
|
||||
startTime: moment("2024-01-01T10:00:00"),
|
||||
endTime: moment("2024-01-01T11:00:00"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 3,
|
||||
name: "Child",
|
||||
startTime: moment("2024-01-01T10:00:00"),
|
||||
endTime: moment("2024-01-01T11:00:00"),
|
||||
|
|
@ -302,7 +301,7 @@ describe("createPdfDefinition", () => {
|
|||
|
||||
it("renders links correctly inside the entry name", () => {
|
||||
const entry: TimeEntry = {
|
||||
id: "1",
|
||||
id: 1,
|
||||
name: "Check this [[https://example.com]]",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { App, TFile, Modal, TextComponent, ButtonComponent } from "obsidian";
|
||||
import { v4 as uuid } from "uuid";
|
||||
|
||||
import { exportPdf } from "@/export/pdf";
|
||||
import { TimekeepSettings } from "@/settings";
|
||||
|
|
@ -7,6 +6,7 @@ import { Store, Unsubscribe } from "@/store";
|
|||
import { assert } from "@/utils/assert";
|
||||
import { createCodeBlock } from "@/utils/codeblock";
|
||||
|
||||
import { timekeepMergerEntries } from "@/timekeep/id";
|
||||
import { Timekeep, stripTimekeepRuntimeData } from "@/timekeep/schema";
|
||||
|
||||
import { TimekeepEntryItemType, TimekeepRegistry, TimekeepRegistryEntry } from "@/service/registry";
|
||||
|
|
@ -15,7 +15,7 @@ interface TimekeepResult {
|
|||
timekeep: Timekeep;
|
||||
file: TFile;
|
||||
index?: number;
|
||||
id: string;
|
||||
id: number;
|
||||
}
|
||||
|
||||
export class TimekeepMergerModal extends Modal {
|
||||
|
|
@ -117,7 +117,7 @@ export class TimekeepMergerModal extends Modal {
|
|||
this.loadingEl && this.mergeButton && this.searchInput,
|
||||
"Required elements should be defined"
|
||||
);
|
||||
this.loadingEl.removeClass("timekeep-merger-loading--loaded")
|
||||
this.loadingEl.removeClass("timekeep-merger-loading--loaded");
|
||||
this.loadingEl.hidden = false;
|
||||
|
||||
this.mergeButton.setDisabled(true);
|
||||
|
|
@ -150,7 +150,7 @@ export class TimekeepMergerModal extends Modal {
|
|||
} catch (err) {
|
||||
console.error(err);
|
||||
this.loadingEl.setText("Failed to load timekeep entries.");
|
||||
this.loadingEl.addClass("timekeep-merger-loading--loaded")
|
||||
this.loadingEl.addClass("timekeep-merger-loading--loaded");
|
||||
} finally {
|
||||
this.mergeButton.setDisabled(false);
|
||||
this.searchInput.setDisabled(false);
|
||||
|
|
@ -191,7 +191,10 @@ export class TimekeepMergerModal extends Modal {
|
|||
|
||||
updateSelectAll() {
|
||||
if (this.selectContainer) {
|
||||
this.selectContainer.toggleClass('timekeep-merge-select-container--visible', this.filteredResults.length > 0);
|
||||
this.selectContainer.toggleClass(
|
||||
"timekeep-merge-select-container--visible",
|
||||
this.filteredResults.length > 0
|
||||
);
|
||||
}
|
||||
|
||||
const isAllSelected = this.isAllSelected();
|
||||
|
|
@ -304,14 +307,14 @@ export class TimekeepMergerModal extends Modal {
|
|||
cls: "timekeep-merge-item-label",
|
||||
});
|
||||
|
||||
const title = label.createSpan( {
|
||||
const title = label.createSpan({
|
||||
cls: "timekeep-merge-item-title",
|
||||
});
|
||||
title.textContent = result.index
|
||||
? `${result.file.basename}: Timekeep ${result.index + 1}`
|
||||
: `${result.file.basename}`;
|
||||
|
||||
const path = label.createSpan( {
|
||||
const path = label.createSpan({
|
||||
cls: "timekeep-merge-item-path",
|
||||
});
|
||||
path.textContent = `${result.file.path}`;
|
||||
|
|
@ -338,7 +341,7 @@ export class TimekeepMergerModal extends Modal {
|
|||
switch (entry.type) {
|
||||
case TimekeepEntryItemType.FILE: {
|
||||
const timekeep = entry.timekeep;
|
||||
results.push({ id: uuid(), file: entry.file, timekeep });
|
||||
results.push({ id: timekeepMergerEntries.next(), file: entry.file, timekeep });
|
||||
break;
|
||||
}
|
||||
case TimekeepEntryItemType.MARKDOWN: {
|
||||
|
|
@ -347,7 +350,7 @@ export class TimekeepMergerModal extends Modal {
|
|||
const timekeep = timekeepWithPosition.timekeep;
|
||||
|
||||
results.push({
|
||||
id: uuid(),
|
||||
id: timekeepMergerEntries.next(),
|
||||
file: entry.file,
|
||||
timekeep,
|
||||
index: i,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { MockVault } from "@/__mocks__/obsidian";
|
||||
|
|
@ -35,7 +34,7 @@ describe("TimekeepAutocomplete", () => {
|
|||
JSON.stringify({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
@ -64,7 +63,7 @@ describe("TimekeepAutocomplete", () => {
|
|||
JSON.stringify({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
@ -93,7 +92,7 @@ describe("TimekeepAutocomplete", () => {
|
|||
JSON.stringify({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test 2",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
@ -116,7 +115,7 @@ describe("TimekeepAutocomplete", () => {
|
|||
JSON.stringify({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
@ -131,7 +130,7 @@ describe("TimekeepAutocomplete", () => {
|
|||
JSON.stringify({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test 2",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
@ -170,35 +169,35 @@ describe("TimekeepAutocomplete", () => {
|
|||
JSON.stringify({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Block 1",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 3,
|
||||
name: "Part",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 4,
|
||||
name: "Part X",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 5,
|
||||
name: "",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
@ -234,14 +233,14 @@ describe("TimekeepAutocomplete", () => {
|
|||
JSON.stringify({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Block 1",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Block 2",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
@ -293,7 +292,7 @@ describe("TimekeepAutocomplete", () => {
|
|||
JSON.stringify({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import type { Workspace } from "obsidian";
|
||||
|
||||
import moment from "moment";
|
||||
import { v4 } from "uuid";
|
||||
import { describe, vi, it, expect } from "vitest";
|
||||
|
||||
import { MockMarkdownView, MockVault, MockWorkspaceLeaf } from "@/__mocks__/obsidian";
|
||||
|
|
@ -264,7 +263,7 @@ describe("TimekeepRegistry", () => {
|
|||
const inputTimekeep: Timekeep = {
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
@ -294,7 +293,7 @@ describe("TimekeepRegistry", () => {
|
|||
const inputTimekeep: Timekeep = {
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
@ -347,7 +346,7 @@ describe("TimekeepRegistry", () => {
|
|||
JSON.stringify({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
@ -386,7 +385,7 @@ describe("TimekeepRegistry", () => {
|
|||
JSON.stringify({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
@ -503,7 +502,7 @@ describe("TimekeepRegistry", () => {
|
|||
JSON.stringify({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
@ -573,7 +572,7 @@ describe("TimekeepRegistry", () => {
|
|||
JSON.stringify({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
@ -602,7 +601,7 @@ describe("TimekeepRegistry", () => {
|
|||
JSON.stringify({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
@ -617,7 +616,7 @@ describe("TimekeepRegistry", () => {
|
|||
JSON.stringify({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
@ -650,7 +649,7 @@ describe("TimekeepRegistry", () => {
|
|||
JSON.stringify({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
@ -677,7 +676,7 @@ describe("TimekeepRegistry", () => {
|
|||
JSON.stringify({
|
||||
entries: [
|
||||
{
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test",
|
||||
startTime: moment("2020-01-01T00:00:00Z"),
|
||||
endTime: null,
|
||||
|
|
@ -899,14 +898,14 @@ describe("TimekeepRegistry", () => {
|
|||
|
||||
const start = moment();
|
||||
const entry1: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 1,
|
||||
name: "Test 1",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
subEntries: null,
|
||||
};
|
||||
const entry2: TimeEntry = {
|
||||
id: v4(),
|
||||
id: 2,
|
||||
name: "Test 2",
|
||||
startTime: moment(start),
|
||||
endTime: null,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import type { Moment } from "moment";
|
||||
|
||||
import { v4 as uuid } from "uuid";
|
||||
|
||||
import { isEmptyString } from "@/utils/text";
|
||||
|
||||
import { timekeepId } from "@/timekeep/id";
|
||||
import { TimeEntry, TimeEntryGroup } from "@/timekeep/schema";
|
||||
|
||||
/**
|
||||
|
|
@ -15,7 +14,7 @@ import { TimeEntry, TimeEntryGroup } from "@/timekeep/schema";
|
|||
*/
|
||||
export function createEntry(name: string, startTime: Moment): TimeEntry {
|
||||
return {
|
||||
id: uuid(),
|
||||
id: timekeepId.next(),
|
||||
name,
|
||||
startTime,
|
||||
endTime: null,
|
||||
|
|
@ -112,7 +111,7 @@ function makeGroupEntry(entry: TimeEntry): TimeEntryGroup {
|
|||
}
|
||||
|
||||
return {
|
||||
id: uuid(),
|
||||
id: timekeepId.next(),
|
||||
name: entry.name,
|
||||
subEntries: [{ ...entry, name: "Part 1" }],
|
||||
startTime: null,
|
||||
|
|
|
|||
51
src/timekeep/id.test.ts
Normal file
51
src/timekeep/id.test.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import { describe, it, expect, vi } from "vitest";
|
||||
|
||||
import { createIdStore, timekeepId, timekeepMergerEntries } from "@/timekeep/id";
|
||||
|
||||
vi.unmock("@/timekeep/id");
|
||||
|
||||
describe("createIdStore", () => {
|
||||
it("should return 1 on first call and increment on subsequent calls", () => {
|
||||
const store = createIdStore();
|
||||
|
||||
expect(store.next()).toBe(1);
|
||||
expect(store.next()).toBe(2);
|
||||
expect(store.next()).toBe(3);
|
||||
});
|
||||
|
||||
it("different stores should have independent counters", () => {
|
||||
const storeA = createIdStore();
|
||||
const storeB = createIdStore();
|
||||
|
||||
expect(storeA.next()).toBe(1);
|
||||
expect(storeA.next()).toBe(2);
|
||||
|
||||
expect(storeB.next()).toBe(1);
|
||||
expect(storeB.next()).toBe(2);
|
||||
|
||||
expect(storeA.next()).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe("timekeepId store", () => {
|
||||
it("should generate incrementing IDs independently", () => {
|
||||
const id1 = timekeepId.next();
|
||||
const id2 = timekeepId.next();
|
||||
const id3 = timekeepId.next();
|
||||
|
||||
expect(id2).toBe(id1 + 1);
|
||||
expect(id3).toBe(id2 + 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("timekeepMergerEntries store", () => {
|
||||
it("should generate incrementing IDs independently from timekeepId", () => {
|
||||
const idStoreValue = timekeepId.next(); // advance timekeepId
|
||||
const mergerId1 = timekeepMergerEntries.next();
|
||||
const mergerId2 = timekeepMergerEntries.next();
|
||||
|
||||
expect(mergerId1).toBe(1);
|
||||
expect(mergerId2).toBe(2);
|
||||
expect(timekeepId.next()).toBe(idStoreValue + 1);
|
||||
});
|
||||
});
|
||||
28
src/timekeep/id.ts
Normal file
28
src/timekeep/id.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* ID store for timekeep entries
|
||||
*/
|
||||
export const timekeepId = createIdStore();
|
||||
|
||||
/**
|
||||
* ID store for entries within the timekeep merger modal
|
||||
*/
|
||||
export const timekeepMergerEntries = createIdStore();
|
||||
|
||||
/**
|
||||
* Store helper for tracking runtime IDs
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
export function createIdStore() {
|
||||
let nextId: number = 1;
|
||||
|
||||
function next() {
|
||||
const value = nextId;
|
||||
nextId++;
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
next,
|
||||
};
|
||||
}
|
||||
|
|
@ -1,19 +1,14 @@
|
|||
import moment from "moment";
|
||||
import { v4 as uuid } from "uuid";
|
||||
import { parse } from "valibot";
|
||||
import { expect, it, describe, vi } from "vitest";
|
||||
import { expect, it, describe, Mock } from "vitest";
|
||||
|
||||
import { timekeepId } from "@/timekeep/id";
|
||||
import { TIMEKEEP } from "@/timekeep/schema";
|
||||
|
||||
vi.mock(import("uuid"), async (importOriginal) => {
|
||||
return {
|
||||
...(await importOriginal()),
|
||||
v4: vi.fn(() => "mocked-uuid"),
|
||||
};
|
||||
});
|
||||
|
||||
describe("schema transform", () => {
|
||||
it("transforms input with an added id", () => {
|
||||
(timekeepId.next as Mock).mockReturnValue(1);
|
||||
|
||||
const input = {
|
||||
entries: [
|
||||
{
|
||||
|
|
@ -42,20 +37,20 @@ describe("schema transform", () => {
|
|||
expect(result).toEqual({
|
||||
entries: [
|
||||
{
|
||||
id: "mocked-uuid",
|
||||
id: 1,
|
||||
name: "Block 2",
|
||||
startTime: moment("2024-03-17T01:33:51.630Z"),
|
||||
endTime: moment("2024-03-17T01:33:55.151Z"),
|
||||
subEntries: null,
|
||||
},
|
||||
{
|
||||
id: "mocked-uuid",
|
||||
id: 1,
|
||||
name: "Block 2",
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
subEntries: [
|
||||
{
|
||||
id: "mocked-uuid",
|
||||
id: 1,
|
||||
name: "Block 2",
|
||||
startTime: moment("2024-03-17T01:33:51.630Z"),
|
||||
endTime: moment("2024-03-17T01:33:55.151Z"),
|
||||
|
|
@ -66,6 +61,6 @@ describe("schema transform", () => {
|
|||
],
|
||||
});
|
||||
|
||||
expect(uuid).toHaveBeenCalled();
|
||||
expect(timekeepId.next).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import moment, { Moment } from "moment";
|
||||
import { v4 as uuid } from "uuid";
|
||||
import * as v from "valibot";
|
||||
|
||||
import { timekeepId } from "@/timekeep/id";
|
||||
|
||||
/*
|
||||
* This file contains the strict schema for parsing timekeep data
|
||||
* it also contains the types for each timekeep structure.
|
||||
|
|
@ -13,7 +14,7 @@ type RawTimeEntryGroupBase = v.InferOutput<typeof TIME_ENTRY_GROUP_BASE>;
|
|||
// Type aliases from inferred zod types
|
||||
export type TimeEntrySingle = RawTimeEntrySingle;
|
||||
export type TimeEntryGroup = RawTimeEntryGroupBase & {
|
||||
id: string;
|
||||
id: number;
|
||||
subEntries: TimeEntry[];
|
||||
};
|
||||
export type TimeEntry = TimeEntrySingle | TimeEntryGroup;
|
||||
|
|
@ -41,7 +42,7 @@ const TIME_ENTRY_SINGLE = v.pipe(
|
|||
// At runtime a unique ID is inserted
|
||||
v.transform((entry) => ({
|
||||
...entry,
|
||||
id: uuid(),
|
||||
id: timekeepId.next(),
|
||||
}))
|
||||
);
|
||||
|
||||
|
|
@ -65,7 +66,7 @@ const TIME_ENTRY_GROUP = v.pipe(
|
|||
// At runtime a unique ID is inserted
|
||||
v.transform((entry) => ({
|
||||
...entry,
|
||||
id: uuid(),
|
||||
id: timekeepId.next(),
|
||||
}))
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -39,10 +39,8 @@ export function parseNameSegments(input: string): NameSegment[] {
|
|||
text: match[1],
|
||||
url: match[1],
|
||||
});
|
||||
} else if (
|
||||
/* v8 ignore start -- @preserve */ match[2] &&
|
||||
match[3] /* v8 ignore stop -- @preserve */
|
||||
) {
|
||||
} /* v8 ignore start -- @preserve */ else if (match[2] && match[3]) {
|
||||
/* v8 ignore stop -- @preserve */
|
||||
// Markdown link ([text](url))
|
||||
segments.push({
|
||||
type: NameSegmentType.Link,
|
||||
|
|
|
|||
|
|
@ -64,7 +64,10 @@ export default defineConfig((env) => {
|
|||
},
|
||||
|
||||
test: {
|
||||
setupFiles: path.resolve(__dirname, "src", "__mocks__", "setupObsidianMocks.ts"),
|
||||
setupFiles: [
|
||||
path.resolve(__dirname, "src", "__mocks__", "setupObsidianMocks.ts"),
|
||||
path.resolve(__dirname, "src", "__mocks__", "setupMocks.ts"),
|
||||
],
|
||||
coverage: {
|
||||
// Exclude mocks and fixtures from coverage
|
||||
exclude: [
|
||||
|
|
|
|||
Loading…
Reference in a new issue