@unbrained/pm-web 2026.7.11 → 2026.7.17-1
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/CHANGELOG.md +19 -0
- package/README.md +26 -0
- package/dist/app.d.ts +16 -1
- package/dist/app.js +53 -3
- package/dist/app.js.map +1 -1
- package/dist/auth.d.ts +2 -1
- package/dist/auth.js +10 -0
- package/dist/auth.js.map +1 -1
- package/dist/db.js +17 -1
- package/dist/db.js.map +1 -1
- package/dist/ical.js.map +1 -1
- package/dist/index.d.ts +1 -22
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/dist/oidc.d.ts +89 -0
- package/dist/oidc.js +305 -0
- package/dist/oidc.js.map +1 -0
- package/dist/routes/auth.js +3 -15
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/github.js +3 -3
- package/dist/routes/github.js.map +1 -1
- package/dist/routes/oidc.d.ts +4 -0
- package/dist/routes/oidc.js +147 -0
- package/dist/routes/oidc.js.map +1 -0
- package/dist/routes/pm.js +172 -108
- package/dist/routes/pm.js.map +1 -1
- package/dist/routes/projects.js +9 -2
- package/dist/routes/projects.js.map +1 -1
- package/dist/server.js +7 -2
- package/dist/server.js.map +1 -1
- package/dist/services/pm-runner.d.ts +27 -3
- package/dist/services/pm-runner.js +188 -54
- package/dist/services/pm-runner.js.map +1 -1
- package/dist/services/realtime-bus.d.ts +1 -0
- package/dist/services/realtime-bus.js +148 -0
- package/dist/services/realtime-bus.js.map +1 -0
- package/dist/services/sse.d.ts +3 -1
- package/dist/services/sse.js +83 -48
- package/dist/services/sse.js.map +1 -1
- package/manifest.json +1 -1
- package/package.json +11 -11
- package/public/cookie-consent.js +54 -39
- package/public/cookie-settings.html +7 -7
- package/public/index.html +32 -26
- package/public/legal-notice.html +10 -12
- package/public/privacy-policy.html +14 -24
- package/public/src/app.js +18 -4
- package/public/src/app.js.map +1 -1
- package/public/src/app.ts +19 -4
- package/public/src/components/modals.js +5 -3
- package/public/src/components/modals.js.map +1 -1
- package/public/src/components/modals.ts +6 -3
- package/public/src/components/toast.js.map +1 -1
- package/public/src/cookie-consent.ts +68 -0
- package/public/src/i18n/de.json +117 -0
- package/public/src/i18n/en.json +117 -0
- package/public/src/i18n/es.json +117 -0
- package/public/src/i18n/zh.json +117 -0
- package/public/src/i18n.js +287 -0
- package/public/src/i18n.js.map +1 -0
- package/public/src/i18n.ts +306 -0
- package/public/src/sw.ts +446 -0
- package/public/src/views/auth.js +29 -6
- package/public/src/views/auth.js.map +1 -1
- package/public/src/views/auth.ts +27 -6
- package/public/src/views/graph.js.map +1 -1
- package/public/src/views/settings.js +73 -48
- package/public/src/views/settings.js.map +1 -1
- package/public/src/views/settings.ts +77 -48
- package/public/styles.css +2 -0
- package/public/sw.js +323 -256
- package/public/terms.html +7 -9
- package/public/tsconfig.json +1 -1
- package/public/tsconfig.scripts.json +18 -0
- package/public/tsconfig.sw.json +18 -0
- package/sql/schema.sql +16 -0
|
@@ -6,6 +6,7 @@ import { api } from '../api.js';
|
|
|
6
6
|
import { escHtml } from '../utils.js';
|
|
7
7
|
import { toast } from '../components/toast.js';
|
|
8
8
|
import { confirmDialog } from '../components/modals.js';
|
|
9
|
+
import { t, translateError, localeDate, getLocale, SUPPORTED_LOCALES } from '../i18n.js';
|
|
9
10
|
function avatarInitial(name) {
|
|
10
11
|
return (name.trim()[0] || '?').toUpperCase();
|
|
11
12
|
}
|
|
@@ -17,21 +18,45 @@ function avatarBg(seed) {
|
|
|
17
18
|
const hue = hash % 360;
|
|
18
19
|
return `hsl(${hue},55%,45%)`;
|
|
19
20
|
}
|
|
21
|
+
/** Compile-time-complete mapping from supported locale → settings label key. */
|
|
22
|
+
const LOCALE_LABEL_KEYS = {
|
|
23
|
+
en: 'settings.languageEn',
|
|
24
|
+
de: 'settings.languageDe',
|
|
25
|
+
es: 'settings.languageEs',
|
|
26
|
+
zh: 'settings.languageZh',
|
|
27
|
+
};
|
|
20
28
|
export function renderSettingsView() {
|
|
21
29
|
const el = document.getElementById('content-settings');
|
|
22
30
|
if (!el)
|
|
23
31
|
return;
|
|
24
32
|
const u = state.user || {};
|
|
25
33
|
const createdInfo = u.created_at
|
|
26
|
-
? `<span style="display:block;margin-top:4px;font-size:12px;color:var(--text-muted)"
|
|
34
|
+
? `<span style="display:block;margin-top:4px;font-size:12px;color:var(--text-muted)">${escHtml(t('settings.accountCreated', { date: localeDate(u.created_at, { year: 'numeric', month: 'long', day: 'numeric' }) }))}</span>`
|
|
27
35
|
: '';
|
|
36
|
+
const currentLocale = getLocale();
|
|
37
|
+
const langOptions = SUPPORTED_LOCALES.map((loc) => {
|
|
38
|
+
const label = t(LOCALE_LABEL_KEYS[loc]);
|
|
39
|
+
return `<option value="${loc}"${loc === currentLocale ? ' selected' : ''}>${escHtml(label)}</option>`;
|
|
40
|
+
}).join('');
|
|
28
41
|
el.innerHTML = `
|
|
29
42
|
<div class="page-header">
|
|
30
|
-
<div><div class="page-title"
|
|
43
|
+
<div><div class="page-title">${escHtml(t('settings.title'))}</div><div class="page-subtitle">${escHtml(t('settings.subtitle'))}</div></div>
|
|
31
44
|
</div>
|
|
32
45
|
<div style="max-width:560px;display:flex;flex-direction:column;gap:20px">
|
|
33
46
|
<div class="card">
|
|
34
|
-
<div class="card-header"><div class="card-title"
|
|
47
|
+
<div class="card-header"><div class="card-title">${escHtml(t('settings.language'))}</div></div>
|
|
48
|
+
<div class="card-body">
|
|
49
|
+
<div class="form-group">
|
|
50
|
+
<label class="form-label" for="settings-language">${escHtml(t('settings.language'))}</label>
|
|
51
|
+
<select class="form-input" id="settings-language" onchange="window.__app.changeLanguage(this.value)" aria-label="${escHtml(t('settings.language'))}">
|
|
52
|
+
${langOptions}
|
|
53
|
+
</select>
|
|
54
|
+
<div style="font-size:12px;color:var(--text-muted);margin-top:6px">${escHtml(t('settings.languageHint'))}</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
<div class="card">
|
|
59
|
+
<div class="card-header"><div class="card-title">${escHtml(t('settings.profile'))}</div></div>
|
|
35
60
|
<div class="card-body">
|
|
36
61
|
<div style="display:flex;align-items:center;gap:16px;margin-bottom:20px">
|
|
37
62
|
<div style="width:64px;height:64px;border-radius:50%;background:${avatarBg(u.email || u.display_name || '?')};display:flex;align-items:center;justify-content:center;font-size:24px;font-weight:700;color:#fff;flex-shrink:0;user-select:none" aria-hidden="true">${escHtml(avatarInitial(u.display_name || u.email || '?'))}</div>
|
|
@@ -41,60 +66,60 @@ export function renderSettingsView() {
|
|
|
41
66
|
</div>
|
|
42
67
|
</div>
|
|
43
68
|
<div class="form-group">
|
|
44
|
-
<label class="form-label" for="settings-display-name"
|
|
45
|
-
<input class="form-input" id="settings-display-name" type="text" value="${escHtml(u.display_name || u.email || '')}" placeholder="
|
|
69
|
+
<label class="form-label" for="settings-display-name">${escHtml(t('settings.displayName'))}</label>
|
|
70
|
+
<input class="form-input" id="settings-display-name" type="text" value="${escHtml(u.display_name || u.email || '')}" placeholder="${escHtml(t('settings.displayNamePlaceholder'))}" aria-label="${escHtml(t('settings.displayName'))}">
|
|
46
71
|
</div>
|
|
47
72
|
<div class="form-group">
|
|
48
|
-
<label class="form-label"
|
|
49
|
-
<input class="form-input" type="text" value="${escHtml(u.email || '')}" disabled style="opacity:0.6;cursor:not-allowed" aria-label="
|
|
73
|
+
<label class="form-label">${escHtml(t('settings.email'))}</label>
|
|
74
|
+
<input class="form-input" type="text" value="${escHtml(u.email || '')}" disabled style="opacity:0.6;cursor:not-allowed" aria-label="${escHtml(t('settings.emailReadonly'))}">
|
|
50
75
|
${createdInfo}
|
|
51
76
|
</div>
|
|
52
77
|
<div class="form-error" id="settings-profile-error" style="display:none" role="alert"></div>
|
|
53
|
-
<button class="btn btn-primary btn-sm" id="settings-profile-btn" onclick="window.__app.saveProfile()" aria-label="
|
|
78
|
+
<button class="btn btn-primary btn-sm" id="settings-profile-btn" onclick="window.__app.saveProfile()" aria-label="${escHtml(t('settings.saveProfile'))}"><span>${escHtml(t('settings.saveProfile'))}</span></button>
|
|
54
79
|
</div>
|
|
55
80
|
</div>
|
|
56
81
|
<div class="card">
|
|
57
|
-
<div class="card-header"><div class="card-title"
|
|
82
|
+
<div class="card-header"><div class="card-title">${escHtml(t('settings.changePassword'))}</div></div>
|
|
58
83
|
<div class="card-body">
|
|
59
84
|
<div class="form-group">
|
|
60
|
-
<label class="form-label" for="settings-current-pw"
|
|
61
|
-
<input class="form-input" id="settings-current-pw" type="password" placeholder="
|
|
85
|
+
<label class="form-label" for="settings-current-pw">${escHtml(t('settings.currentPassword'))}</label>
|
|
86
|
+
<input class="form-input" id="settings-current-pw" type="password" placeholder="${escHtml(t('settings.currentPasswordPlaceholder'))}" autocomplete="current-password" aria-label="${escHtml(t('settings.currentPassword'))}">
|
|
62
87
|
</div>
|
|
63
88
|
<div class="form-group">
|
|
64
|
-
<label class="form-label" for="settings-new-pw"
|
|
65
|
-
<input class="form-input" id="settings-new-pw" type="password" placeholder="
|
|
89
|
+
<label class="form-label" for="settings-new-pw">${escHtml(t('settings.newPassword'))}</label>
|
|
90
|
+
<input class="form-input" id="settings-new-pw" type="password" placeholder="${escHtml(t('settings.newPasswordPlaceholder'))}" autocomplete="new-password" aria-label="${escHtml(t('settings.newPassword'))}">
|
|
66
91
|
</div>
|
|
67
92
|
<div class="form-group">
|
|
68
|
-
<label class="form-label" for="settings-confirm-pw"
|
|
69
|
-
<input class="form-input" id="settings-confirm-pw" type="password" placeholder="
|
|
93
|
+
<label class="form-label" for="settings-confirm-pw">${escHtml(t('settings.confirmPassword'))}</label>
|
|
94
|
+
<input class="form-input" id="settings-confirm-pw" type="password" placeholder="${escHtml(t('settings.confirmPasswordPlaceholder'))}" autocomplete="new-password" aria-label="${escHtml(t('settings.confirmPassword'))}">
|
|
70
95
|
</div>
|
|
71
96
|
<div class="form-error" id="settings-pw-error" style="display:none" role="alert"></div>
|
|
72
|
-
<button class="btn btn-primary btn-sm" id="settings-pw-btn" onclick="window.__app.changePassword()" aria-label="
|
|
97
|
+
<button class="btn btn-primary btn-sm" id="settings-pw-btn" onclick="window.__app.changePassword()" aria-label="${escHtml(t('settings.changePassword'))}"><span>${escHtml(t('settings.changePassword'))}</span></button>
|
|
73
98
|
</div>
|
|
74
99
|
</div>
|
|
75
100
|
<div class="card">
|
|
76
101
|
<div class="card-header">
|
|
77
|
-
<div class="card-title"
|
|
78
|
-
${u.has_github_token ? `<span style="font-size:12px;color:var(--status-closed)"
|
|
102
|
+
<div class="card-title">${escHtml(t('settings.githubToken'))}</div>
|
|
103
|
+
${u.has_github_token ? `<span style="font-size:12px;color:var(--status-closed)">${escHtml(t('settings.tokenConfigured'))}</span>` : `<span style="font-size:12px;color:var(--text-muted)">${escHtml(t('settings.tokenNotSet'))}</span>`}
|
|
79
104
|
</div>
|
|
80
105
|
<div class="card-body">
|
|
81
106
|
<div style="margin-bottom:12px;padding:10px 12px;background:var(--bg-input);border:1px solid var(--border);border-radius:var(--radius);font-size:12px;color:var(--text-secondary)">
|
|
82
|
-
<strong style="color:var(--text-primary)"
|
|
107
|
+
<strong style="color:var(--text-primary)">${escHtml(t('settings.howToGet'))}</strong>
|
|
83
108
|
<ol style="margin-top:6px;padding-left:18px;line-height:1.8">
|
|
84
|
-
<li
|
|
85
|
-
<li
|
|
86
|
-
<li
|
|
109
|
+
<li>${escHtml(t('settings.tokenStep1'))}</li>
|
|
110
|
+
<li>${escHtml(t('settings.tokenStep2'))}</li>
|
|
111
|
+
<li>${escHtml(t('settings.tokenStep3'))}</li>
|
|
87
112
|
</ol>
|
|
88
113
|
</div>
|
|
89
114
|
<div class="form-group">
|
|
90
|
-
<label class="form-label" for="settings-github-token"
|
|
91
|
-
<input class="form-input" id="settings-github-token" type="password" placeholder="${u.has_github_token ? '
|
|
92
|
-
<div style="font-size:11px;color:var(--text-muted);margin-top:4px"
|
|
115
|
+
<label class="form-label" for="settings-github-token">${escHtml(t('settings.tokenLabel'))}</label>
|
|
116
|
+
<input class="form-input" id="settings-github-token" type="password" placeholder="${escHtml(u.has_github_token ? t('settings.tokenPlaceholder.keep') : t('settings.tokenPlaceholder.set'))}" autocomplete="off" aria-label="${escHtml(t('settings.tokenLabel'))}">
|
|
117
|
+
<div style="font-size:11px;color:var(--text-muted);margin-top:4px">${t('settings.tokenHint')}</div>
|
|
93
118
|
</div>
|
|
94
119
|
<div class="form-error" id="settings-github-error" style="display:none" role="alert"></div>
|
|
95
120
|
<div style="display:flex;gap:8px">
|
|
96
|
-
<button class="btn btn-primary btn-sm" id="settings-github-btn" onclick="window.__app.saveGitHubToken()" aria-label="
|
|
97
|
-
${u.has_github_token ? `<button class="btn btn-danger btn-sm" onclick="window.__app.clearGitHubToken()" aria-label="
|
|
121
|
+
<button class="btn btn-primary btn-sm" id="settings-github-btn" onclick="window.__app.saveGitHubToken()" aria-label="${escHtml(t('settings.saveToken'))}"><span>${escHtml(t('settings.saveToken'))}</span></button>
|
|
122
|
+
${u.has_github_token ? `<button class="btn btn-danger btn-sm" onclick="window.__app.clearGitHubToken()" aria-label="${escHtml(t('settings.clearToken'))}">${escHtml(t('settings.clearToken'))}</button>` : ''}
|
|
98
123
|
</div>
|
|
99
124
|
</div>
|
|
100
125
|
</div>
|
|
@@ -106,7 +131,7 @@ export async function saveProfile() {
|
|
|
106
131
|
const btn = document.getElementById('settings-profile-btn');
|
|
107
132
|
if (!displayName) {
|
|
108
133
|
if (errEl) {
|
|
109
|
-
errEl.textContent = '
|
|
134
|
+
errEl.textContent = t('settings.displayNameEmpty');
|
|
110
135
|
errEl.style.display = 'block';
|
|
111
136
|
}
|
|
112
137
|
return;
|
|
@@ -117,7 +142,7 @@ export async function saveProfile() {
|
|
|
117
142
|
btn.disabled = true;
|
|
118
143
|
const sp = btn.querySelector('span');
|
|
119
144
|
if (sp)
|
|
120
|
-
sp.textContent = '
|
|
145
|
+
sp.textContent = t('settings.saving');
|
|
121
146
|
}
|
|
122
147
|
try {
|
|
123
148
|
const data = await api('PATCH', '/auth/profile', { displayName });
|
|
@@ -135,12 +160,12 @@ export async function saveProfile() {
|
|
|
135
160
|
const nameEl = document.getElementById('user-name-display');
|
|
136
161
|
if (nameEl)
|
|
137
162
|
nameEl.textContent = u.display_name || u.email;
|
|
138
|
-
toast('
|
|
163
|
+
toast(t('settings.profileSaved'), 'success');
|
|
139
164
|
renderSettingsView();
|
|
140
165
|
}
|
|
141
166
|
catch (err) {
|
|
142
167
|
if (errEl) {
|
|
143
|
-
errEl.textContent = err instanceof Error ? err.message : String(err);
|
|
168
|
+
errEl.textContent = translateError(err instanceof Error ? err.message : String(err));
|
|
144
169
|
errEl.style.display = 'block';
|
|
145
170
|
}
|
|
146
171
|
}
|
|
@@ -149,7 +174,7 @@ export async function saveProfile() {
|
|
|
149
174
|
btn.disabled = false;
|
|
150
175
|
const sp = btn.querySelector('span');
|
|
151
176
|
if (sp)
|
|
152
|
-
sp.textContent = '
|
|
177
|
+
sp.textContent = t('settings.saveProfile');
|
|
153
178
|
}
|
|
154
179
|
}
|
|
155
180
|
}
|
|
@@ -163,21 +188,21 @@ export async function changePassword() {
|
|
|
163
188
|
errEl.style.display = 'none';
|
|
164
189
|
if (!currentPassword || !newPassword || !confirmPassword) {
|
|
165
190
|
if (errEl) {
|
|
166
|
-
errEl.textContent = '
|
|
191
|
+
errEl.textContent = t('settings.allFieldsRequired');
|
|
167
192
|
errEl.style.display = 'block';
|
|
168
193
|
}
|
|
169
194
|
return;
|
|
170
195
|
}
|
|
171
196
|
if (newPassword !== confirmPassword) {
|
|
172
197
|
if (errEl) {
|
|
173
|
-
errEl.textContent = '
|
|
198
|
+
errEl.textContent = t('settings.passwordsDoNotMatch');
|
|
174
199
|
errEl.style.display = 'block';
|
|
175
200
|
}
|
|
176
201
|
return;
|
|
177
202
|
}
|
|
178
203
|
if (newPassword.length < 6) {
|
|
179
204
|
if (errEl) {
|
|
180
|
-
errEl.textContent = '
|
|
205
|
+
errEl.textContent = t('settings.passwordTooShort');
|
|
181
206
|
errEl.style.display = 'block';
|
|
182
207
|
}
|
|
183
208
|
return;
|
|
@@ -186,11 +211,11 @@ export async function changePassword() {
|
|
|
186
211
|
btn.disabled = true;
|
|
187
212
|
const sp = btn.querySelector('span');
|
|
188
213
|
if (sp)
|
|
189
|
-
sp.textContent = '
|
|
214
|
+
sp.textContent = t('settings.changing');
|
|
190
215
|
}
|
|
191
216
|
try {
|
|
192
217
|
await api('POST', '/auth/change-password', { currentPassword, newPassword });
|
|
193
|
-
toast('
|
|
218
|
+
toast(t('settings.passwordChanged'), 'success');
|
|
194
219
|
const curEl = document.getElementById('settings-current-pw');
|
|
195
220
|
const newEl = document.getElementById('settings-new-pw');
|
|
196
221
|
const confEl = document.getElementById('settings-confirm-pw');
|
|
@@ -203,7 +228,7 @@ export async function changePassword() {
|
|
|
203
228
|
}
|
|
204
229
|
catch (err) {
|
|
205
230
|
if (errEl) {
|
|
206
|
-
errEl.textContent = err instanceof Error ? err.message : String(err);
|
|
231
|
+
errEl.textContent = translateError(err instanceof Error ? err.message : String(err));
|
|
207
232
|
errEl.style.display = 'block';
|
|
208
233
|
}
|
|
209
234
|
}
|
|
@@ -212,7 +237,7 @@ export async function changePassword() {
|
|
|
212
237
|
btn.disabled = false;
|
|
213
238
|
const sp = btn.querySelector('span');
|
|
214
239
|
if (sp)
|
|
215
|
-
sp.textContent = '
|
|
240
|
+
sp.textContent = t('settings.changePassword');
|
|
216
241
|
}
|
|
217
242
|
}
|
|
218
243
|
}
|
|
@@ -222,7 +247,7 @@ export async function saveGitHubToken() {
|
|
|
222
247
|
const btn = document.getElementById('settings-github-btn');
|
|
223
248
|
if (!token) {
|
|
224
249
|
if (errEl) {
|
|
225
|
-
errEl.textContent = '
|
|
250
|
+
errEl.textContent = t('settings.tokenEmpty');
|
|
226
251
|
errEl.style.display = 'block';
|
|
227
252
|
}
|
|
228
253
|
return;
|
|
@@ -233,17 +258,17 @@ export async function saveGitHubToken() {
|
|
|
233
258
|
btn.disabled = true;
|
|
234
259
|
const sp = btn.querySelector('span');
|
|
235
260
|
if (sp)
|
|
236
|
-
sp.textContent = '
|
|
261
|
+
sp.textContent = t('settings.saving');
|
|
237
262
|
}
|
|
238
263
|
try {
|
|
239
264
|
const data = await api('PATCH', '/auth/github-token', { token });
|
|
240
265
|
state.user.has_github_token = data.hasToken !== undefined ? data.hasToken : true;
|
|
241
|
-
toast('
|
|
266
|
+
toast(t('settings.tokenSaved'), 'success');
|
|
242
267
|
renderSettingsView();
|
|
243
268
|
}
|
|
244
269
|
catch (err) {
|
|
245
270
|
if (errEl) {
|
|
246
|
-
errEl.textContent = err instanceof Error ? err.message : String(err);
|
|
271
|
+
errEl.textContent = translateError(err instanceof Error ? err.message : String(err));
|
|
247
272
|
errEl.style.display = 'block';
|
|
248
273
|
}
|
|
249
274
|
}
|
|
@@ -252,21 +277,21 @@ export async function saveGitHubToken() {
|
|
|
252
277
|
btn.disabled = false;
|
|
253
278
|
const sp = btn.querySelector('span');
|
|
254
279
|
if (sp)
|
|
255
|
-
sp.textContent = '
|
|
280
|
+
sp.textContent = t('settings.saveToken');
|
|
256
281
|
}
|
|
257
282
|
}
|
|
258
283
|
}
|
|
259
284
|
export function clearGitHubToken() {
|
|
260
|
-
confirmDialog('
|
|
285
|
+
confirmDialog(t('settings.clearTokenTitle'), t('settings.clearTokenBody'), async () => {
|
|
261
286
|
try {
|
|
262
287
|
const data = await api('PATCH', '/auth/github-token', { token: '' });
|
|
263
288
|
state.user.has_github_token = false;
|
|
264
|
-
toast('
|
|
289
|
+
toast(t('settings.tokenCleared'), 'success');
|
|
265
290
|
renderSettingsView();
|
|
266
291
|
}
|
|
267
292
|
catch (err) {
|
|
268
|
-
toast(err instanceof Error ? err.message : String(err), 'error');
|
|
293
|
+
toast(translateError(err instanceof Error ? err.message : String(err)), 'error');
|
|
269
294
|
}
|
|
270
|
-
});
|
|
295
|
+
}, false, { cancel: t('dialog.cancel'), confirm: t('dialog.confirm') });
|
|
271
296
|
}
|
|
272
297
|
//# sourceMappingURL=settings.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.js","sourceRoot":"","sources":["settings.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["settings.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ import { api } from '../api.js';
|
|
|
6
6
|
import { escHtml } from '../utils.js';
|
|
7
7
|
import { toast } from '../components/toast.js';
|
|
8
8
|
import { confirmDialog } from '../components/modals.js';
|
|
9
|
+
import { t, translateError, localeDate, getLocale, SUPPORTED_LOCALES, type SupportedLocale } from '../i18n.js';
|
|
9
10
|
|
|
10
11
|
function avatarInitial(name: string): string {
|
|
11
12
|
return (name.trim()[0] || '?').toUpperCase();
|
|
@@ -18,20 +19,45 @@ function avatarBg(seed: string): string {
|
|
|
18
19
|
return `hsl(${hue},55%,45%)`;
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
/** Compile-time-complete mapping from supported locale → settings label key. */
|
|
23
|
+
const LOCALE_LABEL_KEYS: Record<SupportedLocale, string> = {
|
|
24
|
+
en: 'settings.languageEn',
|
|
25
|
+
de: 'settings.languageDe',
|
|
26
|
+
es: 'settings.languageEs',
|
|
27
|
+
zh: 'settings.languageZh',
|
|
28
|
+
};
|
|
29
|
+
|
|
21
30
|
export function renderSettingsView(): void {
|
|
22
31
|
const el = document.getElementById('content-settings');
|
|
23
32
|
if (!el) return;
|
|
24
33
|
const u = state.user || ({} as any);
|
|
25
34
|
const createdInfo = u.created_at
|
|
26
|
-
? `<span style="display:block;margin-top:4px;font-size:12px;color:var(--text-muted)"
|
|
35
|
+
? `<span style="display:block;margin-top:4px;font-size:12px;color:var(--text-muted)">${escHtml(t('settings.accountCreated', { date: localeDate(u.created_at, { year: 'numeric', month: 'long', day: 'numeric' }) }))}</span>`
|
|
27
36
|
: '';
|
|
37
|
+
const currentLocale = getLocale();
|
|
38
|
+
const langOptions = SUPPORTED_LOCALES.map((loc) => {
|
|
39
|
+
const label = t(LOCALE_LABEL_KEYS[loc]);
|
|
40
|
+
return `<option value="${loc}"${loc === currentLocale ? ' selected' : ''}>${escHtml(label)}</option>`;
|
|
41
|
+
}).join('');
|
|
28
42
|
el.innerHTML = `
|
|
29
43
|
<div class="page-header">
|
|
30
|
-
<div><div class="page-title"
|
|
44
|
+
<div><div class="page-title">${escHtml(t('settings.title'))}</div><div class="page-subtitle">${escHtml(t('settings.subtitle'))}</div></div>
|
|
31
45
|
</div>
|
|
32
46
|
<div style="max-width:560px;display:flex;flex-direction:column;gap:20px">
|
|
33
47
|
<div class="card">
|
|
34
|
-
<div class="card-header"><div class="card-title"
|
|
48
|
+
<div class="card-header"><div class="card-title">${escHtml(t('settings.language'))}</div></div>
|
|
49
|
+
<div class="card-body">
|
|
50
|
+
<div class="form-group">
|
|
51
|
+
<label class="form-label" for="settings-language">${escHtml(t('settings.language'))}</label>
|
|
52
|
+
<select class="form-input" id="settings-language" onchange="window.__app.changeLanguage(this.value)" aria-label="${escHtml(t('settings.language'))}">
|
|
53
|
+
${langOptions}
|
|
54
|
+
</select>
|
|
55
|
+
<div style="font-size:12px;color:var(--text-muted);margin-top:6px">${escHtml(t('settings.languageHint'))}</div>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
<div class="card">
|
|
60
|
+
<div class="card-header"><div class="card-title">${escHtml(t('settings.profile'))}</div></div>
|
|
35
61
|
<div class="card-body">
|
|
36
62
|
<div style="display:flex;align-items:center;gap:16px;margin-bottom:20px">
|
|
37
63
|
<div style="width:64px;height:64px;border-radius:50%;background:${avatarBg(u.email||u.display_name||'?')};display:flex;align-items:center;justify-content:center;font-size:24px;font-weight:700;color:#fff;flex-shrink:0;user-select:none" aria-hidden="true">${escHtml(avatarInitial(u.display_name||u.email||'?'))}</div>
|
|
@@ -41,60 +67,60 @@ export function renderSettingsView(): void {
|
|
|
41
67
|
</div>
|
|
42
68
|
</div>
|
|
43
69
|
<div class="form-group">
|
|
44
|
-
<label class="form-label" for="settings-display-name"
|
|
45
|
-
<input class="form-input" id="settings-display-name" type="text" value="${escHtml(u.display_name||u.email||'')}" placeholder="
|
|
70
|
+
<label class="form-label" for="settings-display-name">${escHtml(t('settings.displayName'))}</label>
|
|
71
|
+
<input class="form-input" id="settings-display-name" type="text" value="${escHtml(u.display_name||u.email||'')}" placeholder="${escHtml(t('settings.displayNamePlaceholder'))}" aria-label="${escHtml(t('settings.displayName'))}">
|
|
46
72
|
</div>
|
|
47
73
|
<div class="form-group">
|
|
48
|
-
<label class="form-label"
|
|
49
|
-
<input class="form-input" type="text" value="${escHtml(u.email||'')}" disabled style="opacity:0.6;cursor:not-allowed" aria-label="
|
|
74
|
+
<label class="form-label">${escHtml(t('settings.email'))}</label>
|
|
75
|
+
<input class="form-input" type="text" value="${escHtml(u.email||'')}" disabled style="opacity:0.6;cursor:not-allowed" aria-label="${escHtml(t('settings.emailReadonly'))}">
|
|
50
76
|
${createdInfo}
|
|
51
77
|
</div>
|
|
52
78
|
<div class="form-error" id="settings-profile-error" style="display:none" role="alert"></div>
|
|
53
|
-
<button class="btn btn-primary btn-sm" id="settings-profile-btn" onclick="window.__app.saveProfile()" aria-label="
|
|
79
|
+
<button class="btn btn-primary btn-sm" id="settings-profile-btn" onclick="window.__app.saveProfile()" aria-label="${escHtml(t('settings.saveProfile'))}"><span>${escHtml(t('settings.saveProfile'))}</span></button>
|
|
54
80
|
</div>
|
|
55
81
|
</div>
|
|
56
82
|
<div class="card">
|
|
57
|
-
<div class="card-header"><div class="card-title"
|
|
83
|
+
<div class="card-header"><div class="card-title">${escHtml(t('settings.changePassword'))}</div></div>
|
|
58
84
|
<div class="card-body">
|
|
59
85
|
<div class="form-group">
|
|
60
|
-
<label class="form-label" for="settings-current-pw"
|
|
61
|
-
<input class="form-input" id="settings-current-pw" type="password" placeholder="
|
|
86
|
+
<label class="form-label" for="settings-current-pw">${escHtml(t('settings.currentPassword'))}</label>
|
|
87
|
+
<input class="form-input" id="settings-current-pw" type="password" placeholder="${escHtml(t('settings.currentPasswordPlaceholder'))}" autocomplete="current-password" aria-label="${escHtml(t('settings.currentPassword'))}">
|
|
62
88
|
</div>
|
|
63
89
|
<div class="form-group">
|
|
64
|
-
<label class="form-label" for="settings-new-pw"
|
|
65
|
-
<input class="form-input" id="settings-new-pw" type="password" placeholder="
|
|
90
|
+
<label class="form-label" for="settings-new-pw">${escHtml(t('settings.newPassword'))}</label>
|
|
91
|
+
<input class="form-input" id="settings-new-pw" type="password" placeholder="${escHtml(t('settings.newPasswordPlaceholder'))}" autocomplete="new-password" aria-label="${escHtml(t('settings.newPassword'))}">
|
|
66
92
|
</div>
|
|
67
93
|
<div class="form-group">
|
|
68
|
-
<label class="form-label" for="settings-confirm-pw"
|
|
69
|
-
<input class="form-input" id="settings-confirm-pw" type="password" placeholder="
|
|
94
|
+
<label class="form-label" for="settings-confirm-pw">${escHtml(t('settings.confirmPassword'))}</label>
|
|
95
|
+
<input class="form-input" id="settings-confirm-pw" type="password" placeholder="${escHtml(t('settings.confirmPasswordPlaceholder'))}" autocomplete="new-password" aria-label="${escHtml(t('settings.confirmPassword'))}">
|
|
70
96
|
</div>
|
|
71
97
|
<div class="form-error" id="settings-pw-error" style="display:none" role="alert"></div>
|
|
72
|
-
<button class="btn btn-primary btn-sm" id="settings-pw-btn" onclick="window.__app.changePassword()" aria-label="
|
|
98
|
+
<button class="btn btn-primary btn-sm" id="settings-pw-btn" onclick="window.__app.changePassword()" aria-label="${escHtml(t('settings.changePassword'))}"><span>${escHtml(t('settings.changePassword'))}</span></button>
|
|
73
99
|
</div>
|
|
74
100
|
</div>
|
|
75
101
|
<div class="card">
|
|
76
102
|
<div class="card-header">
|
|
77
|
-
<div class="card-title"
|
|
78
|
-
${u.has_github_token ? `<span style="font-size:12px;color:var(--status-closed)"
|
|
103
|
+
<div class="card-title">${escHtml(t('settings.githubToken'))}</div>
|
|
104
|
+
${u.has_github_token ? `<span style="font-size:12px;color:var(--status-closed)">${escHtml(t('settings.tokenConfigured'))}</span>` : `<span style="font-size:12px;color:var(--text-muted)">${escHtml(t('settings.tokenNotSet'))}</span>`}
|
|
79
105
|
</div>
|
|
80
106
|
<div class="card-body">
|
|
81
107
|
<div style="margin-bottom:12px;padding:10px 12px;background:var(--bg-input);border:1px solid var(--border);border-radius:var(--radius);font-size:12px;color:var(--text-secondary)">
|
|
82
|
-
<strong style="color:var(--text-primary)"
|
|
108
|
+
<strong style="color:var(--text-primary)">${escHtml(t('settings.howToGet'))}</strong>
|
|
83
109
|
<ol style="margin-top:6px;padding-left:18px;line-height:1.8">
|
|
84
|
-
<li
|
|
85
|
-
<li
|
|
86
|
-
<li
|
|
110
|
+
<li>${escHtml(t('settings.tokenStep1'))}</li>
|
|
111
|
+
<li>${escHtml(t('settings.tokenStep2'))}</li>
|
|
112
|
+
<li>${escHtml(t('settings.tokenStep3'))}</li>
|
|
87
113
|
</ol>
|
|
88
114
|
</div>
|
|
89
115
|
<div class="form-group">
|
|
90
|
-
<label class="form-label" for="settings-github-token"
|
|
91
|
-
<input class="form-input" id="settings-github-token" type="password" placeholder="${u.has_github_token ? '
|
|
92
|
-
<div style="font-size:11px;color:var(--text-muted);margin-top:4px"
|
|
116
|
+
<label class="form-label" for="settings-github-token">${escHtml(t('settings.tokenLabel'))}</label>
|
|
117
|
+
<input class="form-input" id="settings-github-token" type="password" placeholder="${escHtml(u.has_github_token ? t('settings.tokenPlaceholder.keep') : t('settings.tokenPlaceholder.set'))}" autocomplete="off" aria-label="${escHtml(t('settings.tokenLabel'))}">
|
|
118
|
+
<div style="font-size:11px;color:var(--text-muted);margin-top:4px">${t('settings.tokenHint')}</div>
|
|
93
119
|
</div>
|
|
94
120
|
<div class="form-error" id="settings-github-error" style="display:none" role="alert"></div>
|
|
95
121
|
<div style="display:flex;gap:8px">
|
|
96
|
-
<button class="btn btn-primary btn-sm" id="settings-github-btn" onclick="window.__app.saveGitHubToken()" aria-label="
|
|
97
|
-
${u.has_github_token ? `<button class="btn btn-danger btn-sm" onclick="window.__app.clearGitHubToken()" aria-label="
|
|
122
|
+
<button class="btn btn-primary btn-sm" id="settings-github-btn" onclick="window.__app.saveGitHubToken()" aria-label="${escHtml(t('settings.saveToken'))}"><span>${escHtml(t('settings.saveToken'))}</span></button>
|
|
123
|
+
${u.has_github_token ? `<button class="btn btn-danger btn-sm" onclick="window.__app.clearGitHubToken()" aria-label="${escHtml(t('settings.clearToken'))}">${escHtml(t('settings.clearToken'))}</button>` : ''}
|
|
98
124
|
</div>
|
|
99
125
|
</div>
|
|
100
126
|
</div>
|
|
@@ -105,9 +131,9 @@ export async function saveProfile(): Promise<void> {
|
|
|
105
131
|
const displayName = (document.getElementById('settings-display-name') as HTMLInputElement | null)?.value?.trim() || '';
|
|
106
132
|
const errEl = document.getElementById('settings-profile-error') as HTMLElement | null;
|
|
107
133
|
const btn = document.getElementById('settings-profile-btn') as HTMLButtonElement | null;
|
|
108
|
-
if (!displayName) { if (errEl) { errEl.textContent = '
|
|
134
|
+
if (!displayName) { if (errEl) { errEl.textContent = t('settings.displayNameEmpty'); errEl.style.display = 'block'; } return; }
|
|
109
135
|
if (errEl) errEl.style.display = 'none';
|
|
110
|
-
if (btn) { btn.disabled = true; const sp = btn.querySelector('span'); if (sp) sp.textContent = '
|
|
136
|
+
if (btn) { btn.disabled = true; const sp = btn.querySelector('span'); if (sp) sp.textContent = t('settings.saving'); }
|
|
111
137
|
try {
|
|
112
138
|
const data = await api('PATCH','/auth/profile',{displayName});
|
|
113
139
|
if ((data as any).user) {
|
|
@@ -121,12 +147,12 @@ export async function saveProfile(): Promise<void> {
|
|
|
121
147
|
if (avatarEl) avatarEl.textContent = initials;
|
|
122
148
|
const nameEl = document.getElementById('user-name-display');
|
|
123
149
|
if (nameEl) nameEl.textContent = u.display_name||u.email;
|
|
124
|
-
toast('
|
|
150
|
+
toast(t('settings.profileSaved'),'success');
|
|
125
151
|
renderSettingsView();
|
|
126
152
|
} catch(err: unknown) {
|
|
127
|
-
if (errEl) { errEl.textContent = err instanceof Error ? err.message : String(err); errEl.style.display = 'block'; }
|
|
153
|
+
if (errEl) { errEl.textContent = translateError(err instanceof Error ? err.message : String(err)); errEl.style.display = 'block'; }
|
|
128
154
|
} finally {
|
|
129
|
-
if (btn) { btn.disabled = false; const sp = btn.querySelector('span'); if (sp) sp.textContent = '
|
|
155
|
+
if (btn) { btn.disabled = false; const sp = btn.querySelector('span'); if (sp) sp.textContent = t('settings.saveProfile'); }
|
|
130
156
|
}
|
|
131
157
|
}
|
|
132
158
|
|
|
@@ -137,13 +163,13 @@ export async function changePassword(): Promise<void> {
|
|
|
137
163
|
const errEl = document.getElementById('settings-pw-error') as HTMLElement | null;
|
|
138
164
|
const btn = document.getElementById('settings-pw-btn') as HTMLButtonElement | null;
|
|
139
165
|
if (errEl) errEl.style.display = 'none';
|
|
140
|
-
if (!currentPassword || !newPassword || !confirmPassword) { if (errEl) { errEl.textContent = '
|
|
141
|
-
if (newPassword !== confirmPassword) { if (errEl) { errEl.textContent = '
|
|
142
|
-
if (newPassword.length < 6) { if (errEl) { errEl.textContent = '
|
|
143
|
-
if (btn) { btn.disabled = true; const sp = btn.querySelector('span'); if (sp) sp.textContent = '
|
|
166
|
+
if (!currentPassword || !newPassword || !confirmPassword) { if (errEl) { errEl.textContent = t('settings.allFieldsRequired'); errEl.style.display = 'block'; } return; }
|
|
167
|
+
if (newPassword !== confirmPassword) { if (errEl) { errEl.textContent = t('settings.passwordsDoNotMatch'); errEl.style.display = 'block'; } return; }
|
|
168
|
+
if (newPassword.length < 6) { if (errEl) { errEl.textContent = t('settings.passwordTooShort'); errEl.style.display = 'block'; } return; }
|
|
169
|
+
if (btn) { btn.disabled = true; const sp = btn.querySelector('span'); if (sp) sp.textContent = t('settings.changing'); }
|
|
144
170
|
try {
|
|
145
171
|
await api('POST','/auth/change-password',{currentPassword,newPassword});
|
|
146
|
-
toast('
|
|
172
|
+
toast(t('settings.passwordChanged'),'success');
|
|
147
173
|
const curEl = document.getElementById('settings-current-pw') as HTMLInputElement | null;
|
|
148
174
|
const newEl = document.getElementById('settings-new-pw') as HTMLInputElement | null;
|
|
149
175
|
const confEl = document.getElementById('settings-confirm-pw') as HTMLInputElement | null;
|
|
@@ -151,9 +177,9 @@ export async function changePassword(): Promise<void> {
|
|
|
151
177
|
if (newEl) newEl.value = '';
|
|
152
178
|
if (confEl) confEl.value = '';
|
|
153
179
|
} catch(err: unknown) {
|
|
154
|
-
if (errEl) { errEl.textContent = err instanceof Error ? err.message : String(err); errEl.style.display = 'block'; }
|
|
180
|
+
if (errEl) { errEl.textContent = translateError(err instanceof Error ? err.message : String(err)); errEl.style.display = 'block'; }
|
|
155
181
|
} finally {
|
|
156
|
-
if (btn) { btn.disabled = false; const sp = btn.querySelector('span'); if (sp) sp.textContent = '
|
|
182
|
+
if (btn) { btn.disabled = false; const sp = btn.querySelector('span'); if (sp) sp.textContent = t('settings.changePassword'); }
|
|
157
183
|
}
|
|
158
184
|
}
|
|
159
185
|
|
|
@@ -161,30 +187,33 @@ export async function saveGitHubToken(): Promise<void> {
|
|
|
161
187
|
const token = (document.getElementById('settings-github-token') as HTMLInputElement | null)?.value?.trim() || '';
|
|
162
188
|
const errEl = document.getElementById('settings-github-error') as HTMLElement | null;
|
|
163
189
|
const btn = document.getElementById('settings-github-btn') as HTMLButtonElement | null;
|
|
164
|
-
if (!token) { if (errEl) { errEl.textContent = '
|
|
190
|
+
if (!token) { if (errEl) { errEl.textContent = t('settings.tokenEmpty'); errEl.style.display = 'block'; } return; }
|
|
165
191
|
if (errEl) errEl.style.display = 'none';
|
|
166
|
-
if (btn) { btn.disabled = true; const sp = btn.querySelector('span'); if (sp) sp.textContent = '
|
|
192
|
+
if (btn) { btn.disabled = true; const sp = btn.querySelector('span'); if (sp) sp.textContent = t('settings.saving'); }
|
|
167
193
|
try {
|
|
168
194
|
const data = await api('PATCH','/auth/github-token',{token});
|
|
169
195
|
state.user!.has_github_token = (data as any).hasToken !== undefined ? (data as any).hasToken : true;
|
|
170
|
-
toast('
|
|
196
|
+
toast(t('settings.tokenSaved'),'success');
|
|
171
197
|
renderSettingsView();
|
|
172
198
|
} catch(err: unknown) {
|
|
173
|
-
if (errEl) { errEl.textContent = err instanceof Error ? err.message : String(err); errEl.style.display = 'block'; }
|
|
199
|
+
if (errEl) { errEl.textContent = translateError(err instanceof Error ? err.message : String(err)); errEl.style.display = 'block'; }
|
|
174
200
|
} finally {
|
|
175
|
-
if (btn) { btn.disabled = false; const sp = btn.querySelector('span'); if (sp) sp.textContent = '
|
|
201
|
+
if (btn) { btn.disabled = false; const sp = btn.querySelector('span'); if (sp) sp.textContent = t('settings.saveToken'); }
|
|
176
202
|
}
|
|
177
203
|
}
|
|
178
204
|
|
|
179
205
|
export function clearGitHubToken(): void {
|
|
180
|
-
confirmDialog('
|
|
206
|
+
confirmDialog(t('settings.clearTokenTitle'), t('settings.clearTokenBody'), async () => {
|
|
181
207
|
try {
|
|
182
208
|
const data = await api('PATCH','/auth/github-token',{token:''});
|
|
183
209
|
state.user!.has_github_token = false;
|
|
184
|
-
toast('
|
|
210
|
+
toast(t('settings.tokenCleared'),'success');
|
|
185
211
|
renderSettingsView();
|
|
186
212
|
} catch(err: unknown) {
|
|
187
|
-
toast(err instanceof Error ? err.message : String(err),'error');
|
|
213
|
+
toast(translateError(err instanceof Error ? err.message : String(err)),'error');
|
|
188
214
|
}
|
|
189
|
-
});
|
|
215
|
+
}, false, { cancel: t('dialog.cancel'), confirm: t('dialog.confirm') });
|
|
190
216
|
}
|
|
217
|
+
|
|
218
|
+
// Re-export so type-only re-exports stay usable if extended later.
|
|
219
|
+
export type { SupportedLocale };
|
package/public/styles.css
CHANGED
|
@@ -240,6 +240,8 @@ html, body { height: 100%; font-family: -apple-system, BlinkMacSystemFont, 'Sego
|
|
|
240
240
|
.form-error { color: #f87171; font-size: 12px; margin-top: 8px; }
|
|
241
241
|
|
|
242
242
|
/* ── Buttons ── */
|
|
243
|
+
[hidden] { display: none !important; }
|
|
244
|
+
|
|
243
245
|
.btn {
|
|
244
246
|
display: inline-flex; align-items: center; gap: 6px; padding: 9px 16px;
|
|
245
247
|
border: none; border-radius: var(--radius); cursor: pointer; font-family: inherit;
|