mirror of
https://github.com/orangecoding/fredy.git
synced 2026-06-16 12:31:07 +00:00
adding buttons to remove listings from a given job
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
import restana from 'restana';
|
import restana from 'restana';
|
||||||
import * as listingStorage from '../../services/storage/listingsStorage.js';
|
import * as listingStorage from '../../services/storage/listingsStorage.js';
|
||||||
import { isAdmin as isAdminFn } from '../security.js';
|
import { isAdmin as isAdminFn } from '../security.js';
|
||||||
|
import logger from '../../services/logger.js';
|
||||||
|
|
||||||
const service = restana();
|
const service = restana();
|
||||||
|
|
||||||
const listingsRouter = service.newRouter();
|
const listingsRouter = service.newRouter();
|
||||||
@@ -8,7 +10,7 @@ const listingsRouter = service.newRouter();
|
|||||||
listingsRouter.get('/table', async (req, res) => {
|
listingsRouter.get('/table', async (req, res) => {
|
||||||
const { page, pageSize = 50, filter, sortfield = null, sortdir = 'asc' } = req.query || {};
|
const { page, pageSize = 50, filter, sortfield = null, sortdir = 'asc' } = req.query || {};
|
||||||
|
|
||||||
const result = listingStorage.queryListings({
|
res.body = listingStorage.queryListings({
|
||||||
page: page ? parseInt(page, 10) : 1,
|
page: page ? parseInt(page, 10) : 1,
|
||||||
pageSize: pageSize ? parseInt(pageSize, 10) : 50,
|
pageSize: pageSize ? parseInt(pageSize, 10) : 50,
|
||||||
filter: filter || undefined,
|
filter: filter || undefined,
|
||||||
@@ -17,7 +19,18 @@ listingsRouter.get('/table', async (req, res) => {
|
|||||||
userId: req.session.currentUser,
|
userId: req.session.currentUser,
|
||||||
isAdmin: isAdminFn(req),
|
isAdmin: isAdminFn(req),
|
||||||
});
|
});
|
||||||
res.body = result;
|
|
||||||
res.send();
|
res.send();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
listingsRouter.delete('/', async (req, res) => {
|
||||||
|
const { jobId } = req.body;
|
||||||
|
try {
|
||||||
|
listingStorage.deleteListings(jobId);
|
||||||
|
} catch (error) {
|
||||||
|
res.send(new Error(error));
|
||||||
|
logger.error(error);
|
||||||
|
}
|
||||||
|
res.send();
|
||||||
|
});
|
||||||
|
|
||||||
export { listingsRouter };
|
export { listingsRouter };
|
||||||
|
|||||||
@@ -251,3 +251,14 @@ export const queryListings = ({
|
|||||||
|
|
||||||
return { totalNumber, page: safePage, result: rows };
|
return { totalNumber, page: safePage, result: rows };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete all listings for a given job id.
|
||||||
|
*
|
||||||
|
* @param {string} jobId - The job identifier whose listings should be removed.
|
||||||
|
* @returns {any} The result from SqliteConnection.execute (may contain changes count).
|
||||||
|
*/
|
||||||
|
export const deleteListings = (jobId) => {
|
||||||
|
if (!jobId) return;
|
||||||
|
return SqliteConnection.execute(`DELETE FROM listings WHERE job_id = @jobId`, { jobId });
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { Button, Empty, Table, Switch } from '@douyinfe/semi-ui';
|
import { Button, Empty, Table, Switch, Popover } from '@douyinfe/semi-ui';
|
||||||
import { IconDelete, IconEdit, IconHistogram } from '@douyinfe/semi-icons';
|
import { IconDelete, IconDescend2, IconEdit, IconHistogram } from '@douyinfe/semi-icons';
|
||||||
import { IllustrationNoResult, IllustrationNoResultDark } from '@douyinfe/semi-illustrations';
|
import { IllustrationNoResult, IllustrationNoResultDark } from '@douyinfe/semi-illustrations';
|
||||||
|
|
||||||
import './JobTable.less';
|
import './JobTable.less';
|
||||||
@@ -14,7 +14,16 @@ const empty = (
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default function JobTable({ jobs = {}, onJobRemoval, onJobStatusChanged, onJobEdit, onJobInsight } = {}) {
|
const getPopoverContent = (text) => <article className="jobPopoverContent">{text}</article>;
|
||||||
|
|
||||||
|
export default function JobTable({
|
||||||
|
jobs = {},
|
||||||
|
onJobRemoval,
|
||||||
|
onJobStatusChanged,
|
||||||
|
onJobEdit,
|
||||||
|
onJobInsight,
|
||||||
|
onListingRemoval,
|
||||||
|
} = {}) {
|
||||||
return (
|
return (
|
||||||
<Table
|
<Table
|
||||||
pagination={false}
|
pagination={false}
|
||||||
@@ -58,9 +67,18 @@ export default function JobTable({ jobs = {}, onJobRemoval, onJobStatusChanged,
|
|||||||
render: (_, job) => {
|
render: (_, job) => {
|
||||||
return (
|
return (
|
||||||
<div className="interactions">
|
<div className="interactions">
|
||||||
<Button type="primary" icon={<IconHistogram />} onClick={() => onJobInsight(job.id)} />
|
<Popover content={getPopoverContent('Job Insights')}>
|
||||||
<Button type="secondary" icon={<IconEdit />} onClick={() => onJobEdit(job.id)} />
|
<Button type="primary" icon={<IconHistogram />} onClick={() => onJobInsight(job.id)} />
|
||||||
<Button type="danger" icon={<IconDelete />} onClick={() => onJobRemoval(job.id)} />
|
</Popover>
|
||||||
|
<Popover content={getPopoverContent('Edit a Job')}>
|
||||||
|
<Button type="secondary" icon={<IconEdit />} onClick={() => onJobEdit(job.id)} />
|
||||||
|
</Popover>
|
||||||
|
<Popover content={getPopoverContent('Delete all found Listings of this Job')}>
|
||||||
|
<Button type="danger" icon={<IconDescend2 />} onClick={() => onListingRemoval(job.id)} />
|
||||||
|
</Popover>
|
||||||
|
<Popover content={getPopoverContent('Delete Job')}>
|
||||||
|
<Button type="danger" icon={<IconDelete />} onClick={() => onJobRemoval(job.id)} />
|
||||||
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,6 +5,11 @@
|
|||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.jobPopoverContent {
|
||||||
|
padding: 1rem;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.interactions {
|
.interactions {
|
||||||
flex-direction: initial;
|
flex-direction: initial;
|
||||||
|
|||||||
@@ -16,7 +16,17 @@ export default function Jobs() {
|
|||||||
const onJobRemoval = async (jobId) => {
|
const onJobRemoval = async (jobId) => {
|
||||||
try {
|
try {
|
||||||
await xhrDelete('/api/jobs', { jobId });
|
await xhrDelete('/api/jobs', { jobId });
|
||||||
Toast.success('Job successfully remove');
|
Toast.success('Job successfully removed');
|
||||||
|
await actions.jobs.getJobs();
|
||||||
|
} catch (error) {
|
||||||
|
Toast.error(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onListingRemoval = async (jobId) => {
|
||||||
|
try {
|
||||||
|
await xhrDelete('/api/listings', { jobId });
|
||||||
|
Toast.success('Listings successfully removed');
|
||||||
await actions.jobs.getJobs();
|
await actions.jobs.getJobs();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Toast.error(error);
|
Toast.error(error);
|
||||||
@@ -49,6 +59,7 @@ export default function Jobs() {
|
|||||||
<JobTable
|
<JobTable
|
||||||
jobs={jobs || []}
|
jobs={jobs || []}
|
||||||
onJobRemoval={onJobRemoval}
|
onJobRemoval={onJobRemoval}
|
||||||
|
onListingRemoval={onListingRemoval}
|
||||||
onJobStatusChanged={onJobStatusChanged}
|
onJobStatusChanged={onJobStatusChanged}
|
||||||
onJobInsight={(jobId) => navigate(`/jobs/insights/${jobId}`)}
|
onJobInsight={(jobId) => navigate(`/jobs/insights/${jobId}`)}
|
||||||
onJobEdit={(jobId) => navigate(`/jobs/edit/${jobId}`)}
|
onJobEdit={(jobId) => navigate(`/jobs/edit/${jobId}`)}
|
||||||
|
|||||||
Reference in New Issue
Block a user