extract Text from gmail import, darkmode updates, auto update app versions etc
This commit is contained in:
@@ -16,6 +16,9 @@ REACT_APP_API_BASE_URL=
|
|||||||
|
|
||||||
# Used by docker-compose.yml (email / password resets / notifications)
|
# Used by docker-compose.yml (email / password resets / notifications)
|
||||||
APP_PUBLIC_BASE_URL=https://jobs.cesnimda.uk
|
APP_PUBLIC_BASE_URL=https://jobs.cesnimda.uk
|
||||||
|
APP_VERSION=
|
||||||
|
APP_COMMIT_SHA=
|
||||||
|
APP_BUILD_STAMP=
|
||||||
EMAIL_ENABLED=false
|
EMAIL_ENABLED=false
|
||||||
EMAIL_SMTP_HOST=smtp.gmail.com
|
EMAIL_SMTP_HOST=smtp.gmail.com
|
||||||
EMAIL_SMTP_PORT=587
|
EMAIL_SMTP_PORT=587
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ public sealed class AdminSystemController : ControllerBase
|
|||||||
string Environment,
|
string Environment,
|
||||||
string ContentRoot,
|
string ContentRoot,
|
||||||
string Version,
|
string Version,
|
||||||
|
string? CommitSha,
|
||||||
|
string? BuildStamp,
|
||||||
StorageStatusDto Storage,
|
StorageStatusDto Storage,
|
||||||
EmailStatusDto Email,
|
EmailStatusDto Email,
|
||||||
SummarizerMetrics Summarizer
|
SummarizerMetrics Summarizer
|
||||||
@@ -48,12 +50,20 @@ public sealed class AdminSystemController : ControllerBase
|
|||||||
var companies = await _db.Companies.AsNoTracking().CountAsync(cancellationToken);
|
var companies = await _db.Companies.AsNoTracking().CountAsync(cancellationToken);
|
||||||
var summarizer = await _summarizer.GetMetricsAsync(cancellationToken);
|
var summarizer = await _summarizer.GetMetricsAsync(cancellationToken);
|
||||||
|
|
||||||
var version = Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown";
|
var version = (_cfg["App:Version"] ?? "").Trim();
|
||||||
|
if (string.IsNullOrWhiteSpace(version))
|
||||||
|
{
|
||||||
|
version = Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown";
|
||||||
|
}
|
||||||
|
var commitSha = (_cfg["App:CommitSha"] ?? "").Trim();
|
||||||
|
var buildStamp = (_cfg["App:BuildStamp"] ?? "").Trim();
|
||||||
|
|
||||||
return Ok(new SystemStatusDto(
|
return Ok(new SystemStatusDto(
|
||||||
Environment: _env.EnvironmentName,
|
Environment: _env.EnvironmentName,
|
||||||
ContentRoot: _env.ContentRootPath,
|
ContentRoot: _env.ContentRootPath,
|
||||||
Version: version,
|
Version: version,
|
||||||
|
CommitSha: string.IsNullOrWhiteSpace(commitSha) ? null : commitSha,
|
||||||
|
BuildStamp: string.IsNullOrWhiteSpace(buildStamp) ? null : buildStamp,
|
||||||
Storage: new StorageStatusDto(
|
Storage: new StorageStatusDto(
|
||||||
DataRoot: _paths.DataRoot,
|
DataRoot: _paths.DataRoot,
|
||||||
DbPath: dbPath,
|
DbPath: dbPath,
|
||||||
|
|||||||
@@ -204,6 +204,10 @@ public sealed class GmailOAuthService : IGmailOAuthService
|
|||||||
{
|
{
|
||||||
bodyText = StripHtml(bodyHtml);
|
bodyText = StripHtml(bodyHtml);
|
||||||
}
|
}
|
||||||
|
else if (LooksLikeHtml(bodyText))
|
||||||
|
{
|
||||||
|
bodyText = StripHtml(bodyText);
|
||||||
|
}
|
||||||
|
|
||||||
return new GmailMessageDetail(
|
return new GmailMessageDetail(
|
||||||
messageId,
|
messageId,
|
||||||
@@ -423,6 +427,17 @@ public sealed class GmailOAuthService : IGmailOAuthService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool LooksLikeHtml(string? value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(value)) return false;
|
||||||
|
return value.Contains("<html", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| value.Contains("<body", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| value.Contains("<div", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| value.Contains("<p", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| value.Contains("<br", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| value.Contains("<span", StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
private static string StripHtml(string html)
|
private static string StripHtml(string html)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(html)) return "";
|
if (string.IsNullOrWhiteSpace(html)) return "";
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ services:
|
|||||||
- Summarizer__BaseUrl=${SUMMARIZER_BASE_URL:-http://summarizer:8001}
|
- Summarizer__BaseUrl=${SUMMARIZER_BASE_URL:-http://summarizer:8001}
|
||||||
# Email (SMTP)
|
# Email (SMTP)
|
||||||
- App__PublicBaseUrl=${APP_PUBLIC_BASE_URL}
|
- App__PublicBaseUrl=${APP_PUBLIC_BASE_URL}
|
||||||
|
- App__Version=${APP_VERSION}
|
||||||
|
- App__CommitSha=${APP_COMMIT_SHA}
|
||||||
|
- App__BuildStamp=${APP_BUILD_STAMP}
|
||||||
- Email__Enabled=${EMAIL_ENABLED}
|
- Email__Enabled=${EMAIL_ENABLED}
|
||||||
- Email__SmtpHost=${EMAIL_SMTP_HOST}
|
- Email__SmtpHost=${EMAIL_SMTP_HOST}
|
||||||
- Email__SmtpPort=${EMAIL_SMTP_PORT}
|
- Email__SmtpPort=${EMAIL_SMTP_PORT}
|
||||||
|
|||||||
@@ -74,6 +74,10 @@ export default function KanbanBoard() {
|
|||||||
setJobs((prev) => prev.map((j) => (j.id === id ? { ...j, status } : j)));
|
setJobs((prev) => prev.map((j) => (j.id === id ? { ...j, status } : j)));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const currentMenuStatus = menuJobId == null
|
||||||
|
? null
|
||||||
|
: normalizeStatus(jobs.find((j) => j.id === menuJobId)?.status ?? "");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ mt: 2 }}>
|
<Box sx={{ mt: 2 }}>
|
||||||
<Typography variant="body2" sx={{ color: "text.secondary", mb: 1 }}>
|
<Typography variant="body2" sx={{ color: "text.secondary", mb: 1 }}>
|
||||||
@@ -105,7 +109,7 @@ export default function KanbanBoard() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "center", mb: 1 }}>
|
<Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "center", mb: 1 }}>
|
||||||
<Typography variant="subtitle1" sx={{ fontWeight: 800 }}>
|
<Typography variant="subtitle1" sx={{ fontWeight: 800, color: theme.palette.mode === "dark" ? "#f8fafc" : "inherit" }}>
|
||||||
{status}
|
{status}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Chip
|
<Chip
|
||||||
@@ -182,7 +186,9 @@ export default function KanbanBoard() {
|
|||||||
setMenuJobId(null);
|
setMenuJobId(null);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{(["Waiting", "Rejected", "Ghosted"] as const).map((s) => (
|
{(["Applied", "Waiting", "Interview", "Offer", "Rejected", "Ghosted"] as const)
|
||||||
|
.filter((s) => s !== currentMenuStatus)
|
||||||
|
.map((s) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={s}
|
key={s}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ type SystemStatus = {
|
|||||||
environment: string;
|
environment: string;
|
||||||
contentRoot: string;
|
contentRoot: string;
|
||||||
version: string;
|
version: string;
|
||||||
|
commitSha?: string | null;
|
||||||
|
buildStamp?: string | null;
|
||||||
storage: {
|
storage: {
|
||||||
dataRoot: string;
|
dataRoot: string;
|
||||||
dbPath: string;
|
dbPath: string;
|
||||||
@@ -89,6 +91,8 @@ export default function AdminSystemPage() {
|
|||||||
<Typography variant="overline" sx={{ color: "text.secondary" }}>Environment</Typography>
|
<Typography variant="overline" sx={{ color: "text.secondary" }}>Environment</Typography>
|
||||||
<Typography variant="h5" sx={{ fontWeight: 950 }}>{status?.environment ?? "-"}</Typography>
|
<Typography variant="h5" sx={{ fontWeight: 950 }}>{status?.environment ?? "-"}</Typography>
|
||||||
<Typography variant="body2" sx={{ color: "text.secondary", mt: 1 }}>Version {status?.version ?? "-"}</Typography>
|
<Typography variant="body2" sx={{ color: "text.secondary", mt: 1 }}>Version {status?.version ?? "-"}</Typography>
|
||||||
|
{status?.commitSha ? <Typography variant="body2" sx={{ color: "text.secondary" }}>Commit {status.commitSha}</Typography> : null}
|
||||||
|
{status?.buildStamp ? <Typography variant="body2" sx={{ color: "text.secondary" }}>{status.buildStamp}</Typography> : null}
|
||||||
</Paper>
|
</Paper>
|
||||||
<Paper sx={{ p: 2 }}>
|
<Paper sx={{ p: 2 }}>
|
||||||
<Typography variant="overline" sx={{ color: "text.secondary" }}>Database</Typography>
|
<Typography variant="overline" sx={{ color: "text.secondary" }}>Database</Typography>
|
||||||
|
|||||||
Reference in New Issue
Block a user