estela 0.1.19 → 0.1.21
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 +1 -1
- package/dist/billing/amortize.d.ts.map +1 -1
- package/dist/billing/amortize.js +3 -2
- package/dist/billing/amortize.js.map +1 -1
- package/dist/billing/invoice.d.ts.map +1 -1
- package/dist/billing/invoice.js +19 -18
- package/dist/billing/invoice.js.map +1 -1
- package/dist/billing/sessionize.d.ts.map +1 -1
- package/dist/billing/sessionize.js +3 -2
- package/dist/billing/sessionize.js.map +1 -1
- package/dist/billing.d.ts.map +1 -1
- package/dist/billing.js +5 -4
- package/dist/billing.js.map +1 -1
- package/dist/bin.js +6 -2
- package/dist/bin.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +311 -164
- package/dist/cli.js.map +1 -1
- package/dist/cloud/auth.d.ts.map +1 -1
- package/dist/cloud/auth.js +9 -8
- package/dist/cloud/auth.js.map +1 -1
- package/dist/cloud/client.d.ts.map +1 -1
- package/dist/cloud/client.js +11 -6
- package/dist/cloud/client.js.map +1 -1
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +4 -3
- package/dist/db/schema.js.map +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +50 -45
- package/dist/doctor.js.map +1 -1
- package/dist/i18n/en.d.ts +10 -0
- package/dist/i18n/en.d.ts.map +1 -0
- package/dist/i18n/en.js +326 -0
- package/dist/i18n/en.js.map +1 -0
- package/dist/i18n/i18n.test.d.ts +2 -0
- package/dist/i18n/i18n.test.d.ts.map +1 -0
- package/dist/i18n/i18n.test.js +201 -0
- package/dist/i18n/i18n.test.js.map +1 -0
- package/dist/i18n/index.d.ts +54 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +106 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/publish.d.ts.map +1 -1
- package/dist/publish.js +6 -5
- package/dist/publish.js.map +1 -1
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +50 -25
- package/dist/server.js.map +1 -1
- package/dist/server.test.d.ts +2 -0
- package/dist/server.test.d.ts.map +1 -0
- package/dist/server.test.js +125 -0
- package/dist/server.test.js.map +1 -0
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +8 -5
- package/dist/setup.js.map +1 -1
- package/dist/sync/team.d.ts.map +1 -1
- package/dist/sync/team.js +7 -6
- package/dist/sync/team.js.map +1 -1
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +7 -6
- package/dist/sync.js.map +1 -1
- package/dist/team.d.ts.map +1 -1
- package/dist/team.js +9 -8
- package/dist/team.js.map +1 -1
- package/dist/updateCheck.d.ts.map +1 -1
- package/dist/updateCheck.js +3 -2
- package/dist/updateCheck.js.map +1 -1
- package/dist/watchers/claude.d.ts.map +1 -1
- package/dist/watchers/claude.js +3 -2
- package/dist/watchers/claude.js.map +1 -1
- package/dist/web-ui.test.js +96 -7
- package/dist/web-ui.test.js.map +1 -1
- package/node_modules/@estela/shared/dist/money.d.ts +1 -0
- package/node_modules/@estela/shared/dist/money.d.ts.map +1 -1
- package/node_modules/@estela/shared/dist/money.js +9 -1
- package/node_modules/@estela/shared/dist/money.js.map +1 -1
- package/package.json +1 -1
- package/web/app.js +213 -223
- package/web/i18n.js +635 -0
- package/web/index.html +40 -34
- package/web/lib.js +33 -8
package/web/index.html
CHANGED
|
@@ -15,47 +15,52 @@
|
|
|
15
15
|
<img class="brand-logo" src="/logo.png" alt="getestela.dev">
|
|
16
16
|
</div>
|
|
17
17
|
<nav class="tabs" role="tablist">
|
|
18
|
-
<button type="button" class="tab is-on" data-view="summary" role="tab">Resumen</button>
|
|
19
|
-
<button type="button" class="tab" data-view="day" role="tab">Mi día</button>
|
|
20
|
-
<button type="button" class="tab" data-view="team" role="tab">Equipo</button>
|
|
21
|
-
<button type="button" class="tab" data-view="reports" role="tab">Informes</button>
|
|
22
|
-
<button type="button" class="tab" data-view="projects" role="tab">Proyectos</button>
|
|
18
|
+
<button type="button" class="tab is-on" data-view="summary" role="tab" data-i18n="tab.summary">Resumen</button>
|
|
19
|
+
<button type="button" class="tab" data-view="day" role="tab" data-i18n="tab.day">Mi día</button>
|
|
20
|
+
<button type="button" class="tab" data-view="team" role="tab" data-i18n="tab.team">Equipo</button>
|
|
21
|
+
<button type="button" class="tab" data-view="reports" role="tab" data-i18n="tab.reports">Informes</button>
|
|
22
|
+
<button type="button" class="tab" data-view="projects" role="tab" data-i18n="tab.projects">Proyectos</button>
|
|
23
23
|
</nav>
|
|
24
24
|
<div class="top-right" id="top-right">
|
|
25
|
+
<button type="button" class="chip lang-switch" id="lang-switch"
|
|
26
|
+
data-i18n="lang.switch" data-i18n-title="lang.switch.title">EN</button>
|
|
25
27
|
<button type="button" class="chip" id="sync-now" hidden
|
|
28
|
+
data-i18n="sync.now" data-i18n-title="sync.now.title"
|
|
26
29
|
title="Sube tus horas a la nube y baja lo de tus otras máquinas">Sincronizar</button>
|
|
27
30
|
<div class="upgrade-wrap" id="upgrade-wrap" hidden>
|
|
28
|
-
<button type="button" class="btn-main btn-upgrade" id="upgrade-btn">Actualizar a Pro o Teams</button>
|
|
31
|
+
<button type="button" class="btn-main btn-upgrade" id="upgrade-btn" data-i18n="upgrade.btn">Actualizar a Pro o Teams</button>
|
|
29
32
|
<div class="upgrade-menu" id="upgrade-menu" hidden>
|
|
30
|
-
<div class="upgrade-ciclo" role="group" aria-label="Ciclo de facturación">
|
|
31
|
-
<button type="button" data-ciclo="monthly" class="is-on">Mensual</button>
|
|
32
|
-
<button type="button" data-ciclo="yearly">Anual</button>
|
|
33
|
+
<div class="upgrade-ciclo" role="group" aria-label="Ciclo de facturación" data-i18n-aria-label="upgrade.cycle">
|
|
34
|
+
<button type="button" data-ciclo="monthly" class="is-on" data-i18n="upgrade.monthly">Mensual</button>
|
|
35
|
+
<button type="button" data-ciclo="yearly" data-i18n="upgrade.yearly">Anual</button>
|
|
33
36
|
</div>
|
|
34
|
-
<div class="upgrade-ahorro">Anual: 2 meses gratis</div>
|
|
37
|
+
<div class="upgrade-ahorro" data-i18n="upgrade.saving">Anual: 2 meses gratis</div>
|
|
35
38
|
<button type="button" class="upgrade-option" data-plan="pro"
|
|
39
|
+
data-i18n-monthly="upgrade.pro.monthly" data-i18n-yearly="upgrade.pro.yearly"
|
|
36
40
|
data-monthly="9€/mes · paneles y sync ilimitados"
|
|
37
41
|
data-yearly="90€/año · paneles y sync ilimitados">
|
|
38
|
-
<b>Pro</b><span>9€/mes · paneles y sync ilimitados</span>
|
|
42
|
+
<b>Pro</b><span data-i18n="upgrade.pro.monthly">9€/mes · paneles y sync ilimitados</span>
|
|
39
43
|
</button>
|
|
40
44
|
<button type="button" class="upgrade-option" data-plan="teams"
|
|
45
|
+
data-i18n-monthly="upgrade.teams.monthly" data-i18n-yearly="upgrade.teams.yearly"
|
|
41
46
|
data-monthly="15€/proyecto/mes · horas de equipo medidas"
|
|
42
47
|
data-yearly="150€/proyecto/año · horas de equipo medidas">
|
|
43
|
-
<b>Teams</b><span>15€/proyecto/mes · horas de equipo medidas</span>
|
|
48
|
+
<b>Teams</b><span data-i18n="upgrade.teams.monthly">15€/proyecto/mes · horas de equipo medidas</span>
|
|
44
49
|
</button>
|
|
45
50
|
</div>
|
|
46
51
|
</div>
|
|
47
52
|
<span class="sync-warn" id="sync-warn" hidden></span>
|
|
48
|
-
<button type="button" class="sync" id="sync" title="Buscar trabajo nuevo (R)">
|
|
53
|
+
<button type="button" class="sync" id="sync" title="Buscar trabajo nuevo (R)" data-i18n-title="refresh.title">
|
|
49
54
|
<span class="sync-dot" aria-hidden="true"></span>
|
|
50
|
-
<span id="sync-label">Actualizar</span>
|
|
55
|
+
<span id="sync-label" data-i18n="refresh.label">Actualizar</span>
|
|
51
56
|
</button>
|
|
52
57
|
</div>
|
|
53
58
|
</header>
|
|
54
59
|
|
|
55
60
|
<div class="banner-promo" id="banner-promo" hidden>
|
|
56
61
|
<span id="banner-text"></span>
|
|
57
|
-
<a id="banner-link" href="#" target="_blank" rel="noopener" hidden>Ver más →</a>
|
|
58
|
-
<button type="button" id="banner-close" aria-label="Cerrar">×</button>
|
|
62
|
+
<a id="banner-link" href="#" target="_blank" rel="noopener" hidden data-i18n="banner.more">Ver más →</a>
|
|
63
|
+
<button type="button" id="banner-close" aria-label="Cerrar" data-i18n-aria-label="banner.close">×</button>
|
|
59
64
|
</div>
|
|
60
65
|
|
|
61
66
|
<main>
|
|
@@ -63,13 +68,13 @@
|
|
|
63
68
|
<section class="view" id="view-team">
|
|
64
69
|
<div class="section-head">
|
|
65
70
|
<div>
|
|
66
|
-
<h1>Equipo</h1>
|
|
71
|
+
<h1 data-i18n="tab.team">Equipo</h1>
|
|
67
72
|
<p class="sub" id="team-sub">…</p>
|
|
68
73
|
</div>
|
|
69
74
|
<div class="periods">
|
|
70
|
-
<select class="filter" id="team-project"><option value="">Todos los proyectos</option></select>
|
|
71
|
-
<button type="button" class="period" data-tperiod="month">Este mes</button>
|
|
72
|
-
<button type="button" class="period is-on" data-tperiod="quarter">3 meses</button>
|
|
75
|
+
<select class="filter" id="team-project"><option value="" data-i18n="team.allProjects">Todos los proyectos</option></select>
|
|
76
|
+
<button type="button" class="period" data-tperiod="month" data-i18n="period.month">Este mes</button>
|
|
77
|
+
<button type="button" class="period is-on" data-tperiod="quarter" data-i18n="period.quarter">3 meses</button>
|
|
73
78
|
</div>
|
|
74
79
|
</div>
|
|
75
80
|
|
|
@@ -82,13 +87,13 @@
|
|
|
82
87
|
<section class="view is-on" id="view-summary">
|
|
83
88
|
<div class="section-head">
|
|
84
89
|
<div>
|
|
85
|
-
<h1>Resumen</h1>
|
|
90
|
+
<h1 data-i18n="tab.summary">Resumen</h1>
|
|
86
91
|
<p class="sub" id="summary-range">…</p>
|
|
87
92
|
</div>
|
|
88
93
|
<div class="periods" id="periods">
|
|
89
|
-
<button type="button" class="period" data-period="week">Esta semana</button>
|
|
90
|
-
<button type="button" class="period is-on" data-period="month">Este mes</button>
|
|
91
|
-
<button type="button" class="period" data-period="quarter">3 meses</button>
|
|
94
|
+
<button type="button" class="period" data-period="week" data-i18n="period.week">Esta semana</button>
|
|
95
|
+
<button type="button" class="period is-on" data-period="month" data-i18n="period.month">Este mes</button>
|
|
96
|
+
<button type="button" class="period" data-period="quarter" data-i18n="period.quarter">3 meses</button>
|
|
92
97
|
</div>
|
|
93
98
|
</div>
|
|
94
99
|
|
|
@@ -99,22 +104,22 @@
|
|
|
99
104
|
<!-- ══════════════ MI DÍA ══════════════ -->
|
|
100
105
|
<section class="view" id="view-day">
|
|
101
106
|
<div class="daynav">
|
|
102
|
-
<button type="button" class="arrow" id="prev-day" aria-label="Día anterior">←</button>
|
|
107
|
+
<button type="button" class="arrow" id="prev-day" aria-label="Día anterior" data-i18n-aria-label="day.prev">←</button>
|
|
103
108
|
<div class="daynav-label">
|
|
104
109
|
<h1 id="day-title">…</h1>
|
|
105
|
-
<button type="button" class="today-link" id="go-today" hidden>Volver a hoy</button>
|
|
110
|
+
<button type="button" class="today-link" id="go-today" hidden data-i18n="day.goToday">Volver a hoy</button>
|
|
106
111
|
</div>
|
|
107
|
-
<button type="button" class="arrow" id="next-day" aria-label="Día siguiente">→</button>
|
|
112
|
+
<button type="button" class="arrow" id="next-day" aria-label="Día siguiente" data-i18n-aria-label="day.next">→</button>
|
|
108
113
|
</div>
|
|
109
114
|
|
|
110
115
|
<div class="hero" id="hero" hidden>
|
|
111
116
|
<div class="hero-main">
|
|
112
117
|
<div class="hero-value" id="day-hours">—</div>
|
|
113
|
-
<div class="hero-label" id="day-blocks">trabajadas</div>
|
|
118
|
+
<div class="hero-label" id="day-blocks" data-i18n="day.worked">trabajadas</div>
|
|
114
119
|
</div>
|
|
115
120
|
<div class="hero-main hero-money">
|
|
116
121
|
<div class="hero-value" id="day-amount">—</div>
|
|
117
|
-
<div class="hero-label" id="day-amount-label">registradas</div>
|
|
122
|
+
<div class="hero-label" id="day-amount-label" data-i18n="day.recorded">registradas</div>
|
|
118
123
|
</div>
|
|
119
124
|
</div>
|
|
120
125
|
|
|
@@ -122,7 +127,7 @@
|
|
|
122
127
|
|
|
123
128
|
<div class="approve" id="approve-bar" hidden>
|
|
124
129
|
<button type="button" class="approve-jump" id="approve-text"></button>
|
|
125
|
-
<button type="button" class="btn-main" id="approve-btn">Aprobar el día</button>
|
|
130
|
+
<button type="button" class="btn-main" id="approve-btn" data-i18n="day.approve">Aprobar el día</button>
|
|
126
131
|
</div>
|
|
127
132
|
</section>
|
|
128
133
|
|
|
@@ -130,8 +135,8 @@
|
|
|
130
135
|
<section class="view" id="view-projects">
|
|
131
136
|
<div class="section-head">
|
|
132
137
|
<div>
|
|
133
|
-
<h1>Proyectos</h1>
|
|
134
|
-
<p class="sub">Qué repositorios pertenecen a quién y a qué tarifa. Subir un precio
|
|
138
|
+
<h1 data-i18n="tab.projects">Proyectos</h1>
|
|
139
|
+
<p class="sub" data-i18n="projects.sub">Qué repositorios pertenecen a quién y a qué tarifa. Subir un precio
|
|
135
140
|
no reescribe lo ya trabajado: la tarifa nueva empieza el día que digas.</p>
|
|
136
141
|
</div>
|
|
137
142
|
</div>
|
|
@@ -142,8 +147,8 @@
|
|
|
142
147
|
<section class="view" id="view-reports">
|
|
143
148
|
<div class="section-head">
|
|
144
149
|
<div>
|
|
145
|
-
<h1>Informes</h1>
|
|
146
|
-
<p class="sub">Respaldo del trabajo hecho: horas y commits, para adjuntar a tu factura
|
|
150
|
+
<h1 data-i18n="tab.reports">Informes</h1>
|
|
151
|
+
<p class="sub" data-i18n="reports.sub">Respaldo del trabajo hecho: horas y commits, para adjuntar a tu factura
|
|
147
152
|
o compartir con quien dirige el proyecto.</p>
|
|
148
153
|
</div>
|
|
149
154
|
</div>
|
|
@@ -154,6 +159,7 @@
|
|
|
154
159
|
<div class="toast" id="toast" role="status" aria-live="polite"></div>
|
|
155
160
|
|
|
156
161
|
<script src="/lib.js"></script>
|
|
162
|
+
<script src="/i18n.js"></script>
|
|
157
163
|
<script src="/app.js"></script>
|
|
158
164
|
</body>
|
|
159
165
|
</html>
|
package/web/lib.js
CHANGED
|
@@ -10,11 +10,36 @@
|
|
|
10
10
|
* empaquetador de por medio. */
|
|
11
11
|
|
|
12
12
|
(function (root) {
|
|
13
|
-
const DAYS = ["domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"];
|
|
14
|
-
const MONTHS = ["enero", "febrero", "marzo", "abril", "mayo", "junio",
|
|
15
|
-
"julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"];
|
|
16
13
|
const SYMBOLS = { EUR: "€", USD: "$", GBP: "£", BRL: "R$" };
|
|
17
14
|
|
|
15
|
+
/* Lo que cambia con el idioma y no es una frase: nombres de días y meses,
|
|
16
|
+
cómo se titula un día y cómo se separan los decimales. Las frases viven en
|
|
17
|
+
i18n.js; esto se queda aquí porque lo usan funciones puras que se prueban
|
|
18
|
+
sin navegador. Español por defecto: es lo que asumen los tests de siempre. */
|
|
19
|
+
const LOCALES = {
|
|
20
|
+
es: {
|
|
21
|
+
tag: "es-ES",
|
|
22
|
+
days: ["domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"],
|
|
23
|
+
months: ["enero", "febrero", "marzo", "abril", "mayo", "junio",
|
|
24
|
+
"julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"],
|
|
25
|
+
today: "Hoy", yesterday: "Ayer",
|
|
26
|
+
dayTitle: (weekday, day, month) => `${weekday} ${day} de ${month}`,
|
|
27
|
+
},
|
|
28
|
+
en: {
|
|
29
|
+
tag: "en-US",
|
|
30
|
+
days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
|
|
31
|
+
months: ["January", "February", "March", "April", "May", "June",
|
|
32
|
+
"July", "August", "September", "October", "November", "December"],
|
|
33
|
+
today: "Today", yesterday: "Yesterday",
|
|
34
|
+
dayTitle: (weekday, day, month) => `${weekday}, ${month} ${day}`,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
let locale = LOCALES.es;
|
|
38
|
+
|
|
39
|
+
function setLocale(lang) { locale = LOCALES[lang] || LOCALES.es; }
|
|
40
|
+
/** Etiqueta BCP 47 para toLocaleString y compañía: "es-ES" o "en-US". */
|
|
41
|
+
function localeTag() { return locale.tag; }
|
|
42
|
+
|
|
18
43
|
/** Fecha local en YYYY-MM-DD. Nunca `toISOString()` a secas: eso da la de Greenwich. */
|
|
19
44
|
function localDay(date) {
|
|
20
45
|
return new Date(date.getTime() - date.getTimezoneOffset() * 60000)
|
|
@@ -56,7 +81,7 @@
|
|
|
56
81
|
/** Importe desde unidades menores. `null` cuando no hay dato, no "0". */
|
|
57
82
|
function fmtMoney(minor, currency) {
|
|
58
83
|
if (minor === null || minor === undefined) return null;
|
|
59
|
-
const value = (minor / 100).toLocaleString(
|
|
84
|
+
const value = (minor / 100).toLocaleString(locale.tag, {
|
|
60
85
|
minimumFractionDigits: 2, maximumFractionDigits: 2,
|
|
61
86
|
});
|
|
62
87
|
const symbol = SYMBOLS[currency];
|
|
@@ -64,10 +89,10 @@
|
|
|
64
89
|
}
|
|
65
90
|
|
|
66
91
|
function fmtDayTitle(iso, now = new Date()) {
|
|
67
|
-
if (iso === localToday(0, now)) return
|
|
68
|
-
if (iso === localToday(-1, now)) return
|
|
92
|
+
if (iso === localToday(0, now)) return locale.today;
|
|
93
|
+
if (iso === localToday(-1, now)) return locale.yesterday;
|
|
69
94
|
const d = new Date(`${iso}T12:00:00`);
|
|
70
|
-
return
|
|
95
|
+
return locale.dayTitle(locale.days[d.getDay()], d.getDate(), locale.months[d.getMonth()]);
|
|
71
96
|
}
|
|
72
97
|
|
|
73
98
|
/** Rango de un periodo. "all" devuelve vacío: todo lo pendiente, sin acotar. */
|
|
@@ -86,7 +111,7 @@
|
|
|
86
111
|
({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c]));
|
|
87
112
|
}
|
|
88
113
|
|
|
89
|
-
const api = {
|
|
114
|
+
const api = { LOCALES, setLocale, localeTag, localDay, localToday, shiftDay, fmtDuration,
|
|
90
115
|
fmtMoney, fmtDayTitle, periodRange, esc };
|
|
91
116
|
|
|
92
117
|
if (typeof module !== "undefined" && module.exports) module.exports = api;
|