Skip to content

Commit

Permalink
Added functionality to bulk start and pause the monitorings
Browse files Browse the repository at this point in the history
  • Loading branch information
ydahal1 committed Nov 21, 2024
1 parent 25addd5 commit 0f12961
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React from 'react';
import { Menu, Dropdown, Button, message, Popconfirm } from 'antd';
import { Menu, Dropdown, Button, message, Popconfirm, Popover, Form, Select, Card, Badge } from 'antd';
import { DownOutlined } from '@ant-design/icons';

import { handleBulkDeleteJobMonitorings } from './jobMonitoringUtils';
import { handleBulkDeleteJobMonitorings, toggleJobMonitoringStatus } from './jobMonitoringUtils';

const { Option } = Select;
const JobMonitoringActionButton = ({
handleAddJobMonitoringButtonClick,
selectedRows,
Expand All @@ -13,6 +14,9 @@ const JobMonitoringActionButton = ({
setFiltersVisible,
filtersVisible,
}) => {
const [bulkStartPauseForm] = Form.useForm(); // Form Instance

// Handle bulk delete
const deleteSelected = async () => {
try {
const selectedRowIds = selectedRows.map((row) => row.id);
Expand All @@ -24,6 +28,22 @@ const JobMonitoringActionButton = ({
}
};

// Bulk start/pause job monitorings
const bulkStartPauseJobMonitorings = async () => {
try {
const action = bulkStartPauseForm.getFieldValue('action'); // Ensure correct usage of bulkStartPauseForm
const selectedRowIds = selectedRows.map((row) => row.id);
const updatedMonitorings = await toggleJobMonitoringStatus({ ids: selectedRowIds, action });
setJobMonitorings((prev) =>
prev.map((monitoring) => updatedMonitorings.find((updated) => updated.id === monitoring.id) || monitoring)
);
message.success(`Selected ${action === 'start' ? 'Job Monitorings started' : 'Job Monitorings paused'}`);
} catch (err) {
message.error('Unable to start/pause selected job monitorings');
}
};

// Handle menu selection
const handleMenuSelection = (key) => {
if (key === '1') {
handleAddJobMonitoringButtonClick();
Expand All @@ -49,6 +69,36 @@ const JobMonitoringActionButton = ({
<Menu.Item key="2" disabled={selectedRows.length < 2}>
Bulk Edit
</Menu.Item>
<Menu.Item disabled={selectedRows.length < 2}>
<Popover
placement="left"
content={
<Card size="small">
<Form layout="vertical" form={bulkStartPauseForm}>
<Form.Item label="Select Action" name="action" required>
<Select style={{ width: '18rem' }}>
<Option value="start">
<Badge color="green" style={{ marginRight: '1rem' }}></Badge>
{`Start selected ${selectedRows.length} Job Monitoring`}
</Option>
<Option value="pause">
<Badge color="red" style={{ marginRight: '1rem' }}></Badge>
{`Pause selected ${selectedRows.length} Job Monitoring`}
</Option>
</Select>
</Form.Item>
<Form.Item>
<Button type="primary" style={{ width: '100%' }} onClick={bulkStartPauseJobMonitorings}>
Apply
</Button>
</Form.Item>
</Form>
</Card>
}
trigger="hover">
<a>Bulk start/pause</a>
</Popover>
</Menu.Item>
<Menu.Item key="3" disabled={selectedRows.length < 2}>
<Popconfirm
title={`Are you sure you want to delete selected ${selectedRows.length} monitorings?. `}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const JobMonitoringTable = ({
setDisplayMonitoringDetailsModal,
setDisplayAddRejectModal,
setSelectedRows,
selectedRows,
domains,
allProductCategories,
filteringJobs,
Expand Down Expand Up @@ -271,8 +272,17 @@ const JobMonitoringTable = ({
message.error('Monitoring must be in approved state before it can be started');
return;
}
const updatedData = await toggleJobMonitoringStatus({ id: record.id });
setJobMonitorings((prev) => prev.map((monitoring) => (monitoring.id === record.id ? updatedData : monitoring)));

const updatedData = await toggleJobMonitoringStatus({ ids: [record.id] });
const updatedMonitoringIds = updatedData.map((monitoring) => monitoring.id);

setJobMonitorings((prev) =>
prev.map((monitoring) =>
updatedMonitoringIds.includes(monitoring.id)
? updatedData.find((updated) => updated.id === monitoring.id)
: monitoring
)
);
} catch (err) {
message.error('Failed to toggle monitoring status');
}
Expand All @@ -283,6 +293,7 @@ const JobMonitoringTable = ({
loading={filteringJobs}
columns={columns}
rowKey="id"
rowSelectedBgColor="var(--danger)"
size="small"
rowSelection={{
type: 'checkbox',
Expand All @@ -291,9 +302,16 @@ const JobMonitoringTable = ({
},
}}
pagination={{ pageSize: 20 }}
rowClassName={(record) =>
record?.isActive ? 'jobMonitoringTable__active-monitoring' : 'jobMonitoringTable__inactive-monitoring'
}
rowClassName={(record) => {
let className = record?.isActive
? 'jobMonitoringTable__active-monitoring'
: 'jobMonitoringTable__inactive-monitoring';
const idsOfSelectedRows = selectedRows.map((row) => row.id);
if (idsOfSelectedRows.includes(record.id)) {
className += ' jobMonitoringTable__selected-row';
}
return className;
}}
/>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,7 @@ function JobMonitoring() {
setDisplayAddRejectModal={setDisplayAddRejectModal}
applicationId={applicationId}
setSelectedRows={setSelectedRows}
selectedRows={selectedRows}
domains={domains}
productCategories={productCategories}
allProductCategories={allProductCategories}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@
background-color: var(--secondary-light);
}

.jobMonitoringTable__selected-row > .ant-table-cell {
background-color: rgba(255, 255, 0, 0.1) !important;
}
/* Filters ------------------------------------------------------------------ */

.notifications__filter-label {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,11 @@ export const identifyErroneousTabs = ({ erroneousFields }) => {
};

//Toggle job monitoring status, just post the id of the job monitoring to /toggle in the req body
export const toggleJobMonitoringStatus = async ({ id }) => {
export const toggleJobMonitoringStatus = async ({ ids, action }) => {
const payload = {
method: 'PATCH',
headers: authHeader(),
body: JSON.stringify({ id }),
body: JSON.stringify({ ids, action }),
};

const response = await fetch(`/api/jobmonitoring/toggleIsActive`, payload);
Expand All @@ -140,7 +140,8 @@ export const toggleJobMonitoringStatus = async ({ id }) => {
}

const data = await response.json();
return data;

return data.updatedJobMonitorings;
};

// Bulk delete job monitorings
Expand Down
87 changes: 70 additions & 17 deletions Tombolo/server/routes/jobmonitoring/read.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const express = require("express");
const router = express.Router();
const Sequelize = require("sequelize");
const { body, check, param } = require("express-validator");

//Local imports
Expand All @@ -9,6 +10,7 @@ const { validationResult } = require("express-validator");

//Constants
const JobMonitoring = models.jobMonitoring;
const Op = Sequelize.Op;

// Create new job monitoring
router.post(
Expand Down Expand Up @@ -253,40 +255,91 @@ router.delete(
router.patch(
"/toggleIsActive",
[
body("id").isUUID().withMessage("ID must be a valid UUID"),
body("ids").isArray().withMessage("Invalid ids"), // Ensure ids is an array
body("ids.*").isUUID().withMessage("Invalid id"), // Ensure each id is a valid UUID
// make action optional and when provided must be either start or pause
body("action")
.optional()
.isIn(["start", "pause"])
.withMessage("Action must be either start or pause"),
],
async (req, res) => {

// Handle the PATCH request here
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(503).send("Failed to toggle");
return res.status(400).send("Failed to toggle"); // Use a valid status code
}

let transaction;

try {
const { id } = req.body;
// Get and toggle
const jobMonitoring = await JobMonitoring.findByPk(id);
if (!jobMonitoring) {
logger.error("Toggle Job monitoring - Job monitoring not found");
return res.status(404).send("Job monitoring not found");
transaction = await JobMonitoring.sequelize.transaction();
const { ids, action } = req.body; // Expecting an array of IDs

// Find all job monitorings with the given IDs
const jobMonitorings = await JobMonitoring.findAll({
where: { id: { [Op.in]: ids } },
});

if (jobMonitorings.length === 0) {
logger.error("Toggle Job monitoring - Job monitorings not found");
return res.status(404).send("Job monitorings not found");
}
const isApproved = jobMonitoring.approvalStatus === "Approved";
if (!isApproved) {
logger.error("Toggle Job monitoring - Job monitoring not approved");
return res.status(503).send("Can't toggle job monitoring that is not in approved state");

// Filter out the job monitorings that are not approved
const approvedJobMonitorings = jobMonitorings.filter(
(jobMonitoring) => jobMonitoring.approvalStatus === "Approved"
);

if (approvedJobMonitorings.length === 0) {
logger.error(
"Toggle Job monitoring - No approved job monitorings found"
);
return res.status(400).send("No approved job monitorings to toggle"); // Use a valid status code
}
const currentStatus = jobMonitoring.isActive;
const data = await jobMonitoring.update({ isActive: !currentStatus });

res.status(200).send(data);
// Get the IDs of the approved job monitorings
const approvedIds = approvedJobMonitorings.map(
(jobMonitoring) => jobMonitoring.id
);

if(action){
// If action is start or pause change isActive to true or false respectively
await JobMonitoring.update(
{ isActive: action === "start" },
{
where: { id: { [Op.in]: approvedIds } },
transaction,
}
);
}else{
// Toggle the isActive status for all approved job monitorings
await JobMonitoring.update(
{ isActive: Sequelize.literal("NOT isActive") },
{
where: { id: { [Op.in]: approvedIds } },
transaction,
}
);
}

await transaction.commit();

// Get all updated job monitorings
const updatedJobMonitorings = await JobMonitoring.findAll({
where: { id: { [Op.in]: approvedIds } },
});

res.status(200).send({ success: true, message: "Toggled successfully", updatedJobMonitorings }); // Send the updated job monitorings
} catch (err) {
logger.error(err);
await transaction.rollback();
logger.error(err.message);
res.status(500).send("Failed to toggle job monitoring");
}
}
);

module.exports = router;
// Bulk update - only primary, secondary and notify contact are part of bulk update for now
router.patch(
"/bulkUpdate",
Expand Down

0 comments on commit 0f12961

Please sign in to comment.