iobroker.time-tracker 0.2.0
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/LICENSE +21 -0
- package/README.md +386 -0
- package/admin/i18n/de.json +34 -0
- package/admin/i18n/en.json +1 -0
- package/admin/i18n/es.json +34 -0
- package/admin/i18n/fr.json +34 -0
- package/admin/i18n/it.json +34 -0
- package/admin/i18n/nl.json +34 -0
- package/admin/i18n/pl.json +34 -0
- package/admin/i18n/pt.json +34 -0
- package/admin/i18n/ru.json +34 -0
- package/admin/i18n/uk.json +34 -0
- package/admin/i18n/zh-cn.json +34 -0
- package/admin/jsonConfig.json +266 -0
- package/admin/time-tracker.png +0 -0
- package/build/lib/adapter/automation.js +100 -0
- package/build/lib/adapter/automation.js.map +7 -0
- package/build/lib/adapter/commands.js +160 -0
- package/build/lib/adapter/commands.js.map +7 -0
- package/build/lib/adapter/messages.js +207 -0
- package/build/lib/adapter/messages.js.map +7 -0
- package/build/lib/adapter/presence.js +129 -0
- package/build/lib/adapter/presence.js.map +7 -0
- package/build/lib/adapter/states.js +330 -0
- package/build/lib/adapter/states.js.map +7 -0
- package/build/lib/adapter/triggers.js +92 -0
- package/build/lib/adapter/triggers.js.map +7 -0
- package/build/lib/db/database.js +96 -0
- package/build/lib/db/database.js.map +7 -0
- package/build/lib/db/migrations.js +603 -0
- package/build/lib/db/migrations.js.map +7 -0
- package/build/lib/db/repositories/absences.js +432 -0
- package/build/lib/db/repositories/absences.js.map +7 -0
- package/build/lib/db/repositories/audit.js +90 -0
- package/build/lib/db/repositories/audit.js.map +7 -0
- package/build/lib/db/repositories/automations.js +326 -0
- package/build/lib/db/repositories/automations.js.map +7 -0
- package/build/lib/db/repositories/entries.js +335 -0
- package/build/lib/db/repositories/entries.js.map +7 -0
- package/build/lib/db/repositories/holidays.js +156 -0
- package/build/lib/db/repositories/holidays.js.map +7 -0
- package/build/lib/db/repositories/payouts.js +221 -0
- package/build/lib/db/repositories/payouts.js.map +7 -0
- package/build/lib/db/repositories/rfid.js +264 -0
- package/build/lib/db/repositories/rfid.js.map +7 -0
- package/build/lib/db/repositories/rules.js +356 -0
- package/build/lib/db/repositories/rules.js.map +7 -0
- package/build/lib/db/repositories/settings.js +91 -0
- package/build/lib/db/repositories/settings.js.map +7 -0
- package/build/lib/db/repositories/terminals.js +243 -0
- package/build/lib/db/repositories/terminals.js.map +7 -0
- package/build/lib/db/repositories/triggers.js +240 -0
- package/build/lib/db/repositories/triggers.js.map +7 -0
- package/build/lib/db/repositories/users.js +491 -0
- package/build/lib/db/repositories/users.js.map +7 -0
- package/build/lib/db/seed.js +180 -0
- package/build/lib/db/seed.js.map +7 -0
- package/build/lib/domain/avatar.js +63 -0
- package/build/lib/domain/avatar.js.map +7 -0
- package/build/lib/domain/breaks.js +70 -0
- package/build/lib/domain/breaks.js.map +7 -0
- package/build/lib/domain/calculation.js +150 -0
- package/build/lib/domain/calculation.js.map +7 -0
- package/build/lib/domain/holidays.js +113 -0
- package/build/lib/domain/holidays.js.map +7 -0
- package/build/lib/domain/punch.js +99 -0
- package/build/lib/domain/punch.js.map +7 -0
- package/build/lib/domain/target.js +89 -0
- package/build/lib/domain/target.js.map +7 -0
- package/build/lib/errors.js +56 -0
- package/build/lib/errors.js.map +7 -0
- package/build/lib/reports/labels.js +358 -0
- package/build/lib/reports/labels.js.map +7 -0
- package/build/lib/reports/pdf.js +308 -0
- package/build/lib/reports/pdf.js.map +7 -0
- package/build/lib/reports/types.js +32 -0
- package/build/lib/reports/types.js.map +7 -0
- package/build/lib/reports/xls.js +211 -0
- package/build/lib/reports/xls.js.map +7 -0
- package/build/lib/services/aggregation.js +495 -0
- package/build/lib/services/aggregation.js.map +7 -0
- package/build/lib/services/auth.js +381 -0
- package/build/lib/services/auth.js.map +7 -0
- package/build/lib/services/backup.js +372 -0
- package/build/lib/services/backup.js.map +7 -0
- package/build/lib/services/closing.js +106 -0
- package/build/lib/services/closing.js.map +7 -0
- package/build/lib/services/sessionSecret.js +100 -0
- package/build/lib/services/sessionSecret.js.map +7 -0
- package/build/lib/services/sync.js +278 -0
- package/build/lib/services/sync.js.map +7 -0
- package/build/lib/util/time.js +125 -0
- package/build/lib/util/time.js.map +7 -0
- package/build/lib/web/api.js +2589 -0
- package/build/lib/web/api.js.map +7 -0
- package/build/lib/web/cookies.js +80 -0
- package/build/lib/web/cookies.js.map +7 -0
- package/build/lib/web/events.js +50 -0
- package/build/lib/web/events.js.map +7 -0
- package/build/lib/web/pin-guard.js +86 -0
- package/build/lib/web/pin-guard.js.map +7 -0
- package/build/lib/web/problem.js +129 -0
- package/build/lib/web/problem.js.map +7 -0
- package/build/lib/web/rate-limit.js +65 -0
- package/build/lib/web/rate-limit.js.map +7 -0
- package/build/lib/web/router.js +274 -0
- package/build/lib/web/router.js.map +7 -0
- package/build/lib/web/server.js +189 -0
- package/build/lib/web/server.js.map +7 -0
- package/build/lib/web/static.js +151 -0
- package/build/lib/web/static.js.map +7 -0
- package/build/lib/web/stream.js +135 -0
- package/build/lib/web/stream.js.map +7 -0
- package/build/main.js +986 -0
- package/build/main.js.map +7 -0
- package/io-package.json +221 -0
- package/package.json +131 -0
- package/src-pwa/src/i18n/de.json +359 -0
- package/src-pwa/src/i18n/en.json +359 -0
- package/src-pwa/src/i18n/es.json +359 -0
- package/src-pwa/src/i18n/fr.json +359 -0
- package/src-pwa/src/i18n/index.ts +96 -0
- package/src-pwa/src/i18n/it.json +359 -0
- package/src-pwa/src/i18n/nl.json +359 -0
- package/src-pwa/src/i18n/pl.json +359 -0
- package/src-pwa/src/i18n/pt.json +359 -0
- package/src-pwa/src/i18n/ru.json +359 -0
- package/src-pwa/src/i18n/uk.json +359 -0
- package/src-pwa/src/i18n/zh-cn.json +359 -0
- package/www/assets/index-QI3wrEvW.js +119 -0
- package/www/assets/index-QI3wrEvW.js.map +1 -0
- package/www/assets/workbox-window.prod.es5-Bd17z0YL.js +3 -0
- package/www/assets/workbox-window.prod.es5-Bd17z0YL.js.map +1 -0
- package/www/favicon.svg +16 -0
- package/www/icon-192.png +0 -0
- package/www/icon-512.png +0 -0
- package/www/index.html +38 -0
- package/www/manifest.webmanifest +1 -0
- package/www/person.png +0 -0
- package/www/sw.js +3 -0
- package/www/sw.js.map +1 -0
- package/www/workbox-9c191d2f.js +3 -0
- package/www/workbox-9c191d2f.js.map +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alex <sadam6752@gmail.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
# ioBroker.time-tracker
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/iobroker.time-tracker)
|
|
6
|
+
[](https://www.npmjs.com/package/iobroker.time-tracker)
|
|
7
|
+

|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
[](https://nodei.co/npm/iobroker.time-tracker/)
|
|
11
|
+
|
|
12
|
+
**Tests:** 
|
|
13
|
+
|
|
14
|
+
A punch clock for ioBroker. Employees clock in and out, the adapter calculates target time and balance, absences and
|
|
15
|
+
vacation are managed, and the monthly statement is downloaded as PDF or Excel. Everything runs in the browser —
|
|
16
|
+
installable as an app on a phone — and a shared tablet in the workshop or at the entrance punches with a badge or a
|
|
17
|
+
PIN. All data stays on your own ioBroker host: no cloud, no subscription.
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
- **Clock in and out** in the web app (phone, tablet, PC); installable as an app (PWA) and it keeps punches while offline
|
|
22
|
+
- **Terminal for everybody**: badge (RFID/NFC) or PIN on a shared tablet, plus a board that shows who is at work
|
|
23
|
+
- **Working time**: target time from weekly hours, employment level and working days; breaks (punched or by graduated rules), overtime models, carryover, vacation and public holidays
|
|
24
|
+
- **Absences and vacation**: requests and approvals, half days, and a preview of the days already planned
|
|
25
|
+
- **Corrections** by the administration (change, delete, add a punch or a whole day) — every change carries a reason and the history of a punch stays readable
|
|
26
|
+
- **Monthly statements** as PDF and Excel, for the own account and — with the right — for every employee; statistics and payouts included
|
|
27
|
+
- **Roles**: administrator, manager, employee; every decision is checked on the server
|
|
28
|
+
- **Automations**: aggregates, live events and commands as ioBroker states
|
|
29
|
+
- **Backups**: create, download, upload, restore on the next start, delete — with a retention window
|
|
30
|
+
- **11 languages**; every employee picks their own
|
|
31
|
+
|
|
32
|
+
## Requirements
|
|
33
|
+
|
|
34
|
+
- ioBroker with js-controller >= 6.0.11 and **Node.js >= 22** (required by the bundled SQLite driver)
|
|
35
|
+
- HTTPS for the app on a phone (the service worker needs it) — a reverse proxy with Let's Encrypt is recommended
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
1. In the ioBroker admin: **Adapters → time-tracker → Install** (or `iobroker install iobroker.time-tracker`).
|
|
40
|
+
An installation from Git does not work on its own: the web app in `www/` is built, so it is not part of the
|
|
41
|
+
repository — either install the npm package or build it once in the adapter directory
|
|
42
|
+
(`npm ci && npm run install:pwa && npm run build:pwa && npm run build`).
|
|
43
|
+
2. Start the instance and open the web app on the port of the instance settings (default **8092**):
|
|
44
|
+
`http://<ioBroker host>:8092/`
|
|
45
|
+
3. Log in with the start password (see [First start](#first-start)) and create your employees.
|
|
46
|
+
|
|
47
|
+
## First start
|
|
48
|
+
|
|
49
|
+
The first start creates the database, the roles and the settings — and **one administrator account**, because
|
|
50
|
+
otherwise nobody could log in:
|
|
51
|
+
|
|
52
|
+
| Instance setting | Meaning |
|
|
53
|
+
| ----------------------------------------- | -------------------------------------------------------------------------------------- |
|
|
54
|
+
| Login of the first administrator | login of that account, default `admin` |
|
|
55
|
+
| Start password of the first administrator | password of that account; empty = a random password is written to the adapter log once |
|
|
56
|
+
|
|
57
|
+
The account starts with “change the password”, so the start password opens the door exactly once and the app asks
|
|
58
|
+
for a new one right away. Accounts created later in the administration start the same way.
|
|
59
|
+
|
|
60
|
+
The start password appears **once in the ioBroker log**: open `Logs` in the admin and look for the line
|
|
61
|
+
`administrator "admin" created with the start password "…" - change it at the first login`. The instance settings
|
|
62
|
+
show the same hint — enter your own password there and nothing has to be searched.
|
|
63
|
+
|
|
64
|
+
After that the usual order is: create employees (**Administration → Employees**), set their working time
|
|
65
|
+
(**Arbeitsprofil** button of the row: employment level, weekly hours, working days, overtime model, vacation,
|
|
66
|
+
carryover, paid break minutes, own break rules), and — if a tablet is used — create a terminal and switch the kiosk on
|
|
67
|
+
(see [Terminal](#terminal-kiosk)).
|
|
68
|
+
|
|
69
|
+
## Configuration
|
|
70
|
+
|
|
71
|
+
The adapter is configured in the **instance settings** of the ioBroker admin:
|
|
72
|
+
|
|
73
|
+
| Setting | Meaning |
|
|
74
|
+
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
|
|
75
|
+
| Port | port of the HTTP server (web app, API, terminal) |
|
|
76
|
+
| Bind address | interface to listen on, picked from the local addresses (`0.0.0.0` = all) |
|
|
77
|
+
| Instance time zone | fallback time zone (IANA name), e.g. `Europe/Berlin` |
|
|
78
|
+
| Default language for new users | one of the 11 supported languages |
|
|
79
|
+
| Holiday country | country used to generate the public holidays (default `DE`) |
|
|
80
|
+
| Database file | optional path; empty = adapter data directory |
|
|
81
|
+
| Enable kiosk terminal | switches the shared badge/PIN terminal on |
|
|
82
|
+
| Trust the reverse proxy | use `X-Forwarded-*` of a proxy (client address, HTTPS) |
|
|
83
|
+
| Session secret | secret for CSRF tokens (encrypted at rest; empty = generated once) |
|
|
84
|
+
| Badge link secret (HMAC) | secret for signed badge/NFC links (encrypted at rest); empty = generated on the first start and stored next to the database |
|
|
85
|
+
| Session lifetime in minutes | how long a login lasts |
|
|
86
|
+
| Days users may edit on their own | how far back an employee may correct own punches |
|
|
87
|
+
| Round quick punches to minutes | rounding of the quick punch (0 = off) |
|
|
88
|
+
| Calculate absences only until today | future absences do not reduce the target time |
|
|
89
|
+
| Subtract working time from absences | lets vacation turn into overtime |
|
|
90
|
+
| Keep database backups for days | retention of the backups |
|
|
91
|
+
|
|
92
|
+
These settings win over the values stored in the database and are applied on every start.
|
|
93
|
+
|
|
94
|
+
### Settings inside the app
|
|
95
|
+
|
|
96
|
+
Further settings are edited in the web app (**Administration → Settings**, right `settings.edit`):
|
|
97
|
+
|
|
98
|
+
| Setting | Meaning |
|
|
99
|
+
| ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
100
|
+
| Pause rule (`auto` / `punched` / `staffel`) | how the pause of a day is determined: the punched break (`auto`, default) or only the graduated rules |
|
|
101
|
+
| Graduated break rules (Pausenstaffel) | “from … to … minutes block length → so many minutes deducted”; the pause of a day **without** a punched break. The work profile of an employee can carry **own rules**: a rule with the same “from minutes” replaces the company rule for that person only |
|
|
102
|
+
| Paid break minutes (per employee) | how much of a break is paid: `0` = not paid, `15` = a quarter of an hour, `1440` = any length (work profile) |
|
|
103
|
+
| Company branding | logo, background picture and background colour for the login screen, the header and the kiosk screens — the colour also tints the picture |
|
|
104
|
+
| Unicode font for PDF statements | `report_font_path`: needed for `ru`, `uk`, `zh-cn` and Polish, otherwise the export refuses with a clear message |
|
|
105
|
+
|
|
106
|
+
The pause of a day appears in the month view of the app and in the monthly statement — with the paid part next to it.
|
|
107
|
+
|
|
108
|
+
## Roles
|
|
109
|
+
|
|
110
|
+
| Role | May |
|
|
111
|
+
| ---------- | -------------------------------------------------------------------------------------------- |
|
|
112
|
+
| `employee` | punch, see the own month and year, request absences, edit own punches inside the edit window |
|
|
113
|
+
| `manager` | everything an employee may, plus statements and corrections for other employees |
|
|
114
|
+
| `admin` | everything: employees, roles, terminals, settings, backups |
|
|
115
|
+
|
|
116
|
+
The **edit window** (`edit_window_days`, default 7 days) is what an `employee` is bound by: an older punch is
|
|
117
|
+
rejected with `edit_window_closed` and stays with the administration. Managers and admins are not bound by it.
|
|
118
|
+
Employees correct their own day right in the month view — the pencil beside a day opens its punches.
|
|
119
|
+
|
|
120
|
+
## Web app, terminal and API
|
|
121
|
+
|
|
122
|
+
Everything is served on the port of the instance settings:
|
|
123
|
+
|
|
124
|
+
| Path | Content |
|
|
125
|
+
| ------------------------- | ----------------------------------------------------------------------------- |
|
|
126
|
+
| `/` (and all other paths) | the web app from `www/` — punch screen, month, year report, absences, profile |
|
|
127
|
+
| `/api/...` | the REST API (JSON; errors as `application/problem+json`) |
|
|
128
|
+
| `/api/stream` | live events, so the app updates itself without a reload |
|
|
129
|
+
| `/terminal?token=…` | the kiosk screen (badge and PIN) |
|
|
130
|
+
| `/presence?token=…` | the board “who is at work right now” |
|
|
131
|
+
|
|
132
|
+
### Terminal (kiosk)
|
|
133
|
+
|
|
134
|
+
Switch **Enable kiosk terminal** on, then create the device in **Administration → Terminals** and copy the device
|
|
135
|
+
token — it is shown **exactly once**, because only its hash is stored. The ready-made address for the tablet stands
|
|
136
|
+
next to it:
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
http://<ioBroker host>:<port>/terminal?token=<device token>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The screen offers the badge field (scan or type, Enter punches), the employee list for the name plus PIN punch, the
|
|
143
|
+
clock and — after every punch — name, direction and the figures of that day for a few seconds. A device can be
|
|
144
|
+
limited to the employees that work there; without an assignment it shows everybody. **Employees need their PIN**
|
|
145
|
+
switches between “badge and PIN” and “badge only”. The token stays in the browser of the tablet, so the URL is only
|
|
146
|
+
needed for the first start.
|
|
147
|
+
|
|
148
|
+
## States
|
|
149
|
+
|
|
150
|
+
Punches stay in the database; the adapter publishes aggregates and controls:
|
|
151
|
+
|
|
152
|
+
| State | Type | Purpose |
|
|
153
|
+
| ---------------------------------------------------------------------------------------------- | ------- | ------------------------------------------ |
|
|
154
|
+
| `time-tracker.0.info.connection` | boolean | adapter/service ready |
|
|
155
|
+
| `time-tracker.0.info.lastBackup` | number | instant of the newest database backup |
|
|
156
|
+
| `time-tracker.0.info.version` / `info.schemaVersion` / `info.dbSizeBytes` / `info.lastError` | — | instance information |
|
|
157
|
+
| `time-tracker.0.users.<id>.displayName` | string | name of the employee |
|
|
158
|
+
| `time-tracker.0.users.<id>.hasOpenEntry` | boolean | employee is clocked in |
|
|
159
|
+
| `time-tracker.0.users.<id>.lastPunch` | number | instant of the last punch of today |
|
|
160
|
+
| `time-tracker.0.users.<id>.todayWorkedMinutes` | number | minutes worked today |
|
|
161
|
+
| `time-tracker.0.users.<id>.todayBalanceMinutes` | number | balance of today in minutes |
|
|
162
|
+
| `time-tracker.0.users.<id>.openConflicts` | number | punches waiting for a decision |
|
|
163
|
+
| `time-tracker.0.commands.punchUserId` | number | employee the punch commands apply to |
|
|
164
|
+
| `time-tracker.0.commands.punch` | boolean | punch in or out (button) |
|
|
165
|
+
| `time-tracker.0.commands.quickPunch` | boolean | punch with the configured quick rounding |
|
|
166
|
+
| `time-tracker.0.commands.closeMonth` | string | close a month, value `YYYY-MM` |
|
|
167
|
+
| `time-tracker.0.commands.recalc` | string | recalculate a period, `YYYY-MM` or `YYYY` |
|
|
168
|
+
| `time-tracker.0.commands.backup` | boolean | write a database backup (button) |
|
|
169
|
+
| `time-tracker.0.users.<id>.monthWorkedMinutes` / `monthBalanceMinutes` / `yearBalanceMinutes` | number | month and year figures |
|
|
170
|
+
| `time-tracker.0.company.presentCount` | number | employees clocked in right now |
|
|
171
|
+
| `time-tracker.0.company.present` | string | their names, separated by a comma |
|
|
172
|
+
| `time-tracker.0.company.openConflicts` / `company.lastPunch` | number | punches waiting for a decision, last punch |
|
|
173
|
+
| `time-tracker.0.events.lastAt` / `lastType` / `lastUser` / `lastDirection` / `lastSource` | — | newest event of the instance |
|
|
174
|
+
|
|
175
|
+
### Actions (trigger rules)
|
|
176
|
+
|
|
177
|
+
The ioBroker way of connecting hardware is a state: a fingerprint reader, a button, a door contact or a dashboard
|
|
178
|
+
writes it and the adapter does the rest. A rule is maintained in **Administration → Actions**:
|
|
179
|
+
|
|
180
|
+
| Field | Meaning |
|
|
181
|
+
| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
182
|
+
| State | the state of the other adapter, e.g. `fingerprint.0.lastMatch` |
|
|
183
|
+
| Trigger | _State carries the value_: the value has to equal _Value_ — or _Value is the employee_, where the value names the employee (id, login or shown name) |
|
|
184
|
+
| Value | the value that fires the rule (mode _State carries the value_) — `toggle` (or `*`) fires for **every** change, so a switch that goes on and off again works too |
|
|
185
|
+
| Employee | who is punched (mode _State carries the value_) |
|
|
186
|
+
| Action | punch in or out, punch with the quick rounding, set to present, set to absent |
|
|
187
|
+
| Cooldown | seconds that have to pass before the rule may fire again |
|
|
188
|
+
|
|
189
|
+
A rule fires only when the **value changes**, so a reader that repeats itself is harmless, and the cooldown keeps a
|
|
190
|
+
rapidly blinking state in check. Every punch appears in the audit trail with the note `trigger.<id>`, so its origin
|
|
191
|
+
stays traceable.
|
|
192
|
+
|
|
193
|
+
### Rules (automatic)
|
|
194
|
+
|
|
195
|
+
The adapter can act on its own as well — that table lives in **Administration → Settings**:
|
|
196
|
+
|
|
197
|
+
| Kind | What it does |
|
|
198
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------- |
|
|
199
|
+
| Clock out automatically | At the configured local time of the employee the open day is closed with a punch (note `auto.clockOut`) |
|
|
200
|
+
| Report a missing punch | The same moment, but nothing is written — the instance only reports it |
|
|
201
|
+
| Break reminder | Reminds an employee whose running work block reached the configured length |
|
|
202
|
+
|
|
203
|
+
Every rule runs **at most once per employee and local date**; `automation_runs` holds that decision and doubles as
|
|
204
|
+
the log shown below the table. The events `automation.clockOut`, `automation.missingPunch` and
|
|
205
|
+
`automation.breakReminder` appear in `events.*` too, so a notification adapter can pick them up.
|
|
206
|
+
|
|
207
|
+
### Messages (`sendTo`)
|
|
208
|
+
|
|
209
|
+
A script, a Blockly block or another adapter drives the instance without HTTP:
|
|
210
|
+
|
|
211
|
+
```js
|
|
212
|
+
sendTo("time-tracker.0", "punch", { user: "anna", quick: true }, answer => log(answer.message));
|
|
213
|
+
sendTo("time-tracker.0", "present", { user: 2, present: false });
|
|
214
|
+
sendTo("time-tracker.0", "status", { user: "anna" }, answer => log(JSON.stringify(answer.data)));
|
|
215
|
+
sendTo("time-tracker.0", "report", { user: "anna", period: "2026-09", format: "pdf" }, answer =>
|
|
216
|
+
writeFile("statement.pdf", Buffer.from(answer.data.base64, "base64")),
|
|
217
|
+
);
|
|
218
|
+
sendTo("time-tracker.0", "backup");
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
`user` is a user id, a login or the shown name. `report` answers with the file name, the MIME type and the file
|
|
222
|
+
itself as base64 (PDF or Excel), so it can be mailed or sent with a messenger adapter.
|
|
223
|
+
|
|
224
|
+
## Reports
|
|
225
|
+
|
|
226
|
+
The month view and the year report of the app offer the statement of the shown period as **PDF** and **Excel**
|
|
227
|
+
(`.xlsx`) — with the day table, the numbers of the month, the absences and two signature lines in the PDF. The file
|
|
228
|
+
is generated in the language and the time zone of the employee; the administration can pick another employee and
|
|
229
|
+
download the same statement for them.
|
|
230
|
+
|
|
231
|
+
Next to the two buttons sits a third one: the **raw data as CSV**. It carries one row per punch (`date`, `time`,
|
|
232
|
+
`direction`, `source`, `note`), semicolon separated and UTF-8 with a byte order mark — so a spreadsheet opens it
|
|
233
|
+
directly and a payroll tool can read it without asking. The header is English on purpose, because the file is meant
|
|
234
|
+
for a machine.
|
|
235
|
+
|
|
236
|
+
For `ru`, `uk`, `zh-cn` and Polish the PDF needs a Unicode font: set `report_font_path` in the app settings to a
|
|
237
|
+
`.ttf`/`.otf` file that covers the script. Without it the export stops with a clear message
|
|
238
|
+
(`report_font_missing`) instead of drawing empty boxes.
|
|
239
|
+
|
|
240
|
+
## Backups
|
|
241
|
+
|
|
242
|
+
**Administration → Backups** creates a copy of the database with one click and lists what exists:
|
|
243
|
+
|
|
244
|
+
| Action | What happens |
|
|
245
|
+
| ---------- | ------------------------------------------------------------------------ |
|
|
246
|
+
| Create now | writes a copy (`VACUUM INTO`) into the backup folder |
|
|
247
|
+
| Download | hands the file to the browser |
|
|
248
|
+
| Upload | takes a downloaded file back, checks it and queues it for the next start |
|
|
249
|
+
| Restore | queues one of the listed files for the next start (with a reason) |
|
|
250
|
+
| Delete | removes a single file after a confirmation |
|
|
251
|
+
|
|
252
|
+
A restore needs a closed database, so it is applied **while the adapter starts** — the app says so, and the previous
|
|
253
|
+
database is kept next to it as `<database>.before-restore-<time>`. Backups older than the retention of the instance
|
|
254
|
+
settings are removed automatically; the newest one always stays.
|
|
255
|
+
|
|
256
|
+
## HTTPS and reverse proxy
|
|
257
|
+
|
|
258
|
+
The app on a phone needs **HTTPS** — a service worker only runs on a secure origin. Put nginx or caddy in front of
|
|
259
|
+
the adapter and switch **Trust the reverse proxy** on: the adapter then takes the client address from
|
|
260
|
+
`x-forwarded-for` for the rate limits and the audit trail, and `x-forwarded-proto: https` makes the session cookie
|
|
261
|
+
`Secure`. Without that switch both headers are ignored, because any client could send them.
|
|
262
|
+
|
|
263
|
+
## Troubleshooting
|
|
264
|
+
|
|
265
|
+
| Problem | Cause and fix |
|
|
266
|
+
| -------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
|
267
|
+
| `/` answers `404 not_found` | the web app is missing: install the npm package or build it (`npm run install:pwa && npm run build:pwa`) |
|
|
268
|
+
| Not installable as an app on the phone | the page is not reachable over HTTPS — see above |
|
|
269
|
+
| The PDF refuses or shows empty boxes | `report_font_path` is missing — see [Reports](#reports) |
|
|
270
|
+
| A restore seems to do nothing | it is applied on the next start: restart the instance |
|
|
271
|
+
| An employee cannot log in | the start password has to be changed on first use; the administration can set a new one |
|
|
272
|
+
| A punch is missing | it may wait in the offline queue or be marked as a conflict (see _Synchronisation_ in the app) |
|
|
273
|
+
|
|
274
|
+
## Languages
|
|
275
|
+
|
|
276
|
+
The admin UI, the app and the reports ship in **11 languages** — `en` (base and fallback), `de`, `ru`, `pt`, `nl`,
|
|
277
|
+
`fr`, `it`, `es`, `pl`, `uk`, `zh-cn` — and every employee picks their own. Dates, numbers and units are formatted
|
|
278
|
+
with `Intl`. Further translations are welcome: [`docs/i18n.md`](docs/i18n.md).
|
|
279
|
+
|
|
280
|
+
## Privacy
|
|
281
|
+
|
|
282
|
+
Everything runs on your own ioBroker host: no cloud service, no telemetry. Punches and personal data stay in the
|
|
283
|
+
local SQLite file, access is role-based, and every correction is written to an audit trail.
|
|
284
|
+
|
|
285
|
+
## Documentation
|
|
286
|
+
|
|
287
|
+
| Document | Content |
|
|
288
|
+
| -------------------------------------------------- | -------------------------------------------------------- |
|
|
289
|
+
| [`docs/erste-schritte.md`](docs/erste-schritte.md) | a walk through the first setup (German) |
|
|
290
|
+
| [`docs/kurzfassung-de.md`](docs/kurzfassung-de.md) | the German summary of this README |
|
|
291
|
+
| [`docs/testplan.md`](docs/testplan.md) | acceptance tests and what is still open |
|
|
292
|
+
| [`docs/entscheidungen.md`](docs/entscheidungen.md) | the decisions behind the design (German) |
|
|
293
|
+
| [`docs/technik.md`](docs/technik.md) | internals: HTTP surface, sessions, live events, database |
|
|
294
|
+
| [`docs/entwicklung.md`](docs/entwicklung.md) | build, tests, release |
|
|
295
|
+
| [`docs/i18n.md`](docs/i18n.md) | how the 11 languages are kept complete |
|
|
296
|
+
| [`docs/adapter-check.md`](docs/adapter-check.md) | the local pre-check of the ioBroker adapter rules |
|
|
297
|
+
|
|
298
|
+
## Links
|
|
299
|
+
|
|
300
|
+
- Repository: https://github.com/sadam6752-tech/ioBroker.time-tracker
|
|
301
|
+
- Issues: https://github.com/sadam6752-tech/ioBroker.time-tracker/issues
|
|
302
|
+
- ioBroker forum: https://forum.iobroker.net/
|
|
303
|
+
|
|
304
|
+
## Changelog
|
|
305
|
+
|
|
306
|
+
### **WORK IN PROGRESS**
|
|
307
|
+
|
|
308
|
+
### 0.2.0 (2026-09-20)
|
|
309
|
+
|
|
310
|
+
- (Alex) **renamed to `ioBroker.time-tracker`**: ioBroker requires English adapter names, so the adapter, its npm
|
|
311
|
+
package and the GitHub repository are called `time-tracker` from now on. The instance id becomes `time-tracker.0`
|
|
312
|
+
and the database is created as `time-tracker.sqlite` — existing installations keep their data by pointing
|
|
313
|
+
“Database file” at the old file or by renaming it (before 0.2.0 it was `zeiterfassung.sqlite`). German UI texts
|
|
314
|
+
stay German; `common.titleLang` keeps all 11 languages
|
|
315
|
+
|
|
316
|
+
### 0.1.9 (2026-09-19)
|
|
317
|
+
|
|
318
|
+
- (Alex) ioBroker repository: two findings of the repository checker are fixed — `common.title` is removed (it is
|
|
319
|
+
deprecated, `common.titleLang` replaced it, E1084) and the `common.news` entry of 0.1.7 is gone, because that version
|
|
320
|
+
never reached npm (E2004, its pipeline was red). `npm run version:check` watches both rules from now on: it refuses
|
|
321
|
+
`common.title` and every version in the news list has to exist on npm
|
|
322
|
+
|
|
323
|
+
### 0.1.8 (2026-09-19)
|
|
324
|
+
|
|
325
|
+
- (Alex) fix: the pipeline of 0.1.7 failed in the ioBroker package test — `common.license` was added next to the
|
|
326
|
+
existing `common.licenseInformation`, and the test refuses both together (“common.license should not exist together
|
|
327
|
+
with common.licenseInformation”). The field is removed again, `npm run test:package` is part of the release checklist
|
|
328
|
+
from now on, and `docs/entwicklung.md` records the rule
|
|
329
|
+
|
|
330
|
+
### 0.1.6 (2026-09-19)
|
|
331
|
+
|
|
332
|
+
- (Alex) admin: the raw instance settings show a readable label now — in the language of the display — with the
|
|
333
|
+
technical name in the small line below it, which is what the block promises. The labels are kept short enough that
|
|
334
|
+
the fields do not cut them off
|
|
335
|
+
- (Alex) admin: the block “All instance settings” is much shorter — three fields per line on a wide screen (two on a
|
|
336
|
+
tablet, one on a phone) and the time zone on a line of its own, because its value is the longest
|
|
337
|
+
- (Alex) **rules (automatic)**: the kind **“Clock in automatically”** joins them — an employee who is still missing at
|
|
338
|
+
the configured time gets a punch in (the rule keeps quiet when somebody is clocked in already). Migration 18 rebuilds
|
|
339
|
+
the rule table for the new kind and copies the run log first, because dropping the parent would take it with it
|
|
340
|
+
- (Alex) **holidays**: the seeded days are shown in the language of the display — each one carries a stable key
|
|
341
|
+
(`newYear`, `goodFriday`, …) and the app translates it; a day somebody added by hand keeps its own name
|
|
342
|
+
- (Alex) admin: the two “first start” hints are easier to read — they are rendered as HTML with a larger font
|
|
343
|
+
|
|
344
|
+
### 0.1.5 (2026-09-19)
|
|
345
|
+
|
|
346
|
+
- (Alex) **rules (automatic)**: a rule can be limited to **weekdays** (Monday to Friday for a company rule, the
|
|
347
|
+
weekend for another) and it can be set to act **once a week** instead of once a day — the guard counts the ISO week
|
|
348
|
+
then, so a reminder that fires every Monday still fires next Monday. The days come from `Intl`, so their names are
|
|
349
|
+
spelled in the language of the display
|
|
350
|
+
- (Alex) **badges (RFID/NFC)**: the link of a fresh badge is shown as a **QR code** next to the link itself, so it can
|
|
351
|
+
be scanned or copied onto a tag with a writer app. The code is drawn in the browser (the `qrcode` package is bundled
|
|
352
|
+
with the web app), so it works offline and no service ever sees the link
|
|
353
|
+
- (Alex) docs: `docs/i18n.md` now records who settles the translations — German and Russian are kept by the owner, for
|
|
354
|
+
the other nine languages no native speaker is available, so they stay machine translation with the technical pass
|
|
355
|
+
|
|
356
|
+
Older entries are kept in [`CHANGELOG_OLD.md`](CHANGELOG_OLD.md).
|
|
357
|
+
|
|
358
|
+
## Provenance
|
|
359
|
+
|
|
360
|
+
This project is an independent implementation of the time tracking described in the internal specification.
|
|
361
|
+
Behaviour, calculation rules and data formats follow that specification; **no source code** was taken from any
|
|
362
|
+
other project. The verification record is kept outside this repository.
|
|
363
|
+
|
|
364
|
+
## License
|
|
365
|
+
|
|
366
|
+
MIT License
|
|
367
|
+
|
|
368
|
+
Copyright (c) 2026 Alex <sadam6752@gmail.com>
|
|
369
|
+
|
|
370
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
371
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
372
|
+
in the Software without restriction, including without limitation the rights
|
|
373
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
374
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
375
|
+
furnished to do so, subject to the following conditions:
|
|
376
|
+
|
|
377
|
+
The above copyright notice and this permission notice shall be included in all
|
|
378
|
+
copies or substantial portions of the Software.
|
|
379
|
+
|
|
380
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
381
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
382
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
383
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
384
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
385
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
386
|
+
SOFTWARE.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"⚠️ First start: the first administrator is created when the instance starts for the first time. If the password field stays empty, the generated password is written ONCE into the ioBroker log (open “Logs” on the left, look for the yellow line with “created with the start password”) — both fields are in the tab “Migration and backup”. The app asks for a new password at the first login.": "<div style=\"font-size: 1.15rem; line-height: 1.6\">⚠️ Erster Start: der erste Administrator entsteht beim ersten Start der Instanz. Bleibt das Passwortfeld leer, wird das erzeugte Passwort EINMALIG ins ioBroker-Log geschrieben (links „Logs“ öffnen und die gelbe Zeile mit „created with the start password“ suchen) — beide Felder stehen im Tab „Migration und Backup“. Die App verlangt bei der ersten Anmeldung ein neues Passwort.</div>",
|
|
3
|
+
"⚠️ The account of the first administrator is created at the very first start. If the password field below stays empty, the adapter generates a random password and writes it ONCE into the ioBroker log: open “Logs” in the ioBroker admin on the left and look for the yellow line with “created with the start password” — that is the password for the first login. The app then asks for a new password right away. Enter your own password below instead if you want to skip that.": "<div style=\"font-size: 1.15rem; line-height: 1.6\">⚠️ Das Konto des ersten Administrators entsteht beim allerersten Start. Bleibt das Passwortfeld unten leer, erzeugt der Adapter ein Zufallspasswort und schreibt es EINMALIG ins ioBroker-Log: links im ioBroker-Admin „Logs“ öffnen und die gelbe Zeile mit „created with the start password“ suchen — das ist das Passwort für die erste Anmeldung. Die App verlangt danach sofort ein neues Passwort. Wer das überspringen will, trägt unten gleich ein eigenes Passwort ein.</div>",
|
|
4
|
+
"127.0.0.1 = only this machine": "127.0.0.1 = nur dieser Rechner",
|
|
5
|
+
"Badge link secret (HMAC)": "Geheimnis für Badge-Links (HMAC)",
|
|
6
|
+
"Bind address": "Bind-Adresse",
|
|
7
|
+
"Calculate absences only until today": "Abwesenheiten nur bis heute berechnen",
|
|
8
|
+
"Database file (empty = adapter data directory)": "Datenbankdatei (leer = Datenverzeichnis des Adapters)",
|
|
9
|
+
"Days users may edit on their own": "Tage, die Benutzer selbst bearbeiten dürfen",
|
|
10
|
+
"Default language for new users": "Standardsprache für neue Benutzer",
|
|
11
|
+
"empty = a random password is written to the adapter log once; it has to be changed at the first login": "leer = ein Zufallspasswort wird einmalig ins Adapter-Log geschrieben; es muss bei der ersten Anmeldung geändert werden",
|
|
12
|
+
"empty = the adapter generates one once and stores it next to the database, so sessions survive restarts": "leer = der Adapter erzeugt einmalig eines und legt es neben der Datenbank ab, damit Sitzungen Neustarts überleben",
|
|
13
|
+
"Enable kiosk terminal": "Kiosk-Terminal aktivieren",
|
|
14
|
+
"First start: the start password is in the ioBroker log": "Erster Start: das Startpasswort steht im ioBroker-Log",
|
|
15
|
+
"General": "Allgemein",
|
|
16
|
+
"Holiday country": "Land für Feiertage",
|
|
17
|
+
"Instance time zone": "Zeitzone der Instanz",
|
|
18
|
+
"Keep database backups for days": "Datenbank-Backups aufbewahren für Tage",
|
|
19
|
+
"Login of the first administrator": "Login des ersten Administrators",
|
|
20
|
+
"Migration and backup": "Migration und Backup",
|
|
21
|
+
"only switch this on when a reverse proxy is in front of the adapter": "nur einschalten, wenn ein Reverse-Proxy vor dem Adapter steht",
|
|
22
|
+
"Port": "Port",
|
|
23
|
+
"Round quick punches to minutes (0 = off)": "Schnellstempel auf Minuten runden (0 = aus)",
|
|
24
|
+
"Security": "Sicherheit",
|
|
25
|
+
"Session lifetime in minutes": "Sitzungsdauer in Minuten",
|
|
26
|
+
"Session secret": "Sitzungsgeheimnis",
|
|
27
|
+
"Start password of the first administrator": "Startpasswort des ersten Administrators",
|
|
28
|
+
"Subtract working time from absences": "Arbeitszeit von Abwesenheiten abziehen",
|
|
29
|
+
"the port of the web app, the API and the terminal; 8082 stays free for vis and web": "der Port der Web-App, der API und des Terminals; 8082 bleibt für vis und web frei",
|
|
30
|
+
"Time rules": "Zeitregeln",
|
|
31
|
+
"Trust the reverse proxy (X-Forwarded-*)": "Reverse-Proxy vertrauen (X-Forwarded-*)",
|
|
32
|
+
"used once: the account is created when the instance has no administrator yet": "wird einmalig genutzt: das Konto entsteht, wenn die Instanz noch keinen Administrator hat",
|
|
33
|
+
"time-tracker adapter settings": "Adaptereinstellungen für Zeiterfassung"
|
|
34
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"⚠️ First start: the first administrator is created when the instance starts for the first time. If the password field stays empty, the generated password is written ONCE into the ioBroker log (open “Logs” on the left, look for the yellow line with “created with the start password”) — both fields are in the tab “Migration and backup”. The app asks for a new password at the first login.":"⚠️ First start: the first administrator is created when the instance starts for the first time. If the password field stays empty, the generated password is written ONCE into the ioBroker log (open “Logs” on the left, look for the yellow line with “created with the start password”) — both fields are in the tab “Migration and backup”. The app asks for a new password at the first login.","⚠️ The account of the first administrator is created at the very first start. If the password field below stays empty, the adapter generates a random password and writes it ONCE into the ioBroker log: open “Logs” in the ioBroker admin on the left and look for the yellow line with “created with the start password” — that is the password for the first login. The app then asks for a new password right away. Enter your own password below instead if you want to skip that.":"⚠️ The account of the first administrator is created at the very first start. If the password field below stays empty, the adapter generates a random password and writes it ONCE into the ioBroker log: open “Logs” in the ioBroker admin on the left and look for the yellow line with “created with the start password” — that is the password for the first login. The app then asks for a new password right away. Enter your own password below instead if you want to skip that.","127.0.0.1 = only this machine":"127.0.0.1 = only this machine","Badge link secret (HMAC)":"Badge link secret (HMAC)","Bind address":"Bind address","Calculate absences only until today":"Calculate absences only until today","Database file (empty = adapter data directory)":"Database file (empty = adapter data directory)","Days users may edit on their own":"Days users may edit on their own","Default language for new users":"Default language for new users","empty = a random password is written to the adapter log once; it has to be changed at the first login":"empty = a random password is written to the adapter log once; it has to be changed at the first login","empty = the adapter generates one once and stores it next to the database, so sessions survive restarts":"empty = the adapter generates one once and stores it next to the database, so sessions survive restarts","Enable kiosk terminal":"Enable kiosk terminal","First start: the start password is in the ioBroker log":"First start: the start password is in the ioBroker log","General":"General","Holiday country":"Holiday country","Instance time zone":"Instance time zone","Keep database backups for days":"Keep database backups for days","Login of the first administrator":"Login of the first administrator","Migration and backup":"Migration and backup","only switch this on when a reverse proxy is in front of the adapter":"only switch this on when a reverse proxy is in front of the adapter","Port":"Port","Round quick punches to minutes (0 = off)":"Round quick punches to minutes (0 = off)","Security":"Security","Session lifetime in minutes":"Session lifetime in minutes","Session secret":"Session secret","Start password of the first administrator":"Start password of the first administrator","Subtract working time from absences":"Subtract working time from absences","the port of the web app, the API and the terminal; 8082 stays free for vis and web":"the port of the web app, the API and the terminal; 8082 stays free for vis and web","Time rules":"Time rules","Trust the reverse proxy (X-Forwarded-*)":"Trust the reverse proxy (X-Forwarded-*)","used once: the account is created when the instance has no administrator yet":"used once: the account is created when the instance has no administrator yet","time-tracker adapter settings":"Adapter settings for time-tracker"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"⚠️ First start: the first administrator is created when the instance starts for the first time. If the password field stays empty, the generated password is written ONCE into the ioBroker log (open “Logs” on the left, look for the yellow line with “created with the start password”) — both fields are in the tab “Migration and backup”. The app asks for a new password at the first login.": "<div style=\"font-size: 1.15rem; line-height: 1.6\">⚠️ Primer inicio: el primer administrador se crea en el primer inicio de la instancia. Si el campo de la contraseña queda vacío, la contraseña generada se escribe UNA vez en el registro de ioBroker (abre «Logs» a la izquierda y busca la línea amarilla con «created with the start password») — ambos campos están en la pestaña «Migración y copia de seguridad». La aplicación pide una contraseña nueva en el primer inicio de sesión.</div>",
|
|
3
|
+
"⚠️ The account of the first administrator is created at the very first start. If the password field below stays empty, the adapter generates a random password and writes it ONCE into the ioBroker log: open “Logs” in the ioBroker admin on the left and look for the yellow line with “created with the start password” — that is the password for the first login. The app then asks for a new password right away. Enter your own password below instead if you want to skip that.": "<div style=\"font-size: 1.15rem; line-height: 1.6\">⚠️ La cuenta del primer administrador se crea en el primer inicio. Si el campo de la contraseña de abajo queda vacío, el adaptador genera una contraseña aleatoria y la escribe UNA vez en el registro de ioBroker: abre «Logs» a la izquierda en el admin de ioBroker y busca la línea amarilla con «created with the start password» — esa es la contraseña del primer inicio de sesión. La aplicación pide enseguida una contraseña nueva. Si lo prefieres, introduce tu propia contraseña abajo.</div>",
|
|
4
|
+
"127.0.0.1 = only this machine": "127.0.0.1 = solo este equipo",
|
|
5
|
+
"Badge link secret (HMAC)": "Secreto de enlace de insignia (HMAC)",
|
|
6
|
+
"Bind address": "Dirección de escucha",
|
|
7
|
+
"Calculate absences only until today": "Calcular ausencias solo hasta hoy",
|
|
8
|
+
"Database file (empty = adapter data directory)": "Archivo de base de datos (vacío = directorio de datos del adaptador)",
|
|
9
|
+
"Days users may edit on their own": "Días que los usuarios pueden editar por su cuenta",
|
|
10
|
+
"Default language for new users": "Idioma predeterminado para nuevos usuarios",
|
|
11
|
+
"empty = a random password is written to the adapter log once; it has to be changed at the first login": "vacío = se escribe una contraseña aleatoria una vez en el registro del adaptador; debe cambiarse en el primer inicio de sesión",
|
|
12
|
+
"empty = the adapter generates one once and stores it next to the database, so sessions survive restarts": "vacío = el adaptador genera uno una vez y lo guarda junto a la base de datos, para que las sesiones sobrevivan a los reinicios",
|
|
13
|
+
"Enable kiosk terminal": "Habilitar terminal de quiosco",
|
|
14
|
+
"First start: the start password is in the ioBroker log": "Primer inicio: la contraseña inicial está en el registro de ioBroker",
|
|
15
|
+
"General": "General",
|
|
16
|
+
"Holiday country": "País para los días festivos",
|
|
17
|
+
"Instance time zone": "Zona horaria de la instancia",
|
|
18
|
+
"Keep database backups for days": "Conservar las copias de seguridad de la base de datos durante días",
|
|
19
|
+
"Login of the first administrator": "Usuario del primer administrador",
|
|
20
|
+
"Migration and backup": "Migración y copia de seguridad",
|
|
21
|
+
"only switch this on when a reverse proxy is in front of the adapter": "activar solo si hay un proxy inverso delante del adaptador",
|
|
22
|
+
"Port": "Puerto",
|
|
23
|
+
"Round quick punches to minutes (0 = off)": "Redondear los fichajes rápidos a minutos (0 = desactivado)",
|
|
24
|
+
"Security": "Seguridad",
|
|
25
|
+
"Session lifetime in minutes": "Duración de la sesión en minutos",
|
|
26
|
+
"Session secret": "Secreto de sesión",
|
|
27
|
+
"Start password of the first administrator": "Contraseña inicial del primer administrador",
|
|
28
|
+
"Subtract working time from absences": "Restar el tiempo de trabajo de las ausencias",
|
|
29
|
+
"the port of the web app, the API and the terminal; 8082 stays free for vis and web": "el puerto de la aplicación web, la API y el terminal; 8082 queda libre para vis y web",
|
|
30
|
+
"Time rules": "Reglas de horario",
|
|
31
|
+
"Trust the reverse proxy (X-Forwarded-*)": "Confiar en el proxy inverso (X-Forwarded-*)",
|
|
32
|
+
"used once: the account is created when the instance has no administrator yet": "se usa una sola vez: la cuenta se crea cuando la instancia aún no tiene administrador",
|
|
33
|
+
"time-tracker adapter settings": "Configuración del adaptador para time-tracker"
|
|
34
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"⚠️ First start: the first administrator is created when the instance starts for the first time. If the password field stays empty, the generated password is written ONCE into the ioBroker log (open “Logs” on the left, look for the yellow line with “created with the start password”) — both fields are in the tab “Migration and backup”. The app asks for a new password at the first login.": "<div style=\"font-size: 1.15rem; line-height: 1.6\">⚠️ Premier démarrage : le premier administrateur est créé au premier démarrage de l'instance. Si le champ du mot de passe reste vide, le mot de passe généré est écrit UNE fois dans le journal d'ioBroker (ouvrez « Logs » à gauche et cherchez la ligne jaune « created with the start password ») — les deux champs se trouvent dans l'onglet « Migration et sauvegarde ». L'application demande un nouveau mot de passe à la première connexion.</div>",
|
|
3
|
+
"⚠️ The account of the first administrator is created at the very first start. If the password field below stays empty, the adapter generates a random password and writes it ONCE into the ioBroker log: open “Logs” in the ioBroker admin on the left and look for the yellow line with “created with the start password” — that is the password for the first login. The app then asks for a new password right away. Enter your own password below instead if you want to skip that.": "<div style=\"font-size: 1.15rem; line-height: 1.6\">⚠️ Le compte du premier administrateur est créé au tout premier démarrage. Si le champ du mot de passe ci-dessous reste vide, l'adaptateur génère un mot de passe aléatoire et l'écrit UNE fois dans le journal d'ioBroker : ouvrez « Logs » à gauche dans l'admin ioBroker et cherchez la ligne jaune « created with the start password » — c'est le mot de passe de la première connexion. L'application demande ensuite immédiatement un nouveau mot de passe. Saisissez plutôt votre propre mot de passe ci-dessous pour éviter cela.</div>",
|
|
4
|
+
"127.0.0.1 = only this machine": "127.0.0.1 = uniquement cette machine",
|
|
5
|
+
"Badge link secret (HMAC)": "Secret du lien du badge (HMAC)",
|
|
6
|
+
"Bind address": "Adresse d'écoute",
|
|
7
|
+
"Calculate absences only until today": "Calculer les absences uniquement jusqu'à aujourd'hui",
|
|
8
|
+
"Database file (empty = adapter data directory)": "Fichier de base de données (vide = répertoire de données de l'adaptateur)",
|
|
9
|
+
"Days users may edit on their own": "Jours pendant lesquels les utilisateurs peuvent modifier eux-mêmes",
|
|
10
|
+
"Default language for new users": "Langue par défaut pour les nouveaux utilisateurs",
|
|
11
|
+
"empty = a random password is written to the adapter log once; it has to be changed at the first login": "vide = un mot de passe aléatoire est écrit une fois dans le journal de l'adaptateur ; il doit être changé lors de la première connexion",
|
|
12
|
+
"empty = the adapter generates one once and stores it next to the database, so sessions survive restarts": "vide = l'adaptateur en génère un une fois et le stocke à côté de la base de données, pour que les sessions survivent aux redémarrages",
|
|
13
|
+
"Enable kiosk terminal": "Activer le terminal kiosque",
|
|
14
|
+
"First start: the start password is in the ioBroker log": "Premier démarrage : le mot de passe initial est dans le journal d'ioBroker",
|
|
15
|
+
"General": "Général",
|
|
16
|
+
"Holiday country": "Pays pour les jours fériés",
|
|
17
|
+
"Instance time zone": "Fuseau horaire de l'instance",
|
|
18
|
+
"Keep database backups for days": "Durée de conservation des sauvegardes (jours)",
|
|
19
|
+
"Login of the first administrator": "Identifiant du premier administrateur",
|
|
20
|
+
"Migration and backup": "Migration et sauvegarde",
|
|
21
|
+
"only switch this on when a reverse proxy is in front of the adapter": "à activer uniquement si un proxy inverse se trouve devant l'adaptateur",
|
|
22
|
+
"Port": "Port",
|
|
23
|
+
"Round quick punches to minutes (0 = off)": "Arrondir les pointages rapides en minutes (0 = désactivé)",
|
|
24
|
+
"Security": "Sécurité",
|
|
25
|
+
"Session lifetime in minutes": "Durée de vie de la session en minutes",
|
|
26
|
+
"Session secret": "Secret de session",
|
|
27
|
+
"Start password of the first administrator": "Mot de passe initial du premier administrateur",
|
|
28
|
+
"Subtract working time from absences": "Soustraire le temps de travail des absences",
|
|
29
|
+
"the port of the web app, the API and the terminal; 8082 stays free for vis and web": "le port de l'application web, de l'API et du terminal ; 8082 reste libre pour vis et web",
|
|
30
|
+
"Time rules": "Règles de temps de travail",
|
|
31
|
+
"Trust the reverse proxy (X-Forwarded-*)": "Faire confiance au proxy inverse (X-Forwarded-*)",
|
|
32
|
+
"used once: the account is created when the instance has no administrator yet": "utilisé une seule fois : le compte est créé lorsque l'instance n'a pas encore d'administrateur",
|
|
33
|
+
"time-tracker adapter settings": "Paramètres de l'adaptateur pour time-tracker"
|
|
34
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"⚠️ First start: the first administrator is created when the instance starts for the first time. If the password field stays empty, the generated password is written ONCE into the ioBroker log (open “Logs” on the left, look for the yellow line with “created with the start password”) — both fields are in the tab “Migration and backup”. The app asks for a new password at the first login.": "<div style=\"font-size: 1.15rem; line-height: 1.6\">⚠️ Primo avvio: il primo amministratore viene creato al primo avvio dell'istanza. Se il campo della password resta vuoto, la password generata viene scritta UNA volta nel log di ioBroker (apri «Logs» a sinistra e cerca la riga gialla con «created with the start password») — entrambi i campi sono nella scheda «Migrazione e backup». L'app chiede una nuova password al primo accesso.</div>",
|
|
3
|
+
"⚠️ The account of the first administrator is created at the very first start. If the password field below stays empty, the adapter generates a random password and writes it ONCE into the ioBroker log: open “Logs” in the ioBroker admin on the left and look for the yellow line with “created with the start password” — that is the password for the first login. The app then asks for a new password right away. Enter your own password below instead if you want to skip that.": "<div style=\"font-size: 1.15rem; line-height: 1.6\">⚠️ L'account del primo amministratore viene creato al primissimo avvio. Se il campo della password qui sotto resta vuoto, l'adattatore genera una password casuale e la scrive UNA volta nel log di ioBroker: apri «Logs» a sinistra nell'admin di ioBroker e cerca la riga gialla con «created with the start password» — è quella la password per il primo accesso. L'app chiede subito una nuova password. Se preferisci, inserisci qui sotto la tua password.</div>",
|
|
4
|
+
"127.0.0.1 = only this machine": "127.0.0.1 = solo questa macchina",
|
|
5
|
+
"Badge link secret (HMAC)": "Segreto collegamento badge (HMAC)",
|
|
6
|
+
"Bind address": "Indirizzo di ascolto",
|
|
7
|
+
"Calculate absences only until today": "Calcola le assenze solo fino ad oggi",
|
|
8
|
+
"Database file (empty = adapter data directory)": "File di database (vuoto = directory dei dati dell'adattatore)",
|
|
9
|
+
"Days users may edit on their own": "Giorni in cui gli utenti possono modificare autonomamente",
|
|
10
|
+
"Default language for new users": "Lingua predefinita per i nuovi utenti",
|
|
11
|
+
"empty = a random password is written to the adapter log once; it has to be changed at the first login": "vuoto = una password casuale viene scritta una volta nel log dell'adattatore; va cambiata al primo accesso",
|
|
12
|
+
"empty = the adapter generates one once and stores it next to the database, so sessions survive restarts": "vuoto = l'adattatore ne genera uno una volta e lo salva accanto al database, così le sessioni sopravvivono ai riavvii",
|
|
13
|
+
"Enable kiosk terminal": "Abilita il terminale kiosk",
|
|
14
|
+
"First start: the start password is in the ioBroker log": "Primo avvio: la password iniziale è nel log di ioBroker",
|
|
15
|
+
"General": "Generale",
|
|
16
|
+
"Holiday country": "Paese per i giorni festivi",
|
|
17
|
+
"Instance time zone": "Fuso orario dell'istanza",
|
|
18
|
+
"Keep database backups for days": "Conservazione dei backup del database (giorni)",
|
|
19
|
+
"Login of the first administrator": "Login del primo amministratore",
|
|
20
|
+
"Migration and backup": "Migrazione e backup",
|
|
21
|
+
"only switch this on when a reverse proxy is in front of the adapter": "attivare solo se davanti all'adattatore c'è un proxy inverso",
|
|
22
|
+
"Port": "Porta",
|
|
23
|
+
"Round quick punches to minutes (0 = off)": "Arrotonda le timbrature rapide ai minuti (0 = disattivato)",
|
|
24
|
+
"Security": "Sicurezza",
|
|
25
|
+
"Session lifetime in minutes": "Durata della sessione in minuti",
|
|
26
|
+
"Session secret": "Segreto della sessione",
|
|
27
|
+
"Start password of the first administrator": "Password iniziale del primo amministratore",
|
|
28
|
+
"Subtract working time from absences": "Sottrarre l'orario di lavoro dalle assenze",
|
|
29
|
+
"the port of the web app, the API and the terminal; 8082 stays free for vis and web": "la porta dell'app web, dell'API e del terminale; 8082 resta libera per vis e web",
|
|
30
|
+
"Time rules": "Regole dell'orario di lavoro",
|
|
31
|
+
"Trust the reverse proxy (X-Forwarded-*)": "Fidati del proxy inverso (X-Forwarded-*)",
|
|
32
|
+
"used once: the account is created when the instance has no administrator yet": "usato una sola volta: l'account viene creato quando l'istanza non ha ancora un amministratore",
|
|
33
|
+
"time-tracker adapter settings": "Impostazioni dell'adattatore per time-tracker"
|
|
34
|
+
}
|