Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions public/js/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,16 @@ function showListView() {
el('dash-list-view').classList.remove('d-none');
el('dash-edit-view').classList.add('d-none');
}
/* Keep both. The pane scrolls on a wide window, the document on a phone. */
function scrollSettingsTop() {
q('.cp')?.scrollTo?.(0, 0);
scrollTo(0, 0);
}

function showEditView() {
el('dash-list-view').classList.add('d-none');
el('dash-edit-view').classList.remove('d-none');
el('cp')?.scrollTo?.(0, 0);
q('.cp')?.scrollTo?.(0, 0);
scrollSettingsTop();
}

/* Read at draw time. The catalog is not loaded when this module evaluates. */
Expand Down Expand Up @@ -616,7 +621,8 @@ function initNav() {
const STORE = 'admin_sec';
const sections = qa('.sec', document).map(s => s.id.replace(/^sec-/, ''));

function show(requested) {
/* Do not scroll on the restoring first call. Only a picked section. */
function show(requested, picked) {
const id = resolveAdminSection(requested, sections);
if (id === null) return;
if (requested && id !== requested) console.warn('admin: unknown section', requested, '- showing', id);
Expand All @@ -626,9 +632,10 @@ function initNav() {
links.forEach(l => l.classList.toggle('active', l.dataset.sec === id));
syncGlideSelect();
localStorage.setItem(STORE, id);
if (picked) scrollSettingsTop();
}
links.forEach(l => l.addEventListener('click', () => show(l.dataset.sec)));
addEventListener('hashchange', () => show(location.hash.slice(1)));
links.forEach(l => l.addEventListener('click', () => show(l.dataset.sec, true)));
addEventListener('hashchange', () => show(location.hash.slice(1), true));
show(location.hash.slice(1) || localStorage.getItem(STORE));
initGlideSelect();
}
Expand Down
28 changes: 19 additions & 9 deletions public/widgets/connections/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -333,15 +333,21 @@ async function mapView(ctx) {
o.connected = total;
o.limit = 0;
} else if (s.type === 'umami') {
const lg = await fetchJSON(base + '/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: s.username || '', password: s.password || '' }),
});
if (authErr(lg)) ctx.fail('Auth required — check username/password', { kind: ctx.KIND.AUTH });
if (lg.status >= 400) ctx.fail('Login HTTP ' + lg.status);
const token = lg.data && lg.data.token;
if (!token) ctx.fail('Login failed', { kind: ctx.KIND.AUTH });
const usingKey = !!s.apiKey;
let token = s.apiKey || '';
if (!token) {
if (!s.username && !s.password)
ctx.fail('Enter an API key, or a username and password', { kind: ctx.KIND.INVALID });
const lg = await fetchJSON(base + '/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: s.username || '', password: s.password || '' }),
});
if (authErr(lg)) ctx.fail('Auth required — check username/password', { kind: ctx.KIND.AUTH });
if (lg.status >= 400) ctx.fail('Login HTTP ' + lg.status);
token = (lg.data && lg.data.token) || '';
if (!token) ctx.fail('Login failed', { kind: ctx.KIND.AUTH });
}
const end = Date.now(),
start = end - 7 * 24 * 3600 * 1000;
const r = await fetchJSON(
Expand All @@ -354,6 +360,10 @@ async function mapView(ctx) {
end,
{ headers: { Authorization: 'Bearer ' + token } },
);
if (authErr(r))
ctx.fail(usingKey ? 'Auth rejected — check the API key' : 'Auth rejected — check username/password', {
kind: ctx.KIND.AUTH,
});
if (r.status >= 400) ctx.fail('HTTP ' + r.status);
const rows = Array.isArray(r.data) ? r.data : [];
const regions = {};
Expand Down
2 changes: 2 additions & 0 deletions public/widgets/connections/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
"services.siteId.label": "Site-ID (Domain)",
"services.siteId.placeholder": "example.com",
"services.apiKey.label": "Statistik-API-Schlüssel",
"services.apiKey.label.umami": "API-Schlüssel",
"services.apiKey.hint.umami": "Ab Umami 3.4.0. Leer lassen, um sich mit Benutzername und Passwort anzumelden.",
"services.websiteId.label": "Website-ID",
"services.websiteId.placeholder": "8dc7… (UUID)",
"services.username.label": "Benutzername",
Expand Down
2 changes: 2 additions & 0 deletions public/widgets/connections/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
"services.siteId.label": "Site ID (domain)",
"services.siteId.placeholder": "example.com",
"services.apiKey.label": "Stats API key",
"services.apiKey.label.umami": "API key",
"services.apiKey.hint.umami": "Umami 3.4.0 and later. Leave empty to sign in with a username and password.",
"services.websiteId.label": "Website ID",
"services.websiteId.placeholder": "8dc7… (UUID)",
"services.username.label": "Username",
Expand Down
2 changes: 2 additions & 0 deletions public/widgets/connections/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
"services.siteId.label": "ID del sitio (dominio)",
"services.siteId.placeholder": "example.com",
"services.apiKey.label": "Clave de API de estadísticas",
"services.apiKey.label.umami": "Clave de API",
"services.apiKey.hint.umami": "Umami 3.4.0 o posterior. Déjalo vacío para iniciar sesión con usuario y contraseña.",
"services.websiteId.label": "ID del sitio web",
"services.websiteId.placeholder": "8dc7… (UUID)",
"services.username.label": "Usuario",
Expand Down
2 changes: 2 additions & 0 deletions public/widgets/connections/i18n/fa.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
"services.siteId.label": "شناسهٔ سایت (دامنه)",
"services.siteId.placeholder": "example.com",
"services.apiKey.label": "کلید API آمار",
"services.apiKey.label.umami": "کلید API",
"services.apiKey.hint.umami": "از Umami نسخه ۳.۴.۰ به بعد. برای ورود با نام کاربری و رمز عبور، خالی بگذارید.",
"services.websiteId.label": "شناسهٔ وب‌سایت",
"services.websiteId.placeholder": "8dc7… (UUID)",
"services.username.label": "نام کاربری",
Expand Down
2 changes: 2 additions & 0 deletions public/widgets/connections/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
"services.siteId.label": "Identifiant du site (domaine)",
"services.siteId.placeholder": "example.com",
"services.apiKey.label": "Clé d’API des statistiques",
"services.apiKey.label.umami": "Clé d’API",
"services.apiKey.hint.umami": "Umami 3.4.0 et versions ultérieures. Laissez vide pour vous connecter avec un nom d’utilisateur et un mot de passe.",
"services.websiteId.label": "Identifiant du site web",
"services.websiteId.placeholder": "8dc7… (UUID)",
"services.username.label": "Nom d’utilisateur",
Expand Down
2 changes: 2 additions & 0 deletions public/widgets/connections/i18n/zh-Hans.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
"services.siteId.label": "站点 ID(域名)",
"services.siteId.placeholder": "example.com",
"services.apiKey.label": "统计 API 密钥",
"services.apiKey.label.umami": "API 密钥",
"services.apiKey.hint.umami": "Umami 3.4.0 及以上版本。留空则使用用户名和密码登录。",
"services.websiteId.label": "网站 ID",
"services.websiteId.placeholder": "8dc7… (UUID)",
"services.username.label": "用户名",
Expand Down
25 changes: 21 additions & 4 deletions public/widgets/connections/widget.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@
"type": "text",
"label": "vpn.name.label",
"placeholder": "vpn.name.placeholder",
"optional": true
"optional": true,
"cosmetic": true
},
{
"key": "url",
Expand Down Expand Up @@ -128,7 +129,8 @@
"key": "color",
"type": "color",
"label": "vpn.color.label",
"default": "#30d158"
"default": "#30d158",
"cosmetic": true
}
]
},
Expand Down Expand Up @@ -174,7 +176,8 @@
"type": "text",
"label": "services.name.label",
"placeholder": "services.name.placeholder",
"optional": true
"optional": true,
"cosmetic": true
},
{
"key": "url",
Expand Down Expand Up @@ -265,11 +268,23 @@
"equals": "umami"
}
},
{
"key": "apiKey",
"type": "secret",
"label": "services.apiKey.label.umami",
"hint": "services.apiKey.hint.umami",
"optional": true,
"showIf": {
"field": "type",
"equals": "umami"
}
},
{
"key": "username",
"type": "text",
"label": "services.username.label",
"placeholder": "services.username.placeholder",
"optional": true,
"showIf": {
"field": "type",
"equals": "umami"
Expand All @@ -279,6 +294,7 @@
"key": "password",
"type": "secret",
"label": "services.password.label",
"optional": true,
"showIf": {
"field": "type",
"equals": "umami"
Expand All @@ -295,7 +311,8 @@
"key": "color",
"type": "color",
"label": "services.color.label",
"default": "#30d158"
"default": "#30d158",
"cosmetic": true
}
]
},
Expand Down
Loading