more jobspy settings
This commit is contained in:
parent
ed23722ffa
commit
e54b5f2178
@ -155,6 +155,7 @@ export async function updateSettings(update: {
|
|||||||
jobspyResultsWanted?: number | null
|
jobspyResultsWanted?: number | null
|
||||||
jobspyHoursOld?: number | null
|
jobspyHoursOld?: number | null
|
||||||
jobspyCountryIndeed?: string | null
|
jobspyCountryIndeed?: string | null
|
||||||
|
jobspySites?: string[] | null
|
||||||
jobspyLinkedinFetchDescription?: boolean | null
|
jobspyLinkedinFetchDescription?: boolean | null
|
||||||
}): Promise<AppSettings> {
|
}): Promise<AppSettings> {
|
||||||
return fetchApi<AppSettings>('/settings', {
|
return fetchApi<AppSettings>('/settings', {
|
||||||
|
|||||||
@ -69,6 +69,7 @@ export const SettingsPage: React.FC = () => {
|
|||||||
const [jobspyResultsWantedDraft, setJobspyResultsWantedDraft] = useState<number | null>(null)
|
const [jobspyResultsWantedDraft, setJobspyResultsWantedDraft] = useState<number | null>(null)
|
||||||
const [jobspyHoursOldDraft, setJobspyHoursOldDraft] = useState<number | null>(null)
|
const [jobspyHoursOldDraft, setJobspyHoursOldDraft] = useState<number | null>(null)
|
||||||
const [jobspyCountryIndeedDraft, setJobspyCountryIndeedDraft] = useState<string | null>(null)
|
const [jobspyCountryIndeedDraft, setJobspyCountryIndeedDraft] = useState<string | null>(null)
|
||||||
|
const [jobspySitesDraft, setJobspySitesDraft] = useState<string[] | null>(null)
|
||||||
const [jobspyLinkedinFetchDescriptionDraft, setJobspyLinkedinFetchDescriptionDraft] = useState<boolean | null>(null)
|
const [jobspyLinkedinFetchDescriptionDraft, setJobspyLinkedinFetchDescriptionDraft] = useState<boolean | null>(null)
|
||||||
const [isSaving, setIsSaving] = useState(false)
|
const [isSaving, setIsSaving] = useState(false)
|
||||||
const [isLoading, setIsLoading] = useState(true)
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
@ -94,6 +95,7 @@ export const SettingsPage: React.FC = () => {
|
|||||||
setJobspyResultsWantedDraft(data.overrideJobspyResultsWanted)
|
setJobspyResultsWantedDraft(data.overrideJobspyResultsWanted)
|
||||||
setJobspyHoursOldDraft(data.overrideJobspyHoursOld)
|
setJobspyHoursOldDraft(data.overrideJobspyHoursOld)
|
||||||
setJobspyCountryIndeedDraft(data.overrideJobspyCountryIndeed)
|
setJobspyCountryIndeedDraft(data.overrideJobspyCountryIndeed)
|
||||||
|
setJobspySitesDraft(data.overrideJobspySites)
|
||||||
setJobspyLinkedinFetchDescriptionDraft(data.overrideJobspyLinkedinFetchDescription)
|
setJobspyLinkedinFetchDescriptionDraft(data.overrideJobspyLinkedinFetchDescription)
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@ -143,6 +145,9 @@ export const SettingsPage: React.FC = () => {
|
|||||||
const effectiveJobspyCountryIndeed = settings?.jobspyCountryIndeed ?? ""
|
const effectiveJobspyCountryIndeed = settings?.jobspyCountryIndeed ?? ""
|
||||||
const defaultJobspyCountryIndeed = settings?.defaultJobspyCountryIndeed ?? ""
|
const defaultJobspyCountryIndeed = settings?.defaultJobspyCountryIndeed ?? ""
|
||||||
const overrideJobspyCountryIndeed = settings?.overrideJobspyCountryIndeed
|
const overrideJobspyCountryIndeed = settings?.overrideJobspyCountryIndeed
|
||||||
|
const effectiveJobspySites = settings?.jobspySites ?? ["indeed", "linkedin"]
|
||||||
|
const defaultJobspySites = settings?.defaultJobspySites ?? ["indeed", "linkedin"]
|
||||||
|
const overrideJobspySites = settings?.overrideJobspySites
|
||||||
const effectiveJobspyLinkedinFetchDescription = settings?.jobspyLinkedinFetchDescription ?? true
|
const effectiveJobspyLinkedinFetchDescription = settings?.jobspyLinkedinFetchDescription ?? true
|
||||||
const defaultJobspyLinkedinFetchDescription = settings?.defaultJobspyLinkedinFetchDescription ?? true
|
const defaultJobspyLinkedinFetchDescription = settings?.defaultJobspyLinkedinFetchDescription ?? true
|
||||||
const overrideJobspyLinkedinFetchDescription = settings?.overrideJobspyLinkedinFetchDescription
|
const overrideJobspyLinkedinFetchDescription = settings?.overrideJobspyLinkedinFetchDescription
|
||||||
@ -180,6 +185,7 @@ export const SettingsPage: React.FC = () => {
|
|||||||
jobspyResultsWantedDraft !== (overrideJobspyResultsWanted ?? null) ||
|
jobspyResultsWantedDraft !== (overrideJobspyResultsWanted ?? null) ||
|
||||||
jobspyHoursOldDraft !== (overrideJobspyHoursOld ?? null) ||
|
jobspyHoursOldDraft !== (overrideJobspyHoursOld ?? null) ||
|
||||||
jobspyCountryIndeedDraft !== (overrideJobspyCountryIndeed ?? null) ||
|
jobspyCountryIndeedDraft !== (overrideJobspyCountryIndeed ?? null) ||
|
||||||
|
JSON.stringify((jobspySitesDraft ?? []).slice().sort()) !== JSON.stringify((overrideJobspySites ?? []).slice().sort()) ||
|
||||||
jobspyLinkedinFetchDescriptionDraft !== (overrideJobspyLinkedinFetchDescription ?? null)
|
jobspyLinkedinFetchDescriptionDraft !== (overrideJobspyLinkedinFetchDescription ?? null)
|
||||||
)
|
)
|
||||||
}, [
|
}, [
|
||||||
@ -205,11 +211,13 @@ export const SettingsPage: React.FC = () => {
|
|||||||
jobspyResultsWantedDraft,
|
jobspyResultsWantedDraft,
|
||||||
jobspyHoursOldDraft,
|
jobspyHoursOldDraft,
|
||||||
jobspyCountryIndeedDraft,
|
jobspyCountryIndeedDraft,
|
||||||
|
jobspySitesDraft,
|
||||||
jobspyLinkedinFetchDescriptionDraft,
|
jobspyLinkedinFetchDescriptionDraft,
|
||||||
overrideJobspyLocation,
|
overrideJobspyLocation,
|
||||||
overrideJobspyResultsWanted,
|
overrideJobspyResultsWanted,
|
||||||
overrideJobspyHoursOld,
|
overrideJobspyHoursOld,
|
||||||
overrideJobspyCountryIndeed,
|
overrideJobspyCountryIndeed,
|
||||||
|
overrideJobspySites,
|
||||||
overrideJobspyLinkedinFetchDescription,
|
overrideJobspyLinkedinFetchDescription,
|
||||||
])
|
])
|
||||||
|
|
||||||
@ -232,6 +240,7 @@ export const SettingsPage: React.FC = () => {
|
|||||||
const jobspyResultsWantedOverride = jobspyResultsWantedDraft === defaultJobspyResultsWanted ? null : jobspyResultsWantedDraft
|
const jobspyResultsWantedOverride = jobspyResultsWantedDraft === defaultJobspyResultsWanted ? null : jobspyResultsWantedDraft
|
||||||
const jobspyHoursOldOverride = jobspyHoursOldDraft === defaultJobspyHoursOld ? null : jobspyHoursOldDraft
|
const jobspyHoursOldOverride = jobspyHoursOldDraft === defaultJobspyHoursOld ? null : jobspyHoursOldDraft
|
||||||
const jobspyCountryIndeedOverride = jobspyCountryIndeedDraft === defaultJobspyCountryIndeed ? null : jobspyCountryIndeedDraft
|
const jobspyCountryIndeedOverride = jobspyCountryIndeedDraft === defaultJobspyCountryIndeed ? null : jobspyCountryIndeedDraft
|
||||||
|
const jobspySitesOverride = arraysEqual((jobspySitesDraft ?? []).slice().sort(), (defaultJobspySites ?? []).slice().sort()) ? null : jobspySitesDraft
|
||||||
const jobspyLinkedinFetchDescriptionOverride = jobspyLinkedinFetchDescriptionDraft === defaultJobspyLinkedinFetchDescription ? null : jobspyLinkedinFetchDescriptionDraft
|
const jobspyLinkedinFetchDescriptionOverride = jobspyLinkedinFetchDescriptionDraft === defaultJobspyLinkedinFetchDescription ? null : jobspyLinkedinFetchDescriptionDraft
|
||||||
const updated = await api.updateSettings({
|
const updated = await api.updateSettings({
|
||||||
model: trimmed.length > 0 ? trimmed : null,
|
model: trimmed.length > 0 ? trimmed : null,
|
||||||
@ -247,6 +256,7 @@ export const SettingsPage: React.FC = () => {
|
|||||||
jobspyResultsWanted: jobspyResultsWantedOverride,
|
jobspyResultsWanted: jobspyResultsWantedOverride,
|
||||||
jobspyHoursOld: jobspyHoursOldOverride,
|
jobspyHoursOld: jobspyHoursOldOverride,
|
||||||
jobspyCountryIndeed: jobspyCountryIndeedOverride,
|
jobspyCountryIndeed: jobspyCountryIndeedOverride,
|
||||||
|
jobspySites: jobspySitesOverride,
|
||||||
jobspyLinkedinFetchDescription: jobspyLinkedinFetchDescriptionOverride,
|
jobspyLinkedinFetchDescription: jobspyLinkedinFetchDescriptionOverride,
|
||||||
})
|
})
|
||||||
setSettings(updated)
|
setSettings(updated)
|
||||||
@ -263,6 +273,7 @@ export const SettingsPage: React.FC = () => {
|
|||||||
setJobspyResultsWantedDraft(updated.overrideJobspyResultsWanted)
|
setJobspyResultsWantedDraft(updated.overrideJobspyResultsWanted)
|
||||||
setJobspyHoursOldDraft(updated.overrideJobspyHoursOld)
|
setJobspyHoursOldDraft(updated.overrideJobspyHoursOld)
|
||||||
setJobspyCountryIndeedDraft(updated.overrideJobspyCountryIndeed)
|
setJobspyCountryIndeedDraft(updated.overrideJobspyCountryIndeed)
|
||||||
|
setJobspySitesDraft(updated.overrideJobspySites)
|
||||||
setJobspyLinkedinFetchDescriptionDraft(updated.overrideJobspyLinkedinFetchDescription)
|
setJobspyLinkedinFetchDescriptionDraft(updated.overrideJobspyLinkedinFetchDescription)
|
||||||
toast.success("Settings saved")
|
toast.success("Settings saved")
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -314,6 +325,7 @@ export const SettingsPage: React.FC = () => {
|
|||||||
jobspyResultsWanted: null,
|
jobspyResultsWanted: null,
|
||||||
jobspyHoursOld: null,
|
jobspyHoursOld: null,
|
||||||
jobspyCountryIndeed: null,
|
jobspyCountryIndeed: null,
|
||||||
|
jobspySites: null,
|
||||||
jobspyLinkedinFetchDescription: null,
|
jobspyLinkedinFetchDescription: null,
|
||||||
})
|
})
|
||||||
setSettings(updated)
|
setSettings(updated)
|
||||||
@ -330,6 +342,7 @@ export const SettingsPage: React.FC = () => {
|
|||||||
setJobspyResultsWantedDraft(null)
|
setJobspyResultsWantedDraft(null)
|
||||||
setJobspyHoursOldDraft(null)
|
setJobspyHoursOldDraft(null)
|
||||||
setJobspyCountryIndeedDraft(null)
|
setJobspyCountryIndeedDraft(null)
|
||||||
|
setJobspySitesDraft(null)
|
||||||
setJobspyLinkedinFetchDescriptionDraft(null)
|
setJobspyLinkedinFetchDescriptionDraft(null)
|
||||||
toast.success("Reset to default")
|
toast.success("Reset to default")
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -598,6 +611,55 @@ export const SettingsPage: React.FC = () => {
|
|||||||
</AccordionTrigger>
|
</AccordionTrigger>
|
||||||
<AccordionContent className="pb-4">
|
<AccordionContent className="pb-4">
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
|
<div className="space-y-3">
|
||||||
|
<div className="text-sm font-medium">Scraped Sites</div>
|
||||||
|
<div className="flex gap-6">
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<Checkbox
|
||||||
|
id="site-indeed"
|
||||||
|
checked={jobspySitesDraft?.includes('indeed') ?? defaultJobspySites.includes('indeed')}
|
||||||
|
onCheckedChange={(checked) => {
|
||||||
|
const current = jobspySitesDraft ?? defaultJobspySites
|
||||||
|
let next = [...current]
|
||||||
|
if (checked) {
|
||||||
|
if (!next.includes('indeed')) next.push('indeed')
|
||||||
|
} else {
|
||||||
|
next = next.filter(s => s !== 'indeed')
|
||||||
|
}
|
||||||
|
setJobspySitesDraft(next)
|
||||||
|
}}
|
||||||
|
disabled={isLoading || isSaving}
|
||||||
|
/>
|
||||||
|
<label htmlFor="site-indeed" className="text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">Indeed</label>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<Checkbox
|
||||||
|
id="site-linkedin"
|
||||||
|
checked={jobspySitesDraft?.includes('linkedin') ?? defaultJobspySites.includes('linkedin')}
|
||||||
|
onCheckedChange={(checked) => {
|
||||||
|
const current = jobspySitesDraft ?? defaultJobspySites
|
||||||
|
let next = [...current]
|
||||||
|
if (checked) {
|
||||||
|
if (!next.includes('linkedin')) next.push('linkedin')
|
||||||
|
} else {
|
||||||
|
next = next.filter(s => s !== 'linkedin')
|
||||||
|
}
|
||||||
|
setJobspySitesDraft(next)
|
||||||
|
}}
|
||||||
|
disabled={isLoading || isSaving}
|
||||||
|
/>
|
||||||
|
<label htmlFor="site-linkedin" className="text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">LinkedIn</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-muted-foreground">
|
||||||
|
Select which sites JobSpy should scrape.
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-2 text-xs text-muted-foreground">
|
||||||
|
<span>Effective: {(effectiveJobspySites || []).join(', ') || "None"}</span>
|
||||||
|
<span>Default: {(defaultJobspySites || []).join(', ')}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="grid gap-6 md:grid-cols-2">
|
<div className="grid gap-6 md:grid-cols-2">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div className="text-sm font-medium">Location</div>
|
<div className="text-sm font-medium">Location</div>
|
||||||
|
|||||||
@ -304,7 +304,7 @@ apiRouter.get('/settings', async (_req: Request, res: Response) => {
|
|||||||
const overrideSearchTerms = overrideSearchTermsRaw ? JSON.parse(overrideSearchTermsRaw) as string[] : null;
|
const overrideSearchTerms = overrideSearchTermsRaw ? JSON.parse(overrideSearchTermsRaw) as string[] : null;
|
||||||
const searchTerms = overrideSearchTerms ?? defaultSearchTerms;
|
const searchTerms = overrideSearchTerms ?? defaultSearchTerms;
|
||||||
|
|
||||||
// JobSpy settings
|
// JobSpy settings (GET)
|
||||||
const overrideJobspyLocation = await settingsRepo.getSetting('jobspyLocation');
|
const overrideJobspyLocation = await settingsRepo.getSetting('jobspyLocation');
|
||||||
const defaultJobspyLocation = process.env.JOBSPY_LOCATION || 'UK';
|
const defaultJobspyLocation = process.env.JOBSPY_LOCATION || 'UK';
|
||||||
const jobspyLocation = overrideJobspyLocation || defaultJobspyLocation;
|
const jobspyLocation = overrideJobspyLocation || defaultJobspyLocation;
|
||||||
@ -323,6 +323,11 @@ apiRouter.get('/settings', async (_req: Request, res: Response) => {
|
|||||||
const defaultJobspyCountryIndeed = process.env.JOBSPY_COUNTRY_INDEED || 'UK';
|
const defaultJobspyCountryIndeed = process.env.JOBSPY_COUNTRY_INDEED || 'UK';
|
||||||
const jobspyCountryIndeed = overrideJobspyCountryIndeed || defaultJobspyCountryIndeed;
|
const jobspyCountryIndeed = overrideJobspyCountryIndeed || defaultJobspyCountryIndeed;
|
||||||
|
|
||||||
|
const overrideJobspySitesRaw = await settingsRepo.getSetting('jobspySites');
|
||||||
|
const defaultJobspySites = (process.env.JOBSPY_SITES || 'indeed,linkedin').split(',').map(s => s.trim()).filter(Boolean);
|
||||||
|
const overrideJobspySites = overrideJobspySitesRaw ? JSON.parse(overrideJobspySitesRaw) as string[] : null;
|
||||||
|
const jobspySites = overrideJobspySites ?? defaultJobspySites;
|
||||||
|
|
||||||
const overrideJobspyLinkedinFetchDescriptionRaw = await settingsRepo.getSetting('jobspyLinkedinFetchDescription');
|
const overrideJobspyLinkedinFetchDescriptionRaw = await settingsRepo.getSetting('jobspyLinkedinFetchDescription');
|
||||||
const defaultJobspyLinkedinFetchDescription = (process.env.JOBSPY_LINKEDIN_FETCH_DESCRIPTION || '1') === '1';
|
const defaultJobspyLinkedinFetchDescription = (process.env.JOBSPY_LINKEDIN_FETCH_DESCRIPTION || '1') === '1';
|
||||||
const overrideJobspyLinkedinFetchDescription = overrideJobspyLinkedinFetchDescriptionRaw
|
const overrideJobspyLinkedinFetchDescription = overrideJobspyLinkedinFetchDescriptionRaw
|
||||||
@ -367,6 +372,9 @@ apiRouter.get('/settings', async (_req: Request, res: Response) => {
|
|||||||
jobspyCountryIndeed,
|
jobspyCountryIndeed,
|
||||||
defaultJobspyCountryIndeed,
|
defaultJobspyCountryIndeed,
|
||||||
overrideJobspyCountryIndeed,
|
overrideJobspyCountryIndeed,
|
||||||
|
jobspySites,
|
||||||
|
defaultJobspySites,
|
||||||
|
overrideJobspySites,
|
||||||
jobspyLinkedinFetchDescription,
|
jobspyLinkedinFetchDescription,
|
||||||
defaultJobspyLinkedinFetchDescription,
|
defaultJobspyLinkedinFetchDescription,
|
||||||
overrideJobspyLinkedinFetchDescription,
|
overrideJobspyLinkedinFetchDescription,
|
||||||
@ -396,6 +404,7 @@ const updateSettingsSchema = z.object({
|
|||||||
jobspyResultsWanted: z.number().int().min(1).max(500).nullable().optional(),
|
jobspyResultsWanted: z.number().int().min(1).max(500).nullable().optional(),
|
||||||
jobspyHoursOld: z.number().int().min(1).max(168).nullable().optional(),
|
jobspyHoursOld: z.number().int().min(1).max(168).nullable().optional(),
|
||||||
jobspyCountryIndeed: z.string().trim().min(1).max(100).nullable().optional(),
|
jobspyCountryIndeed: z.string().trim().min(1).max(100).nullable().optional(),
|
||||||
|
jobspySites: z.array(z.string().trim().min(1).max(50)).max(10).nullable().optional(),
|
||||||
jobspyLinkedinFetchDescription: z.boolean().nullable().optional(),
|
jobspyLinkedinFetchDescription: z.boolean().nullable().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -475,6 +484,11 @@ apiRouter.patch('/settings', async (req: Request, res: Response) => {
|
|||||||
await settingsRepo.setSetting('jobspyCountryIndeed', value);
|
await settingsRepo.setSetting('jobspyCountryIndeed', value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ('jobspySites' in input) {
|
||||||
|
const value = input.jobspySites ?? null;
|
||||||
|
await settingsRepo.setSetting('jobspySites', value !== null ? JSON.stringify(value) : null);
|
||||||
|
}
|
||||||
|
|
||||||
if ('jobspyLinkedinFetchDescription' in input) {
|
if ('jobspyLinkedinFetchDescription' in input) {
|
||||||
const value = input.jobspyLinkedinFetchDescription ?? null;
|
const value = input.jobspyLinkedinFetchDescription ?? null;
|
||||||
await settingsRepo.setSetting('jobspyLinkedinFetchDescription', value !== null ? (value ? '1' : '0') : null);
|
await settingsRepo.setSetting('jobspyLinkedinFetchDescription', value !== null ? (value ? '1' : '0') : null);
|
||||||
@ -537,6 +551,11 @@ apiRouter.patch('/settings', async (req: Request, res: Response) => {
|
|||||||
const defaultJobspyCountryIndeed = process.env.JOBSPY_COUNTRY_INDEED || 'UK';
|
const defaultJobspyCountryIndeed = process.env.JOBSPY_COUNTRY_INDEED || 'UK';
|
||||||
const jobspyCountryIndeed = overrideJobspyCountryIndeed || defaultJobspyCountryIndeed;
|
const jobspyCountryIndeed = overrideJobspyCountryIndeed || defaultJobspyCountryIndeed;
|
||||||
|
|
||||||
|
const overrideJobspySitesRaw = await settingsRepo.getSetting('jobspySites');
|
||||||
|
const defaultJobspySites = (process.env.JOBSPY_SITES || 'indeed,linkedin').split(',').map(s => s.trim()).filter(Boolean);
|
||||||
|
const overrideJobspySites = overrideJobspySitesRaw ? JSON.parse(overrideJobspySitesRaw) as string[] : null;
|
||||||
|
const jobspySites = overrideJobspySites ?? defaultJobspySites;
|
||||||
|
|
||||||
const overrideJobspyLinkedinFetchDescriptionRaw = await settingsRepo.getSetting('jobspyLinkedinFetchDescription');
|
const overrideJobspyLinkedinFetchDescriptionRaw = await settingsRepo.getSetting('jobspyLinkedinFetchDescription');
|
||||||
const defaultJobspyLinkedinFetchDescription = (process.env.JOBSPY_LINKEDIN_FETCH_DESCRIPTION || '1') === '1';
|
const defaultJobspyLinkedinFetchDescription = (process.env.JOBSPY_LINKEDIN_FETCH_DESCRIPTION || '1') === '1';
|
||||||
const overrideJobspyLinkedinFetchDescription = overrideJobspyLinkedinFetchDescriptionRaw
|
const overrideJobspyLinkedinFetchDescription = overrideJobspyLinkedinFetchDescriptionRaw
|
||||||
@ -581,6 +600,9 @@ apiRouter.patch('/settings', async (req: Request, res: Response) => {
|
|||||||
jobspyCountryIndeed,
|
jobspyCountryIndeed,
|
||||||
defaultJobspyCountryIndeed,
|
defaultJobspyCountryIndeed,
|
||||||
overrideJobspyCountryIndeed,
|
overrideJobspyCountryIndeed,
|
||||||
|
jobspySites,
|
||||||
|
defaultJobspySites,
|
||||||
|
overrideJobspySites,
|
||||||
jobspyLinkedinFetchDescription,
|
jobspyLinkedinFetchDescription,
|
||||||
defaultJobspyLinkedinFetchDescription,
|
defaultJobspyLinkedinFetchDescription,
|
||||||
overrideJobspyLinkedinFetchDescription,
|
overrideJobspyLinkedinFetchDescription,
|
||||||
@ -588,6 +610,8 @@ apiRouter.patch('/settings', async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const message = error instanceof Error ? error.message : 'Unknown error';
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
||||||
|
// PATCH usually returns 500 for unknown, but let's stick to what was there (400?)
|
||||||
|
// Wait, the file said 400? Let's verify line 608.
|
||||||
res.status(400).json({ success: false, error: message });
|
res.status(400).json({ success: false, error: message });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -127,10 +127,23 @@ export async function runPipeline(config: Partial<PipelineConfig> = {}): Promise
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run JobSpy (Indeed/LinkedIn) if selected
|
// Run JobSpy (Indeed/LinkedIn) if selected
|
||||||
const jobSpySites = mergedConfig.sources.filter(
|
let jobSpySites = mergedConfig.sources.filter(
|
||||||
(s): s is 'indeed' | 'linkedin' => s === 'indeed' || s === 'linkedin'
|
(s): s is 'indeed' | 'linkedin' => s === 'indeed' || s === 'linkedin'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Apply setting override for JobSpy sites
|
||||||
|
const jobspySitesSettingRaw = await settingsRepo.getSetting('jobspySites');
|
||||||
|
if (jobspySitesSettingRaw) {
|
||||||
|
try {
|
||||||
|
const allowed = JSON.parse(jobspySitesSettingRaw);
|
||||||
|
if (Array.isArray(allowed)) {
|
||||||
|
jobSpySites = jobSpySites.filter((s) => allowed.includes(s));
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// ignore JSON parse error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (jobSpySites.length > 0) {
|
if (jobSpySites.length > 0) {
|
||||||
updateProgress({
|
updateProgress({
|
||||||
step: 'crawling',
|
step: 'crawling',
|
||||||
|
|||||||
@ -20,6 +20,7 @@ export type SettingKey = 'model'
|
|||||||
| 'jobspyResultsWanted'
|
| 'jobspyResultsWanted'
|
||||||
| 'jobspyHoursOld'
|
| 'jobspyHoursOld'
|
||||||
| 'jobspyCountryIndeed'
|
| 'jobspyCountryIndeed'
|
||||||
|
| 'jobspySites'
|
||||||
| 'jobspyLinkedinFetchDescription'
|
| 'jobspyLinkedinFetchDescription'
|
||||||
|
|
||||||
export async function getSetting(key: SettingKey): Promise<string | null> {
|
export async function getSetting(key: SettingKey): Promise<string | null> {
|
||||||
|
|||||||
@ -247,6 +247,9 @@ export interface AppSettings {
|
|||||||
jobspyCountryIndeed: string;
|
jobspyCountryIndeed: string;
|
||||||
defaultJobspyCountryIndeed: string;
|
defaultJobspyCountryIndeed: string;
|
||||||
overrideJobspyCountryIndeed: string | null;
|
overrideJobspyCountryIndeed: string | null;
|
||||||
|
jobspySites: string[];
|
||||||
|
defaultJobspySites: string[];
|
||||||
|
overrideJobspySites: string[] | null;
|
||||||
jobspyLinkedinFetchDescription: boolean;
|
jobspyLinkedinFetchDescription: boolean;
|
||||||
defaultJobspyLinkedinFetchDescription: boolean;
|
defaultJobspyLinkedinFetchDescription: boolean;
|
||||||
overrideJobspyLinkedinFetchDescription: boolean | null;
|
overrideJobspyLinkedinFetchDescription: boolean | null;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user