From 572cb1d42daa98294d4ca567bbb28d8f18e0847d Mon Sep 17 00:00:00 2001 From: DaKheera47 Date: Fri, 26 Dec 2025 22:25:55 +0000 Subject: [PATCH] keywords can be set from UI --- extractors/gradcracker/src/main.ts | 21 +++- orchestrator/src/client/api/client.ts | 1 + .../src/client/pages/SettingsPage.tsx | 62 +++++++++- orchestrator/src/server/api/routes.ts | 26 +++++ .../src/server/pipeline/orchestrator.ts | 76 ++++++++---- .../src/server/repositories/settings.ts | 1 + orchestrator/src/server/services/crawler.ts | 28 +++-- .../src/server/services/ukvisajobs.ts | 108 ++++++++++++------ orchestrator/src/shared/types.ts | 3 + 9 files changed, 250 insertions(+), 76 deletions(-) diff --git a/extractors/gradcracker/src/main.ts b/extractors/gradcracker/src/main.ts index 850d765..09f910a 100644 --- a/extractors/gradcracker/src/main.ts +++ b/extractors/gradcracker/src/main.ts @@ -17,11 +17,30 @@ const locations = [ ]; // roles -const roles = [ +const defaultRoles = [ "web-development", "software-systems", ]; +let roles = defaultRoles; +const envRolesRaw = process.env.GRADCRACKER_SEARCH_TERMS; + +if (envRolesRaw) { + try { + const parsed = JSON.parse(envRolesRaw) as string[]; + if (Array.isArray(parsed) && parsed.length > 0) { + roles = parsed.map(term => + term.toLowerCase() + .replace(/[^a-z0-9]+/g, '-') + .replace(/^-+|-+$/g, '') + ); + console.log(`Using configured search terms: ${roles.join(', ')}`); + } + } catch (e) { + console.warn('Failed to parse GRADCRACKER_SEARCH_TERMS', e); + } +} + // combo of locations and roles const gradcrackerUrls = locations.flatMap((location) => { return roles.map((role) => { diff --git a/orchestrator/src/client/api/client.ts b/orchestrator/src/client/api/client.ts index 43d624e..a98c74c 100644 --- a/orchestrator/src/client/api/client.ts +++ b/orchestrator/src/client/api/client.ts @@ -106,6 +106,7 @@ export async function updateSettings(update: { jobCompleteWebhookUrl?: string | null resumeProjects?: ResumeProjectsSettings | null ukvisajobsMaxJobs?: number | null + searchTerms?: string[] | null }): Promise { return fetchApi('/settings', { method: 'PATCH', diff --git a/orchestrator/src/client/pages/SettingsPage.tsx b/orchestrator/src/client/pages/SettingsPage.tsx index f90bb2a..7eb207d 100644 --- a/orchestrator/src/client/pages/SettingsPage.tsx +++ b/orchestrator/src/client/pages/SettingsPage.tsx @@ -43,6 +43,7 @@ export const SettingsPage: React.FC = () => { const [jobCompleteWebhookUrlDraft, setJobCompleteWebhookUrlDraft] = useState("") const [resumeProjectsDraft, setResumeProjectsDraft] = useState(null) const [ukvisajobsMaxJobsDraft, setUkvisajobsMaxJobsDraft] = useState(null) + const [searchTermsDraft, setSearchTermsDraft] = useState(null) const [isSaving, setIsSaving] = useState(false) const [isLoading, setIsLoading] = useState(true) @@ -59,6 +60,7 @@ export const SettingsPage: React.FC = () => { setJobCompleteWebhookUrlDraft(data.overrideJobCompleteWebhookUrl ?? "") setResumeProjectsDraft(data.resumeProjects) setUkvisajobsMaxJobsDraft(data.overrideUkvisajobsMaxJobs) + setSearchTermsDraft(data.overrideSearchTerms) }) .catch((error) => { const message = error instanceof Error ? error.message : "Failed to load settings" @@ -86,6 +88,9 @@ export const SettingsPage: React.FC = () => { const effectiveUkvisajobsMaxJobs = settings?.ukvisajobsMaxJobs ?? 50 const defaultUkvisajobsMaxJobs = settings?.defaultUkvisajobsMaxJobs ?? 50 const overrideUkvisajobsMaxJobs = settings?.overrideUkvisajobsMaxJobs + const effectiveSearchTerms = settings?.searchTerms ?? [] + const defaultSearchTerms = settings?.defaultSearchTerms ?? [] + const overrideSearchTerms = settings?.overrideSearchTerms const profileProjects = settings?.profileProjects ?? [] const maxProjectsTotal = profileProjects.length const lockedCount = resumeProjectsDraft?.lockedProjectIds.length ?? 0 @@ -99,12 +104,14 @@ export const SettingsPage: React.FC = () => { const nextJobCompleteWebhook = jobCompleteWebhookUrlDraft.trim() const currentJobCompleteWebhook = (overrideJobCompleteWebhookUrl ?? "").trim() const ukvisajobsChanged = ukvisajobsMaxJobsDraft !== (overrideUkvisajobsMaxJobs ?? null) + const searchTermsChanged = JSON.stringify(searchTermsDraft) !== JSON.stringify(overrideSearchTerms ?? null) return ( next !== current || nextWebhook !== currentWebhook || nextJobCompleteWebhook !== currentJobCompleteWebhook || !resumeProjectsEqual(resumeProjectsDraft, settings.resumeProjects) || - ukvisajobsChanged + ukvisajobsChanged || + searchTermsChanged ) }, [ settings, @@ -117,6 +124,8 @@ export const SettingsPage: React.FC = () => { resumeProjectsDraft, ukvisajobsMaxJobsDraft, overrideUkvisajobsMaxJobs, + searchTermsDraft, + overrideSearchTerms, ]) const handleSave = async () => { @@ -130,12 +139,14 @@ export const SettingsPage: React.FC = () => { ? null : resumeProjectsDraft const ukvisajobsMaxJobsOverride = ukvisajobsMaxJobsDraft === defaultUkvisajobsMaxJobs ? null : ukvisajobsMaxJobsDraft + const searchTermsOverride = arraysEqual(searchTermsDraft ?? [], defaultSearchTerms) ? null : searchTermsDraft const updated = await api.updateSettings({ model: trimmed.length > 0 ? trimmed : null, pipelineWebhookUrl: webhookTrimmed.length > 0 ? webhookTrimmed : null, jobCompleteWebhookUrl: jobCompleteTrimmed.length > 0 ? jobCompleteTrimmed : null, resumeProjects: resumeProjectsOverride, ukvisajobsMaxJobs: ukvisajobsMaxJobsOverride, + searchTerms: searchTermsOverride, }) setSettings(updated) setModelDraft(updated.overrideModel ?? "") @@ -143,6 +154,7 @@ export const SettingsPage: React.FC = () => { setJobCompleteWebhookUrlDraft(updated.overrideJobCompleteWebhookUrl ?? "") setResumeProjectsDraft(updated.resumeProjects) setUkvisajobsMaxJobsDraft(updated.overrideUkvisajobsMaxJobs) + setSearchTermsDraft(updated.overrideSearchTerms) toast.success("Settings saved") } catch (error) { const message = error instanceof Error ? error.message : "Failed to save settings" @@ -161,6 +173,7 @@ export const SettingsPage: React.FC = () => { jobCompleteWebhookUrl: null, resumeProjects: null, ukvisajobsMaxJobs: null, + searchTerms: null, }) setSettings(updated) setModelDraft("") @@ -168,6 +181,7 @@ export const SettingsPage: React.FC = () => { setJobCompleteWebhookUrlDraft("") setResumeProjectsDraft(updated.resumeProjects) setUkvisajobsMaxJobsDraft(null) + setSearchTermsDraft(null) toast.success("Reset to default") } catch (error) { const message = error instanceof Error ? error.message : "Failed to reset settings" @@ -330,6 +344,52 @@ export const SettingsPage: React.FC = () => { + + + Search Terms + + + +
+
Global search terms
+