mirror of
https://github.com/orangecoding/fredy.git
synced 2026-06-16 12:31:07 +00:00
189 lines
7.2 KiB
JavaScript
189 lines
7.2 KiB
JavaScript
import React, { Fragment, useState } from 'react';
|
|
|
|
import NotificationAdapterMutator from './components/notificationAdapter/NotificationAdapterMutator';
|
|
import NotificationAdapterTable from '../../../components/table/NotificationAdapterTable';
|
|
import ProviderTable from '../../../components/table/ProviderTable';
|
|
import ProviderMutator from './components/provider/ProviderMutator';
|
|
import Headline from '../../../components/headline/Headline';
|
|
import { useDispatch, useSelector } from 'react-redux';
|
|
import { xhrPost } from '../../../services/xhr';
|
|
import { useNavigate, useParams } from 'react-router-dom';
|
|
import { Divider, Input, Switch, Button, TagInput, Toast } from '@douyinfe/semi-ui';
|
|
import './JobMutation.less';
|
|
import { SegmentPart } from '../../../components/segment/SegmentPart';
|
|
import { IconPlusCircle } from '@douyinfe/semi-icons';
|
|
|
|
export default function JobMutator() {
|
|
const jobs = useSelector((state) => state.jobs.jobs);
|
|
const params = useParams();
|
|
|
|
const jobToBeEdit = params.jobId == null ? null : jobs.find((job) => job.id === params.jobId);
|
|
|
|
const defaultBlacklist = jobToBeEdit?.blacklist || [];
|
|
const defaultName = jobToBeEdit?.name || null;
|
|
const defaultProviderData = jobToBeEdit?.provider || [];
|
|
const defaultNotificationAdapter = jobToBeEdit?.notificationAdapter || [];
|
|
const defaultEnabled = jobToBeEdit?.enabled ?? true;
|
|
|
|
const [providerCreationVisible, setProviderCreationVisibility] = useState(false);
|
|
const [notificationCreationVisible, setNotificationCreationVisibility] = useState(false);
|
|
const [editNotificationAdapter, setEditNotificationAdapter] = useState(null);
|
|
const [providerData, setProviderData] = useState(defaultProviderData);
|
|
const [name, setName] = useState(defaultName);
|
|
const [blacklist, setBlacklist] = useState(defaultBlacklist);
|
|
const [notificationAdapterData, setNotificationAdapterData] = useState(defaultNotificationAdapter);
|
|
const [enabled, setEnabled] = useState(defaultEnabled);
|
|
const navigate = useNavigate();
|
|
const dispatch = useDispatch();
|
|
|
|
const isSavingEnabled = () => {
|
|
return Boolean(notificationAdapterData.length && providerData.length && name);
|
|
};
|
|
|
|
const mutateJob = async () => {
|
|
try {
|
|
await xhrPost('/api/jobs', {
|
|
provider: providerData,
|
|
notificationAdapter: notificationAdapterData,
|
|
name,
|
|
blacklist,
|
|
enabled,
|
|
jobId: jobToBeEdit?.id || null,
|
|
});
|
|
await dispatch.jobs.getJobs();
|
|
Toast.success('Job successfully saved...');
|
|
navigate('/jobs');
|
|
} catch (Exception) {
|
|
console.error(Exception.json.message);
|
|
Toast.error(Exception.json != null ? Exception.json.message : Exception);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Fragment>
|
|
<ProviderMutator
|
|
visible={providerCreationVisible}
|
|
onVisibilityChanged={(visible) => setProviderCreationVisibility(visible)}
|
|
onData={(data) => {
|
|
setProviderData([...providerData, data]);
|
|
}}
|
|
/>
|
|
|
|
{notificationCreationVisible && (
|
|
<NotificationAdapterMutator
|
|
visible={notificationCreationVisible}
|
|
onVisibilityChanged={(visible) => {
|
|
setEditNotificationAdapter(null);
|
|
setNotificationCreationVisibility(visible);
|
|
}}
|
|
selected={notificationAdapterData}
|
|
editNotificationAdapter={
|
|
editNotificationAdapter == null
|
|
? null
|
|
: notificationAdapterData.find((adapter) => adapter.id === editNotificationAdapter)
|
|
}
|
|
onData={(data) => {
|
|
const oldData = [...notificationAdapterData].filter((o) => o.id !== data.id);
|
|
setNotificationAdapterData([...oldData, data]);
|
|
}}
|
|
/>
|
|
)}
|
|
|
|
<Headline text={jobToBeEdit ? 'Edit a Job' : 'Create a new Job'} />
|
|
<form>
|
|
<SegmentPart name="Name">
|
|
<Input
|
|
autoFocus
|
|
type="text"
|
|
maxLength={40}
|
|
placeholder="Name"
|
|
width={6}
|
|
value={name}
|
|
onChange={(value) => setName(value)}
|
|
/>
|
|
</SegmentPart>
|
|
<Divider margin="1rem" />
|
|
<SegmentPart
|
|
name="Providers"
|
|
icon="briefcase"
|
|
helpText={`
|
|
A provider is essentially the service (e.g. ImmoScout24, Kleinanzeigen) that Fredy searches for new listings.
|
|
Fredy will open a new tab pointing to the website of this provider. You have to adjust your search parameter
|
|
and click on "Search". If the results are being shown, copy the browser URL in here.
|
|
`}
|
|
>
|
|
<Button
|
|
type="primary"
|
|
icon={<IconPlusCircle />}
|
|
className="jobMutation__newButton"
|
|
onClick={() => setProviderCreationVisibility(true)}
|
|
>
|
|
Add new Provider
|
|
</Button>
|
|
|
|
<ProviderTable
|
|
providerData={providerData}
|
|
onRemove={(providerUrl) => {
|
|
setProviderData(providerData.filter((provider) => provider.url !== providerUrl));
|
|
}}
|
|
/>
|
|
</SegmentPart>
|
|
<Divider margin="1rem" />
|
|
<SegmentPart
|
|
icon="bell"
|
|
name="Notification Adapters"
|
|
helpText="Fredy supports multiple ways to notify you about new findings. These are called notification adapter. You can chose between email, Telegram etc."
|
|
>
|
|
<Button
|
|
type="primary"
|
|
className="jobMutation__newButton"
|
|
icon={<IconPlusCircle />}
|
|
onClick={() => setNotificationCreationVisibility(true)}
|
|
>
|
|
Add new Notification Adapter
|
|
</Button>
|
|
|
|
<NotificationAdapterTable
|
|
notificationAdapter={notificationAdapterData}
|
|
onRemove={(adapterId) => {
|
|
setEditNotificationAdapter(null);
|
|
setNotificationAdapterData(notificationAdapterData.filter((adapter) => adapter.id !== adapterId));
|
|
}}
|
|
onEdit={(adapterId) => {
|
|
setEditNotificationAdapter(adapterId);
|
|
setNotificationCreationVisibility(true);
|
|
}}
|
|
/>
|
|
</SegmentPart>
|
|
<Divider margin="1rem" />
|
|
<SegmentPart
|
|
icon="bell"
|
|
name="Blacklist"
|
|
helpText="If a listing contains one of these words, it will be filtered out. Type in a word, then hit enter."
|
|
>
|
|
<TagInput
|
|
value={blacklist || []}
|
|
placeholder="Add a word for filtering..."
|
|
onChange={(v) => setBlacklist([...v])}
|
|
/>
|
|
</SegmentPart>
|
|
<Divider margin="1rem" />
|
|
<SegmentPart
|
|
icon="play circle outline"
|
|
name="Job activation"
|
|
helpText="Whether or not the job is activated. Inactive jobs will be ignored when Fredy checks for new listings."
|
|
>
|
|
<Switch className="jobMutation__spaceTop" onChange={(checked) => setEnabled(checked)} checked={enabled} />
|
|
</SegmentPart>
|
|
<Divider margin="1rem" />
|
|
<Button type="danger" style={{ marginRight: '1rem' }} onClick={() => navigate('/jobs')}>
|
|
Cancel
|
|
</Button>
|
|
<Button type="primary" icon={<IconPlusCircle />} disabled={!isSavingEnabled()} onClick={mutateJob}>
|
|
Save
|
|
</Button>
|
|
</form>
|
|
</Fragment>
|
|
);
|
|
}
|