frontend: prevent contacts content overflowing the viewport + sync UI repo
- ContactsPage: drop whiteSpace:nowrap on the action cell; wrap the Edit/History/Delete/⋮ buttons in a flex container with flex-wrap so they reflow instead of forcing the table wider than the viewport; allow the name/number/email cell to break long strings. - index.css: td word-break:break-word + table max-width:100% as a guard. - Sync the UI repo (ContactsPage/ContactHistory/MessagesPage implicit-any annotations that unblock npm run build) into the frontend/ mirror.
This commit is contained in:
@ -15,7 +15,7 @@ export default function ContactHistory() {
|
|||||||
</div>
|
</div>
|
||||||
{isLoading && <div className="card empty">Loading...</div>}
|
{isLoading && <div className="card empty">Loading...</div>}
|
||||||
{error && <div className="card err">{(error as Error).message}</div>}
|
{error && <div className="card err">{(error as Error).message}</div>}
|
||||||
{data?.messages?.map((m) => (
|
{data?.messages?.map((m: any) => (
|
||||||
<div key={m.id} className={"card" + (m.is_read ? "" : " unread")}>
|
<div key={m.id} className={"card" + (m.is_read ? "" : " unread")}>
|
||||||
<div className="who">{data.contact}</div>
|
<div className="who">{data.contact}</div>
|
||||||
<div className="meta">{m.time}{m.duration_fmt ? ` · ${m.duration_fmt}` : ""}</div>
|
<div className="meta">{m.time}{m.duration_fmt ? ` · ${m.duration_fmt}` : ""}</div>
|
||||||
|
|||||||
@ -38,23 +38,23 @@ export default function ContactsPage() {
|
|||||||
</div>
|
</div>
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
{data.map((c) => (
|
{data.map((c: any) => (
|
||||||
<tr key={c.id}>
|
<tr key={c.id}>
|
||||||
<td>
|
<td style={{ minWidth: 0 }}>
|
||||||
<b>{c.name || "Unnamed"}</b><br />
|
<b>{c.name || "Unnamed"}</b><br />
|
||||||
<span style={{ color: "var(--text-muted)", fontSize: 13 }}>
|
<span style={{ color: "var(--text-muted)", fontSize: 13, overflowWrap: "anywhere", wordBreak: "break-word" }}>
|
||||||
{c.number_e164} {c.email && `· ${c.email}`}
|
{c.number_e164} {c.email && `· ${c.email}`}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td style={{ textAlign: "right", whiteSpace: "nowrap" }}>
|
<td style={{ textAlign: "right", verticalAlign: "middle" }}>
|
||||||
<a className="btn" href={`/contacts/edit/${c.id}`}>Edit</a>
|
<div style={{ display: "flex", flexWrap: "wrap", gap: 6, justifyContent: "flex-end" }}>
|
||||||
{" "}
|
<a className="btn" href={`/contacts/edit/${c.id}`}>Edit</a>
|
||||||
<a className="btn" href={`/contacts/history/${encodeURIComponent(c.number_e164 || c.name)}`}>History</a>
|
<a className="btn" href={`/contacts/history/${encodeURIComponent(c.number_e164 || c.name)}`}>History</a>
|
||||||
{" "}
|
<DeleteBtn id={c.id} name={c.name} />
|
||||||
<DeleteBtn id={c.id} name={c.name} />
|
<span style={{ position: "relative", display: "inline-block" }}>
|
||||||
<span style={{ position: "relative", display: "inline-block", marginLeft: 4 }}>
|
<ContactMenu number={c.number_e164} name={c.name} />
|
||||||
<ContactMenu number={c.number_e164} name={c.name} />
|
</span>
|
||||||
</span>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
@ -121,7 +121,7 @@ function ContactMenu({ number, name }: { number?: string; name?: string }) {
|
|||||||
)}
|
)}
|
||||||
<a
|
<a
|
||||||
className="btn"
|
className="btn"
|
||||||
href={"https://who-called.co.uk/Number/" + lookup}
|
href={"https://www.google.com/search?q=uk+number+" + lookup}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
style={{ display: "block", borderRadius: 0, border: "none", width: "100%", justifyContent: "flex-start" }}
|
style={{ display: "block", borderRadius: 0, border: "none", width: "100%", justifyContent: "flex-start" }}
|
||||||
|
|||||||
@ -70,7 +70,7 @@ export default function MessagesPage() {
|
|||||||
{isLoading && <div className="card empty">Loading...</div>}
|
{isLoading && <div className="card empty">Loading...</div>}
|
||||||
{error && <div className="card err">{(error as Error).message}</div>}
|
{error && <div className="card err">{(error as Error).message}</div>}
|
||||||
|
|
||||||
{data?.messages?.map((m) => {
|
{data?.messages?.map((m: any) => {
|
||||||
const whoRaw = m.contact_name || m.callerid || "Unknown caller";
|
const whoRaw = m.contact_name || m.callerid || "Unknown caller";
|
||||||
const num = sanitiseNumber(m.callerid);
|
const num = sanitiseNumber(m.callerid);
|
||||||
const showAdd = !m.contact_name && num;
|
const showAdd = !m.contact_name && num;
|
||||||
@ -192,7 +192,7 @@ function MsgContactMenu({ number, name, callerid }: { number?: string; name?: st
|
|||||||
)}
|
)}
|
||||||
<a
|
<a
|
||||||
className="btn"
|
className="btn"
|
||||||
href={"https://who-called.co.uk/Number/" + lookup}
|
href={"https://www.google.com/search?q=uk+number+" + lookup}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
style={{ display: "block", borderRadius: 0, border: "none", width: "100%", justifyContent: "flex-start" }}
|
style={{ display: "block", borderRadius: 0, border: "none", width: "100%", justifyContent: "flex-start" }}
|
||||||
|
|||||||
@ -332,6 +332,12 @@ td {
|
|||||||
padding: 10px 6px;
|
padding: 10px 6px;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep the contacts table (and any table) from forcing horizontal overflow */
|
||||||
|
table {
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
tr:hover td { background: rgba(255, 255, 255, 0.01); }
|
tr:hover td { background: rgba(255, 255, 255, 0.01); }
|
||||||
|
|||||||
Reference in New Issue
Block a user