iobroker.time-tracker 0.7.8 → 0.7.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -10
- package/build/lib/db/repositories/holidays.js +5 -1
- package/build/lib/db/repositories/holidays.js.map +2 -2
- package/build/lib/web/api.js +5 -3
- package/build/lib/web/api.js.map +2 -2
- package/io-package.json +14 -14
- package/package.json +1 -1
- package/src-www/src/i18n/de.json +1 -1
- package/src-www/src/i18n/en.json +1 -1
- package/src-www/src/i18n/es.json +1 -1
- package/src-www/src/i18n/fr.json +1 -1
- package/src-www/src/i18n/it.json +1 -1
- package/src-www/src/i18n/nl.json +1 -1
- package/src-www/src/i18n/pl.json +1 -1
- package/src-www/src/i18n/pt.json +1 -1
- package/src-www/src/i18n/ru.json +1 -1
- package/src-www/src/i18n/uk.json +1 -1
- package/src-www/src/i18n/zh-cn.json +1 -1
- package/www/assets/{index-DlGND1Q4.js → index-D5c1Xz-S.js} +3 -3
- package/www/assets/index-D5c1Xz-S.js.map +1 -0
- package/www/index.html +1 -1
- package/www/sw.js +1 -1
- package/www/sw.js.map +1 -1
- package/www/assets/index-DlGND1Q4.js.map +0 -1
package/README.md
CHANGED
|
@@ -421,6 +421,15 @@ local SQLite file, access is role-based, and every correction is written to an a
|
|
|
421
421
|
|
|
422
422
|
### **WORK IN PROGRESS**
|
|
423
423
|
|
|
424
|
+
### 0.7.9 (2026-09-26)
|
|
425
|
+
|
|
426
|
+
- (Alex) fix: “Feiertag hinzufügen” stayed grey while the day had to be typed as text — it comes from the date field of
|
|
427
|
+
the browser now, and the label no longer names a format. A holiday entered without a region belongs to the country of
|
|
428
|
+
the instance instead of always `DE`, the list shows the days of **every** region of the year, and a day of the next
|
|
429
|
+
year takes the shown year along
|
|
430
|
+
- (Alex) fix: “Abbrechen” closes the form of an absence while it is being changed as well — it cleared only the flag of
|
|
431
|
+
the new absence and left the dialog of the change on the screen
|
|
432
|
+
|
|
424
433
|
### 0.7.8 (2026-09-26)
|
|
425
434
|
|
|
426
435
|
- (Alex) new: an absence can be taken back. An employee withdraws a request that is still open, and for an approved
|
|
@@ -458,16 +467,6 @@ local SQLite file, access is role-based, and every correction is written to an a
|
|
|
458
467
|
- (Alex) fix: the periodic refresh and the hourly backup check cannot overlap themselves any more. A tick that finds the previous run still busy is skipped and logged, so a slow run (a big database, a slow disk) can no longer pile a second one on top of itself
|
|
459
468
|
- (Alex) change: `onStateChange` no longer writes a debug line for every state of the instance that it does not handle - on a busy system that filled the log at log level `debug` for nothing
|
|
460
469
|
|
|
461
|
-
### 0.7.4 (2026-09-24)
|
|
462
|
-
|
|
463
|
-
- (Alex) fix: the subscription link of the company carries the API prefix now (`…/api/calendar.ics?token=…`). Without
|
|
464
|
-
it a browser got the web app and its login instead of the calendar
|
|
465
|
-
- (Alex) change: the written calendar file sits in `<iobroker-data>/files/time-tracker.<n>/calendar.ics` instead of the
|
|
466
|
-
instance folder next to it — that one is readable for the adapter alone; the `ical` adapter keeps reading it as a
|
|
467
|
-
local file
|
|
468
|
-
- (Alex) docs: the test plan carries a small snippet for the *Scripts* tab that reads `calendar.absences` and logs who
|
|
469
|
-
is away today (for T21, not part of the adapter)
|
|
470
|
-
|
|
471
470
|
Older entries are kept in [`CHANGELOG_OLD.md`](CHANGELOG_OLD.md).
|
|
472
471
|
|
|
473
472
|
## Provenance
|
|
@@ -36,6 +36,7 @@ function requireDate(date) {
|
|
|
36
36
|
}
|
|
37
37
|
function createHolidaysRepository(db) {
|
|
38
38
|
const selectByYear = db.prepare(`SELECT ${COLUMNS} FROM holidays WHERE year = ? AND region = ? ORDER BY date`);
|
|
39
|
+
const selectByYearAllRegions = db.prepare(`SELECT ${COLUMNS} FROM holidays WHERE year = ? ORDER BY date, region`);
|
|
39
40
|
const selectByDate = db.prepare(`SELECT ${COLUMNS} FROM holidays WHERE date = ? AND region = ?`);
|
|
40
41
|
const selectYears = db.prepare("SELECT DISTINCT year FROM holidays ORDER BY year");
|
|
41
42
|
const selectById = db.prepare(`SELECT ${COLUMNS} FROM holidays WHERE id = ?`);
|
|
@@ -49,7 +50,10 @@ function createHolidaysRepository(db) {
|
|
|
49
50
|
return row != null ? row : null;
|
|
50
51
|
};
|
|
51
52
|
return {
|
|
52
|
-
listByYear(year, region
|
|
53
|
+
listByYear(year, region) {
|
|
54
|
+
if (region === void 0) {
|
|
55
|
+
return selectByYearAllRegions.all(year);
|
|
56
|
+
}
|
|
53
57
|
return selectByYear.all(year, region);
|
|
54
58
|
},
|
|
55
59
|
years() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/db/repositories/holidays.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Holiday repository (`holidays`).\n *\n * Holidays are stored per region, the region is the country code of the instance (`CH`, `DE`, `AT`).\n * `ensureYear` generates the holidays of a country idempotently and never touches edited rows, so\n * administrators can rename or delete single days.\n */\n\nimport type { Db } from \"../database\";\nimport { holidaysForYear, type HolidayCountry } from \"../../domain/holidays\";\nimport { isDateString } from \"../../util/time\";\nimport { ValidationError } from \"../../errors\";\nimport { writeAuditLog } from \"./audit\";\n\n/** A public holiday as stored in the database. */\nexport interface HolidayRecord {\n\t/** Primary key */\n\tid: number;\n\t/** Region (country code) the holiday belongs to */\n\tregion: string;\n\t/** Year of the holiday (derived from `date`) */\n\tyear: number;\n\t/** Local date, `YYYY-MM-DD` */\n\tdate: string;\n\t/** Display name */\n\tname: string;\n\t/** Key of a seeded holiday (`null` for one that was added by hand) */\n\tkey: string | null;\n}\n\n/** Holiday storage operations. */\nexport interface HolidaysRepository {\n\t/** Holidays of one year, sorted by date */\n\tlistByYear(year: number, region?: string): HolidayRecord[];\n\t/** Years for which holidays are stored */\n\tyears(): number[];\n\t/** True when the date is a holiday of the region */\n\tisHoliday(date: string, region?: string): boolean;\n\t/** All holiday dates of a year as a set (input for the calculation service) */\n\tdateSet(year: number, region?: string): Set<string>;\n\t/** Generates the missing holidays of a country for one year */\n\tensureYear(input: { year: number; country: HolidayCountry; actorId?: number | null; now?: number }): {\n\t\tyear: number;\n\t\tinserted: number;\n\t};\n\t/** Adds a holiday; an existing date of the region is renamed */\n\tadd(input: {\n\t\tdate: string;\n\t\tname: string;\n\t\tregion?: string;\n\t\tactorId: number;\n\t\tactorIp?: string | null;\n\t\tnow?: number;\n\t}): HolidayRecord;\n\t/** Deletes a holiday by id */\n\tremove(input: { id: number; actorId: number; actorIp?: string | null; now?: number }): boolean;\n}\n\ninterface HolidayRow {\n\tid: number;\n\tregion: string;\n\tyear: number;\n\tdate: string;\n\tname: string;\n\tkey: string | null;\n}\n\n/** Default region used when the caller does not pass one. */\nconst DEFAULT_REGION = \"DE\";\n\nconst COLUMNS = \"id, region, year, date, name, key\";\n\n/**\n * Checks and normalises a holiday date.\n *\n * @param date - date to validate\n * @returns the validated date\n */\nfunction requireDate(date: string): string {\n\tconst trimmed = date.trim();\n\tif (!isDateString(trimmed)) {\n\t\tthrow new ValidationError(`invalid date \"${date}\", expected YYYY-MM-DD`);\n\t}\n\treturn trimmed;\n}\n\n/**\n * Creates the holiday repository.\n *\n * @param db - open database handle\n * @returns repository instance\n */\nexport function createHolidaysRepository(db: Db): HolidaysRepository {\n\tconst selectByYear = db.prepare(`SELECT ${COLUMNS} FROM holidays WHERE year = ? AND region = ? ORDER BY date`);\n\tconst selectByDate = db.prepare(`SELECT ${COLUMNS} FROM holidays WHERE date = ? AND region = ?`);\n\tconst selectYears = db.prepare(\"SELECT DISTINCT year FROM holidays ORDER BY year\");\n\tconst selectById = db.prepare(`SELECT ${COLUMNS} FROM holidays WHERE id = ?`);\n\tconst insertHoliday = db.prepare(\n\t\t`INSERT INTO holidays (region, year, date, name, key) VALUES (?, ?, ?, ?, ?)\n\t\t ON CONFLICT(region, date) DO UPDATE SET name = excluded.name, year = excluded.year, key = excluded.key`,\n\t);\n\tconst deleteHoliday = db.prepare(\"DELETE FROM holidays WHERE id = ?\");\n\n\tconst read = (id: number): HolidayRecord | null => {\n\t\tconst row = selectById.get(id) as HolidayRow | undefined;\n\t\treturn row ?? null;\n\t};\n\n\treturn {\n\t\tlistByYear(year: number, region
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,sBAAqD;AACrD,kBAA6B;AAC7B,oBAAgC;AAChC,mBAA8B;AAwD9B,MAAM,iBAAiB;AAEvB,MAAM,UAAU;AAQhB,SAAS,YAAY,MAAsB;AAC1C,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,KAAC,0BAAa,OAAO,GAAG;AAC3B,UAAM,IAAI,8BAAgB,iBAAiB,IAAI,wBAAwB;AAAA,EACxE;AACA,SAAO;AACR;AAQO,SAAS,yBAAyB,IAA4B;AACpE,QAAM,eAAe,GAAG,QAAQ,UAAU,OAAO,4DAA4D;AAC7G,QAAM,eAAe,GAAG,QAAQ,UAAU,OAAO,8CAA8C;AAC/F,QAAM,cAAc,GAAG,QAAQ,kDAAkD;AACjF,QAAM,aAAa,GAAG,QAAQ,UAAU,OAAO,6BAA6B;AAC5E,QAAM,gBAAgB,GAAG;AAAA,IACxB;AAAA;AAAA,EAED;AACA,QAAM,gBAAgB,GAAG,QAAQ,mCAAmC;AAEpE,QAAM,OAAO,CAAC,OAAqC;AAClD,UAAM,MAAM,WAAW,IAAI,EAAE;AAC7B,WAAO,oBAAO;AAAA,EACf;AAEA,SAAO;AAAA,IACN,WAAW,MAAc,
|
|
4
|
+
"sourcesContent": ["/**\n * Holiday repository (`holidays`).\n *\n * Holidays are stored per region, the region is the country code of the instance (`CH`, `DE`, `AT`).\n * `ensureYear` generates the holidays of a country idempotently and never touches edited rows, so\n * administrators can rename or delete single days.\n */\n\nimport type { Db } from \"../database\";\nimport { holidaysForYear, type HolidayCountry } from \"../../domain/holidays\";\nimport { isDateString } from \"../../util/time\";\nimport { ValidationError } from \"../../errors\";\nimport { writeAuditLog } from \"./audit\";\n\n/** A public holiday as stored in the database. */\nexport interface HolidayRecord {\n\t/** Primary key */\n\tid: number;\n\t/** Region (country code) the holiday belongs to */\n\tregion: string;\n\t/** Year of the holiday (derived from `date`) */\n\tyear: number;\n\t/** Local date, `YYYY-MM-DD` */\n\tdate: string;\n\t/** Display name */\n\tname: string;\n\t/** Key of a seeded holiday (`null` for one that was added by hand) */\n\tkey: string | null;\n}\n\n/** Holiday storage operations. */\nexport interface HolidaysRepository {\n\t/** Holidays of one year, sorted by date; without a region the days of every region are returned */\n\tlistByYear(year: number, region?: string): HolidayRecord[];\n\t/** Years for which holidays are stored */\n\tyears(): number[];\n\t/** True when the date is a holiday of the region */\n\tisHoliday(date: string, region?: string): boolean;\n\t/** All holiday dates of a year as a set (input for the calculation service) */\n\tdateSet(year: number, region?: string): Set<string>;\n\t/** Generates the missing holidays of a country for one year */\n\tensureYear(input: { year: number; country: HolidayCountry; actorId?: number | null; now?: number }): {\n\t\tyear: number;\n\t\tinserted: number;\n\t};\n\t/** Adds a holiday; an existing date of the region is renamed */\n\tadd(input: {\n\t\tdate: string;\n\t\tname: string;\n\t\tregion?: string;\n\t\tactorId: number;\n\t\tactorIp?: string | null;\n\t\tnow?: number;\n\t}): HolidayRecord;\n\t/** Deletes a holiday by id */\n\tremove(input: { id: number; actorId: number; actorIp?: string | null; now?: number }): boolean;\n}\n\ninterface HolidayRow {\n\tid: number;\n\tregion: string;\n\tyear: number;\n\tdate: string;\n\tname: string;\n\tkey: string | null;\n}\n\n/** Default region used when the caller does not pass one. */\nconst DEFAULT_REGION = \"DE\";\n\nconst COLUMNS = \"id, region, year, date, name, key\";\n\n/**\n * Checks and normalises a holiday date.\n *\n * @param date - date to validate\n * @returns the validated date\n */\nfunction requireDate(date: string): string {\n\tconst trimmed = date.trim();\n\tif (!isDateString(trimmed)) {\n\t\tthrow new ValidationError(`invalid date \"${date}\", expected YYYY-MM-DD`);\n\t}\n\treturn trimmed;\n}\n\n/**\n * Creates the holiday repository.\n *\n * @param db - open database handle\n * @returns repository instance\n */\nexport function createHolidaysRepository(db: Db): HolidaysRepository {\n\tconst selectByYear = db.prepare(`SELECT ${COLUMNS} FROM holidays WHERE year = ? AND region = ? ORDER BY date`);\n\tconst selectByYearAllRegions = db.prepare(`SELECT ${COLUMNS} FROM holidays WHERE year = ? ORDER BY date, region`);\n\tconst selectByDate = db.prepare(`SELECT ${COLUMNS} FROM holidays WHERE date = ? AND region = ?`);\n\tconst selectYears = db.prepare(\"SELECT DISTINCT year FROM holidays ORDER BY year\");\n\tconst selectById = db.prepare(`SELECT ${COLUMNS} FROM holidays WHERE id = ?`);\n\tconst insertHoliday = db.prepare(\n\t\t`INSERT INTO holidays (region, year, date, name, key) VALUES (?, ?, ?, ?, ?)\n\t\t ON CONFLICT(region, date) DO UPDATE SET name = excluded.name, year = excluded.year, key = excluded.key`,\n\t);\n\tconst deleteHoliday = db.prepare(\"DELETE FROM holidays WHERE id = ?\");\n\n\tconst read = (id: number): HolidayRecord | null => {\n\t\tconst row = selectById.get(id) as HolidayRow | undefined;\n\t\treturn row ?? null;\n\t};\n\n\treturn {\n\t\tlistByYear(year: number, region?: string): HolidayRecord[] {\n\t\t\t// without a region the whole year is listed: the administration also sees the days of another region,\n\t\t\t// which keeps them at hand after a change of the holiday country\n\t\t\tif (region === undefined) {\n\t\t\t\treturn selectByYearAllRegions.all(year) as HolidayRecord[];\n\t\t\t}\n\t\t\treturn selectByYear.all(year, region) as HolidayRecord[];\n\t\t},\n\n\t\tyears(): number[] {\n\t\t\treturn (selectYears.all() as { year: number }[]).map(row => row.year);\n\t\t},\n\n\t\tisHoliday(date: string, region: string = DEFAULT_REGION): boolean {\n\t\t\treturn selectByDate.get(date, region) !== undefined;\n\t\t},\n\n\t\tdateSet(year: number, region: string = DEFAULT_REGION): Set<string> {\n\t\t\tconst rows = selectByYear.all(year, region) as HolidayRow[];\n\t\t\treturn new Set(rows.map(row => row.date));\n\t\t},\n\n\t\tensureYear(input: { year: number; country: HolidayCountry; actorId?: number | null; now?: number }): {\n\t\t\tyear: number;\n\t\t\tinserted: number;\n\t\t} {\n\t\t\tconst now = input.now ?? Math.floor(Date.now() / 1000);\n\t\t\tlet inserted = 0;\n\n\t\t\tconst run = db.transaction((): void => {\n\t\t\t\tconst insertMissing = db.prepare(\n\t\t\t\t\t\"INSERT OR IGNORE INTO holidays (region, year, date, name, key) VALUES (?, ?, ?, ?, ?)\",\n\t\t\t\t);\n\t\t\t\tfor (const holiday of holidaysForYear(input.year, input.country)) {\n\t\t\t\t\tinserted += insertMissing.run(\n\t\t\t\t\t\tinput.country,\n\t\t\t\t\t\tinput.year,\n\t\t\t\t\t\tholiday.date,\n\t\t\t\t\t\tholiday.name,\n\t\t\t\t\t\tholiday.key,\n\t\t\t\t\t).changes;\n\t\t\t\t}\n\t\t\t});\n\t\t\trun();\n\n\t\t\tif (inserted > 0) {\n\t\t\t\twriteAuditLog(db, {\n\t\t\t\t\tatUtc: now,\n\t\t\t\t\tactorId: input.actorId ?? null,\n\t\t\t\t\taction: \"holiday.ensure\",\n\t\t\t\t\tentity: \"holiday\",\n\t\t\t\t\tentityId: input.year,\n\t\t\t\t\tdetail: { year: input.year, country: input.country, inserted },\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { year: input.year, inserted };\n\t\t},\n\n\t\tadd(input: {\n\t\t\tdate: string;\n\t\t\tname: string;\n\t\t\tregion?: string;\n\t\t\tactorId: number;\n\t\t\tactorIp?: string | null;\n\t\t\tnow?: number;\n\t\t}): HolidayRecord {\n\t\t\tconst date = requireDate(input.date);\n\t\t\tconst name = input.name.trim();\n\t\t\tif (!name) {\n\t\t\t\tthrow new ValidationError(\"name must not be empty\");\n\t\t\t}\n\t\t\tconst region = input.region ?? DEFAULT_REGION;\n\t\t\tconst year = Number(date.slice(0, 4));\n\t\t\tconst now = input.now ?? Math.floor(Date.now() / 1000);\n\t\t\tconst existing = selectByDate.get(date, region) as HolidayRow | undefined;\n\n\t\t\tconst run = db.transaction((): void => {\n\t\t\t\t// a day somebody adds by hand has no key: it keeps the name it was given\n\t\t\t\tinsertHoliday.run(region, year, date, name, null);\n\t\t\t\twriteAuditLog(db, {\n\t\t\t\t\tatUtc: now,\n\t\t\t\t\tactorId: input.actorId,\n\t\t\t\t\taction: existing ? \"holiday.update\" : \"holiday.create\",\n\t\t\t\t\tentity: \"holiday\",\n\t\t\t\t\tentityId: date,\n\t\t\t\t\tdetail: existing\n\t\t\t\t\t\t? { changes: { name: { old: existing.name, new: name } } }\n\t\t\t\t\t\t: { date, name, region },\n\t\t\t\t\tip: input.actorIp ?? null,\n\t\t\t\t});\n\t\t\t});\n\t\t\trun();\n\n\t\t\tconst saved = selectByDate.get(date, region) as HolidayRow | undefined;\n\t\t\tif (!saved) {\n\t\t\t\tthrow new Error(`holiday ${date} disappeared right after the write`);\n\t\t\t}\n\t\t\treturn saved;\n\t\t},\n\n\t\tremove(input: { id: number; actorId: number; actorIp?: string | null; now?: number }): boolean {\n\t\t\tconst existing = read(input.id);\n\t\t\tif (!existing) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tconst now = input.now ?? Math.floor(Date.now() / 1000);\n\n\t\t\tconst run = db.transaction((): void => {\n\t\t\t\tdeleteHoliday.run(input.id);\n\t\t\t\twriteAuditLog(db, {\n\t\t\t\t\tatUtc: now,\n\t\t\t\t\tactorId: input.actorId,\n\t\t\t\t\taction: \"holiday.delete\",\n\t\t\t\t\tentity: \"holiday\",\n\t\t\t\t\tentityId: existing.date,\n\t\t\t\t\tdetail: { region: existing.region, name: existing.name },\n\t\t\t\t\tip: input.actorIp ?? null,\n\t\t\t\t});\n\t\t\t});\n\t\t\trun();\n\t\t\treturn true;\n\t\t},\n\t};\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["_a"]
|
|
7
7
|
}
|
package/build/lib/web/api.js
CHANGED
|
@@ -1169,7 +1169,7 @@ function createApi(deps) {
|
|
|
1169
1169
|
return (0, import_router.json)(200, { year, region: region != null ? region : null, holidays: holidays.listByYear(year, region) });
|
|
1170
1170
|
});
|
|
1171
1171
|
route("POST", "/holidays", { permission: "holiday.manage", csrf: true }, (context) => {
|
|
1172
|
-
var _a2, _b2;
|
|
1172
|
+
var _a2, _b2, _c2;
|
|
1173
1173
|
if (!context.auth) {
|
|
1174
1174
|
throw (0, import_problem.problem)(401, "no_session", "request rejected (no_session)");
|
|
1175
1175
|
}
|
|
@@ -1177,9 +1177,11 @@ function createApi(deps) {
|
|
|
1177
1177
|
const created = holidays.add({
|
|
1178
1178
|
date: requireString(body, "date"),
|
|
1179
1179
|
name: requireString(body, "name"),
|
|
1180
|
-
region
|
|
1180
|
+
// without a region the day belongs to the country of the instance: the calculation looks only there, so a
|
|
1181
|
+
// day filed under a foreign region would never count
|
|
1182
|
+
region: (_b2 = (_a2 = optionalString(body, "region")) != null ? _a2 : settings.get("holiday_country")) != null ? _b2 : void 0,
|
|
1181
1183
|
actorId: context.auth.user.id,
|
|
1182
|
-
actorIp: (
|
|
1184
|
+
actorIp: (_c2 = context.request.remoteAddress) != null ? _c2 : null,
|
|
1183
1185
|
now: now()
|
|
1184
1186
|
});
|
|
1185
1187
|
return (0, import_router.json)(201, { holiday: created }, { location: `/holidays/${created.id}` });
|