v0.11.0 more bug fixes

This commit is contained in:
2026-03-20 22:45:09 -04:00
parent d2c157e8d0
commit 50e7adf246
6 changed files with 18 additions and 18 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "jama-backend", "name": "jama-backend",
"version": "0.10.9", "version": "0.11.0",
"description": "TeamChat backend server", "description": "TeamChat backend server",
"main": "src/index.js", "main": "src/index.js",
"scripts": { "scripts": {

View File

@@ -13,7 +13,7 @@
# ───────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────
set -euo pipefail set -euo pipefail
VERSION="${1:-0.10.9}" VERSION="${1:-0.11.0}"
ACTION="${2:-}" ACTION="${2:-}"
REGISTRY="${REGISTRY:-}" REGISTRY="${REGISTRY:-}"
IMAGE_NAME="jama" IMAGE_NAME="jama"

View File

@@ -1,6 +1,6 @@
{ {
"name": "jama-frontend", "name": "jama-frontend",
"version": "0.10.9", "version": "0.11.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@@ -354,6 +354,8 @@ export default function Chat() {
{modal === 'profile' && <ProfileModal onClose={() => setModal(null)} />} {modal === 'profile' && <ProfileModal onClose={() => setModal(null)} />}
{modal === 'settings' && <SettingsModal onClose={() => setModal(null)} onFeaturesChanged={setFeatures} />} {modal === 'settings' && <SettingsModal onClose={() => setModal(null)} onFeaturesChanged={setFeatures} />}
{modal === 'branding' && <BrandingModal onClose={() => setModal(null)} />} {modal === 'branding' && <BrandingModal onClose={() => setModal(null)} />}
{modal === 'help' && <HelpModal onClose={() => setModal(null)} dismissed={helpDismissed} />}
{modal === 'about' && <AboutModal onClose={() => setModal(null)} />}
</div> </div>
); );
} }
@@ -379,6 +381,8 @@ export default function Chat() {
{modal === 'profile' && <ProfileModal onClose={() => setModal(null)} />} {modal === 'profile' && <ProfileModal onClose={() => setModal(null)} />}
{modal === 'settings' && <SettingsModal onClose={() => setModal(null)} onFeaturesChanged={setFeatures} />} {modal === 'settings' && <SettingsModal onClose={() => setModal(null)} onFeaturesChanged={setFeatures} />}
{modal === 'branding' && <BrandingModal onClose={() => setModal(null)} />} {modal === 'branding' && <BrandingModal onClose={() => setModal(null)} />}
{modal === 'help' && <HelpModal onClose={() => setModal(null)} dismissed={helpDismissed} />}
{modal === 'about' && <AboutModal onClose={() => setModal(null)} />}
</div> </div>
); );
} }

View File

@@ -508,7 +508,7 @@ function U2URestrictionsTab({ allUserGroups, isMobile = false }) {
} }
// ── Main page ───────────────────────────────────────────────────────────────── // ── Main page ─────────────────────────────────────────────────────────────────
const SIDEBAR_W = 260; const SIDEBAR_W = 320;
export default function GroupManagerPage({ isMobile = false, onProfile, onHelp, onAbout }) { export default function GroupManagerPage({ isMobile = false, onProfile, onHelp, onAbout }) {
const [tab, setTab] = useState('all'); const [tab, setTab] = useState('all');
@@ -559,7 +559,7 @@ export default function GroupManagerPage({ isMobile = false, onProfile, onHelp,
)} )}
{/* ── Right panel ── */} {/* ── Right panel ── */}
<div style={{ flex:1, display:'flex', flexDirection:'column', overflow:'hidden', minWidth:0, background:'var(--background)' }}> <div style={{ flex:1, display:'flex', flexDirection:'column', overflow:'hidden', minWidth:0, background:'var(--background)', height:'100%' }}>
{/* Mobile tab bar — only shown on mobile */} {/* Mobile tab bar — only shown on mobile */}
{isMobile && ( {isMobile && (
@@ -578,11 +578,9 @@ export default function GroupManagerPage({ isMobile = false, onProfile, onHelp,
{tab==='u2u' && <U2URestrictionsTab allUserGroups={allUserGroups} isMobile={isMobile} />} {tab==='u2u' && <U2URestrictionsTab allUserGroups={allUserGroups} isMobile={isMobile} />}
</div> </div>
{/* Mobile footer — hidden when keyboard is open */} {/* Mobile footer — in-flow so it stays at bottom and never floats with keyboard */}
{isMobile && !keyboardOpen && ( {isMobile && (
<div style={{ position:'fixed', bottom:0, left:0, right:0, zIndex:20, background:'var(--surface)', borderTop:'1px solid var(--border)' }}> <UserFooter onProfile={onProfile} onHelp={onHelp} onAbout={onAbout} />
<UserFooter onProfile={onProfile} onHelp={onHelp} onAbout={onAbout} />
</div>
)} )}
</div> </div>
</div> </div>

View File

@@ -4,7 +4,7 @@ import { api } from '../utils/api.js';
import Avatar from '../components/Avatar.jsx'; import Avatar from '../components/Avatar.jsx';
import UserFooter from '../components/UserFooter.jsx'; import UserFooter from '../components/UserFooter.jsx';
const SIDEBAR_W = 260; const SIDEBAR_W = 320;
function isValidEmail(e) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e); } function isValidEmail(e) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e); }
@@ -349,7 +349,7 @@ export default function UserManagerPage({ isMobile = false, onProfile, onHelp, o
)} )}
{/* ── Right panel ── */} {/* ── Right panel ── */}
<div style={{ flex:1, display:'flex', flexDirection:'column', overflow:'hidden', minWidth:0, background:'var(--background)' }}> <div style={{ flex:1, display:'flex', flexDirection:'column', overflow:'hidden', minWidth:0, background:'var(--background)', height:'100%' }}>
{/* Mobile tab bar — only on mobile since desktop uses left panel */} {/* Mobile tab bar — only on mobile since desktop uses left panel */}
{isMobile && ( {isMobile && (
@@ -361,7 +361,7 @@ export default function UserManagerPage({ isMobile = false, onProfile, onHelp, o
)} )}
{/* Content */} {/* Content */}
<div style={{ flex:1, overflowY:'auto', padding:16, paddingBottom: isMobile ? 80 : 16 }}> <div style={{ flex:1, overflowY:'auto', padding:16 }}>
{tab === 'users' && ( {tab === 'users' && (
<> <>
<input className="input" placeholder="Search users…" value={search} onChange={e => setSearch(e.target.value)} <input className="input" placeholder="Search users…" value={search} onChange={e => setSearch(e.target.value)}
@@ -389,11 +389,9 @@ export default function UserManagerPage({ isMobile = false, onProfile, onHelp, o
{tab === 'bulk' && <BulkImportForm userPass={userPass} onCreated={load} />} {tab === 'bulk' && <BulkImportForm userPass={userPass} onCreated={load} />}
</div> </div>
{/* Mobile footer — hidden when keyboard is open */} {/* Mobile footer — in-flow so it stays at bottom and never floats with keyboard */}
{isMobile && !keyboardOpen && ( {isMobile && (
<div style={{ position:'fixed', bottom:0, left:0, right:0, zIndex:20, background:'var(--surface)', borderTop:'1px solid var(--border)' }}> <UserFooter onProfile={onProfile} onHelp={onHelp} onAbout={onAbout} />
<UserFooter onProfile={onProfile} onHelp={onHelp} onAbout={onAbout} />
</div>
)} )}
</div> </div>
</div> </div>