Made Jarvis more mobile friendly

This commit is contained in:
2026-04-21 11:00:39 +02:00
parent a72eef4b82
commit eaea8d94b1
14 changed files with 604 additions and 97 deletions
+24 -48
View File
@@ -114,57 +114,33 @@
</div>
</div>
<!-- Edit modal (reuse agent modal markup with inline) -->
<div class="modal-overlay hidden" id="agent-modal">
<div class="modal" style="max-width:560px;width:100%">
<h3 id="agent-modal-title">Edit Agent</h3>
<input type="hidden" id="a-id">
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px">
<div class="form-group">
<label>Name</label>
<input type="text" id="a-name" class="form-input" required>
</div>
<div class="form-group">
<label>Model</label>
<select id="a-model" class="form-input"></select>
</div>
<!-- Fullscreen prompt editor -->
<div id="prompt-editor-overlay" style="
display:none;position:fixed;inset:0;z-index:1001;
background:var(--bg);flex-direction:column;
">
<!-- Header bar -->
<div style="
display:flex;align-items:center;justify-content:space-between;
padding:12px 20px;border-bottom:1px solid var(--border);
background:var(--bg2);flex-shrink:0;gap:12px
">
<div style="display:flex;align-items:center;gap:12px;min-width:0">
<span style="font-size:13px;color:var(--text-dim);white-space:nowrap">Editing prompt —</span>
<span id="pe-agent-name" style="font-weight:600;font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap"></span>
</div>
<div class="form-group">
<label>Description</label>
<input type="text" id="a-desc" class="form-input">
</div>
<div class="form-group">
<label>Prompt</label>
<textarea id="a-prompt" class="form-input" rows="5" style="resize:vertical"></textarea>
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px">
<div class="form-group">
<label>Schedule</label>
<input type="text" id="a-schedule" class="form-input"
placeholder="0 8 * * *" oninput="updateAgentCronPreview(this.value)">
<div id="a-cron-preview" style="font-size:11px;color:var(--text-dim);margin-top:4px"></div>
</div>
<div class="form-group" style="display:flex;flex-direction:column;justify-content:center;gap:8px;padding-top:18px">
<label style="display:flex;align-items:center;gap:8px;cursor:pointer">
<input type="checkbox" id="a-subagents">
<span>Can create sub-agents</span>
</label>
<label style="display:flex;align-items:center;gap:8px;cursor:pointer">
<input type="checkbox" id="a-enabled" checked>
<span>Enabled</span>
</label>
</div>
</div>
<div class="modal-buttons">
<button class="btn btn-ghost" onclick="closeAgentModal()">Cancel</button>
<button class="btn btn-primary" onclick="saveAgentAndReload()">Save</button>
<div style="display:flex;align-items:center;gap:8px;flex-shrink:0">
<span style="font-size:11px;color:var(--text-dim)">Ctrl+S to save · Esc to cancel</span>
<button class="btn btn-ghost" onclick="closePromptEditor()">Cancel</button>
<button class="btn btn-primary" id="pe-save-btn" onclick="savePromptEditor()">Save</button>
</div>
</div>
<!-- Editor -->
<textarea id="pe-textarea" spellcheck="false" style="
flex:1;width:100%;box-sizing:border-box;resize:none;border:none;outline:none;
background:var(--bg);color:var(--text);font-family:var(--mono);font-size:13px;
line-height:1.7;padding:24px 32px;
"></textarea>
</div>
{% endblock %}
+28 -4
View File
@@ -2,21 +2,26 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<title>{% block title %}{{ brand_name }}{% endblock %}</title>
<link rel="icon" type="image/png" href="/static/icon.png">
<link rel="manifest" href="/static/manifest.json">
<meta name="theme-color" content="#0f1117">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<link rel="apple-touch-icon" href="/static/icon.png">
<link rel="stylesheet" href="/static/style.css?v={{ sv }}">
{% if theme_css %}<style>{{ theme_css | safe }}</style>{% endif %}
</head>
<body>
<!-- ── Sidebar ── -->
<nav class="sidebar">
<nav class="sidebar" id="sidebar">
<div class="sidebar-logo">
<img src="{{ logo_url }}" alt="logo" class="sidebar-logo-img">
<div class="sidebar-logo-text">
<div class="sidebar-logo-name">{{ brand_name }}</div>
<div class="sidebar-logo-app">oAI-Web <span class="sidebar-logo-version">v1.2.3</span></div>
<div class="sidebar-logo-app">oAI-Web <span class="sidebar-logo-version">v1.2.5</span></div>
</div>
</div>
@@ -89,8 +94,22 @@
</div>
</nav>
<!-- ── Sidebar overlay (mobile) ── -->
<div class="sidebar-overlay" id="sidebar-overlay" onclick="closeSidebar()"></div>
<!-- ── Main column (nag + content) ── -->
<div style="flex:1;display:flex;flex-direction:column;overflow:hidden">
<div class="app-body">
<!-- ── Mobile header ── -->
<div class="mobile-header">
<button class="hamburger-btn" onclick="toggleSidebar()" aria-label="Menu">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
</button>
<span class="mobile-title">{{ agent_name }}</span>
<button class="mobile-install-btn" id="pwa-install-btn" onclick="handleInstall()" title="Add to Home Screen" style="display:none">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18"><path d="M12 2v13M7 9l5 5 5-5"/><path d="M5 20h14"/></svg>
</button>
</div>
{% if needs_personality_setup %}
<div class="nag-banner" id="nag-banner">
@@ -110,6 +129,11 @@
<script>window.AGENT_NAME = "{{ agent_name }}";</script>
<script src="/static/app.js?v={{ sv }}"></script>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js').catch(() => {});
}
</script>
{% block extra_scripts %}{% endblock %}
</body>
</html>
+32 -17
View File
@@ -13,7 +13,7 @@
{% if current_user.is_admin %}
<!-- ── Admin Tabs ── -->
<div style="display:flex;gap:0;border-bottom:1px solid var(--border);margin-bottom:28px">
<div class="tab-bar" style="border-bottom:1px solid var(--border);margin-bottom:28px">
<button type="button" class="tab-btn active" id="stab-general" onclick="switchSettingsTab('general')">General</button>
<button type="button" class="tab-btn" id="stab-whitelists" onclick="switchSettingsTab('whitelists')">Whitelists</button>
<button type="button" class="tab-btn" id="stab-credentials" onclick="switchSettingsTab('credentials')">Credentials</button>
@@ -32,7 +32,7 @@
</div>
{% else %}
<!-- ── User Tabs ── -->
<div style="display:flex;gap:0;border-bottom:1px solid var(--border);margin-bottom:28px">
<div class="tab-bar" style="border-bottom:1px solid var(--border);margin-bottom:28px">
<button type="button" class="tab-btn active" id="ustab-apikeys" onclick="switchUserTab('apikeys')">API Keys</button>
<button type="button" class="tab-btn" id="ustab-personality" onclick="switchUserTab('personality')">Personality</button>
<button type="button" class="tab-btn" id="ustab-inbox" onclick="switchUserTab('inbox')">Inbox</button>
@@ -1934,18 +1934,18 @@
</div>
<!-- ── Email Handling Account modal ── -->
<div class="modal-overlay" id="email-account-modal" style="display:none">
<div class="modal" style="max-width:820px;width:100%">
<h3 id="eam-title">Add Handling Account</h3>
<div class="modal-overlay" id="email-account-modal" style="display:none;align-items:flex-start;padding:32px 16px;overflow-y:auto">
<div class="modal" style="max-width:1100px;width:100%">
<h3 id="eam-title" style="margin-bottom:16px">Add Handling Account</h3>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:24px;margin-top:16px">
<div style="display:grid;grid-template-columns:1fr 1.4fr 1fr;gap:24px">
<!-- Left column: IMAP account -->
<!-- Column 1: IMAP account -->
<div>
<p style="font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-dim);margin-bottom:14px;font-weight:600">Account</p>
<div class="form-group"><label>Label</label>
<input type="text" id="eam-label" class="form-input" placeholder="e.g. Work Email"></div>
<div style="display:grid;grid-template-columns:2fr 1fr;gap:10px">
<div style="display:grid;grid-template-columns:2fr 1fr;gap:8px">
<div class="form-group"><label>IMAP Host</label>
<input type="text" id="eam-imap-host" class="form-input" placeholder="imap.example.com"></div>
<div class="form-group"><label>Port</label>
@@ -1955,7 +1955,7 @@
<input type="text" id="eam-imap-username" class="form-input" placeholder="user@example.com"></div>
<div class="form-group"><label>Password</label>
<input type="password" id="eam-imap-password" class="form-input" placeholder="Leave blank to keep existing"></div>
<div class="form-group"><label>Initial load limit <span style="color:var(--text-dim);font-size:11px">(emails on first connect)</span></label>
<div class="form-group"><label>Initial load limit <span style="color:var(--text-dim);font-size:11px">(on first connect)</span></label>
<input type="number" id="eam-initial-load-limit" class="form-input" value="200" min="0" max="5000"></div>
<div class="form-group">
<label>Monitored folders</label>
@@ -1963,26 +1963,41 @@
<span id="eam-folders-display" style="font-size:13px;color:var(--text-dim)">INBOX</span>
<button type="button" class="btn btn-ghost btn-small" id="eam-load-folders-btn" onclick="loadEamFolders()">Load folders</button>
</div>
<div id="eam-folders-checklist" style="display:none;max-height:160px;overflow-y:auto;background:var(--bg2);padding:8px 12px;border-radius:var(--radius);border:1px solid var(--border)"></div>
<div id="eam-folders-checklist" style="display:none;max-height:140px;overflow-y:auto;background:var(--bg2);padding:8px 12px;border-radius:var(--radius);border:1px solid var(--border)"></div>
<input type="hidden" id="eam-folders-hidden" value='["INBOX"]'>
</div>
</div>
<!-- Right column: Handling agent -->
<!-- Column 2: Agent prompt + model -->
<div>
<p style="font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-dim);margin-bottom:14px;font-weight:600">Handling Agent</p>
<p style="font-size:12px;color:var(--text-dim);margin-bottom:14px;line-height:1.5">
A dedicated agent is created for this account. It can use email tools plus any notification tools you enable below.
</p>
<div class="form-group"><label>Model</label>
<select id="eam-agent-model" class="form-input"><option value="">Loading…</option></select>
</div>
<div class="form-group" style="display:flex;flex-direction:column;flex:1">
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px">
<div class="form-group">
<label>Max tool calls <span style="color:var(--text-dim);font-size:11px">(blank = default)</span></label>
<input type="number" id="eam-max-tool-calls" class="form-input" min="1" max="50" placeholder="e.g. 6">
</div>
<div class="form-group">
<label>Prompt mode</label>
<select id="eam-prompt-mode" class="form-input">
<option value="combined">Combined (full personality)</option>
<option value="agent_only">Agent only (cheaper)</option>
</select>
</div>
</div>
<div class="form-group" style="display:flex;flex-direction:column">
<label>Agent prompt</label>
<textarea id="eam-agent-prompt" class="form-input" rows="8"
style="resize:vertical;font-size:13px;line-height:1.5"
<textarea id="eam-agent-prompt" class="form-input" rows="10"
style="resize:vertical;font-size:13px;line-height:1.5;flex:1"
placeholder="Describe how the agent should handle incoming emails…"></textarea>
</div>
</div>
<!-- Column 3: Options -->
<div>
<p style="font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-dim);margin-bottom:14px;font-weight:600">Options</p>
<div class="form-group">
<label>Notification tools <span style="font-size:11px;color:var(--text-dim)">(optional)</span></label>
<div id="eam-extra-tools-area" style="margin-top:6px;display:flex;flex-direction:column;gap:8px">
+2 -2
View File
@@ -4,10 +4,10 @@
{% block content %}
<div class="page" id="usage-container">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:24px">
<div class="usage-header">
<h1>Usage</h1>
<!-- Time range filter + admin actions -->
<div style="display:flex;gap:6px;align-items:center">
<div class="usage-header-actions">
<button class="btn" id="usage-range-today" type="button" onclick="setUsageRange('today')">Today</button>
<button class="btn" id="usage-range-7d" type="button" onclick="setUsageRange('7d')" style="background:var(--accent);color:#fff;border-color:var(--accent)">7 days</button>
<button class="btn" id="usage-range-30d" type="button" onclick="setUsageRange('30d')">30 days</button>