Added esc functionality to open windows, added 'n' keybind to create new tasks, fixed Accounts and settings page to allow for edits to be made as well as profile picture to be updated
This commit is contained in:
+44
-11
@@ -608,9 +608,10 @@ function Modal({ children, onClose, title, eyebrow, wide = false }) {
|
||||
);
|
||||
}
|
||||
|
||||
function TaskDetail({ task, allAudit = [], onClose, onMove, onPriority, onComplete, onReopen, onEditDesc, onDeleteTask }) {
|
||||
function TaskDetail({ task, allAudit = [], onClose, onMove, onPriority, onComplete, onReopen, onEditDesc, onDeleteTask, onAddNote }) {
|
||||
const [editingDesc, setEditingDesc] = React.useState(false);
|
||||
const [descValue, setDescValue] = React.useState(task ? task.description || '' : '');
|
||||
const [noteValue, setNoteValue] = React.useState('');
|
||||
|
||||
React.useEffect(() => {
|
||||
setDescValue(task ? task.description || '' : '');
|
||||
@@ -623,6 +624,13 @@ function TaskDetail({ task, allAudit = [], onClose, onMove, onPriority, onComple
|
||||
if (audit.length === 0) {
|
||||
audit.push({ at: task.addedAt, actor: task.addedBy, action: 'task_created', summary: '' });
|
||||
}
|
||||
|
||||
const handleAddNote = async () => {
|
||||
if (!noteValue.trim()) return;
|
||||
await onAddNote(noteValue);
|
||||
setNoteValue('');
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal onClose={onClose} wide title={task.title} eyebrow={(task.tags && task.tags.join(' · ')) || 'Task'}>
|
||||
<div className="detail">
|
||||
@@ -671,13 +679,32 @@ function TaskDetail({ task, allAudit = [], onClose, onMove, onPriority, onComple
|
||||
</div>
|
||||
|
||||
<div className="detail__notes">
|
||||
<h3 className="detail__h">Notes & reminders</h3>
|
||||
<h3 className="detail__h">Notes</h3>
|
||||
<ul className="notes">
|
||||
{/* Dynamic notes will go here */}
|
||||
{task.notes && task.notes.map(note => {
|
||||
const noteAuthor = findUser(note.author_id);
|
||||
return (
|
||||
<li key={note.id} className="notes__item">
|
||||
<span className="notes__bullet"><Icon.Pin /></span>
|
||||
<div>
|
||||
<div>{note.body}</div>
|
||||
<div className="notes__meta mono">
|
||||
{noteAuthor ? noteAuthor.name : 'Unknown'} · {fmtDateTime(note.created_at)}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
<div className="notes__add">
|
||||
<input className="field__input" placeholder="Add a note or @mention…" />
|
||||
<button className="btn btn--soft btn--sm">Add</button>
|
||||
<input
|
||||
className="field__input"
|
||||
placeholder="Add a note…"
|
||||
value={noteValue}
|
||||
onChange={e => setNoteValue(e.target.value)}
|
||||
onKeyDown={e => { if (e.key === 'Enter') handleAddNote(); }}
|
||||
/>
|
||||
<button className="btn btn--soft btn--sm" onClick={handleAddNote}>Add</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -921,6 +948,8 @@ function FilterChip({ on, onClick, children }) {
|
||||
function SettingsScreen({ user, dbUsers, isAdmin, onClose, onSave, onLogout, onSwitchUser, onCreateUser, onDeleteUser, onUpdateUserRole, onChangePassword, workspace, onUpdateWorkspace }) {
|
||||
const [name, setName] = React.useState(user.name);
|
||||
const [role, setRole] = React.useState(user.role);
|
||||
const [email, setEmail] = React.useState(user.email || '');
|
||||
const [phone, setPhone] = React.useState(user.phone || '');
|
||||
const [photo, setPhoto] = React.useState(user.photo || null);
|
||||
const [tab, setTab] = React.useState('profile');
|
||||
const [pwOld, setPwOld] = React.useState('');
|
||||
@@ -948,7 +977,11 @@ function SettingsScreen({ user, dbUsers, isAdmin, onClose, onSave, onLogout, onS
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
setName(user.name); setRole(user.role); setPhoto(user.photo || null);
|
||||
setName(user.name);
|
||||
setRole(user.role);
|
||||
setEmail(user.email || '');
|
||||
setPhone(user.phone || '');
|
||||
setPhoto(user.photo || null);
|
||||
}, [user.id]);
|
||||
|
||||
const fileInputRef = React.useRef(null);
|
||||
@@ -961,12 +994,12 @@ function SettingsScreen({ user, dbUsers, isAdmin, onClose, onSave, onLogout, onS
|
||||
};
|
||||
|
||||
const save = () => {
|
||||
onSave({ name, role, photo });
|
||||
onSave({ name, role, photo, email, phone });
|
||||
setSaved(true);
|
||||
setTimeout(() => setSaved(false), 1600);
|
||||
};
|
||||
|
||||
const dirty = name !== user.name || role !== user.role || photo !== (user.photo || null);
|
||||
const dirty = name !== user.name || role !== user.role || photo !== (user.photo || null) || email !== (user.email || '') || phone !== (user.phone || '');
|
||||
|
||||
return (
|
||||
<Modal onClose={onClose} title="Account & settings" eyebrow={"Signed in as " + user.name} wide>
|
||||
@@ -1025,17 +1058,17 @@ function SettingsScreen({ user, dbUsers, isAdmin, onClose, onSave, onLogout, onS
|
||||
</label>
|
||||
<label className="field">
|
||||
<span className="field__label">Email</span>
|
||||
<input className="field__input" defaultValue={user.id + "@murchison-auto.co"} />
|
||||
<input className="field__input" value={email} onChange={e => setEmail(e.target.value)} placeholder="yourname@example.com" />
|
||||
</label>
|
||||
<label className="field">
|
||||
<span className="field__label">Phone</span>
|
||||
<input className="field__input" defaultValue="+64 27 555 0184" />
|
||||
<input className="field__input" value={phone} onChange={e => setPhone(e.target.value)} placeholder="+64 ..." />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="settings__save-row">
|
||||
{saved && <span className="settings__saved mono"><Icon.Check /> Saved</span>}
|
||||
<button className="btn btn--ghost" onClick={() => { setName(user.name); setRole(user.role); setPhoto(user.photo||null); }} disabled={!dirty}>Discard</button>
|
||||
<button className="btn btn--ghost" onClick={() => { setName(user.name); setRole(user.role); setPhoto(user.photo||null); setEmail(user.email||''); setPhone(user.phone||''); }} disabled={!dirty}>Discard</button>
|
||||
<button className="btn btn--primary" onClick={save} disabled={!dirty}>Save changes</button>
|
||||
</div>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user