v0.11.0 more bug fixes
This commit is contained in:
@@ -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": {
|
||||||
|
|||||||
2
build.sh
2
build.sh
@@ -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"
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user