Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions inc/Abilities/Job/GetJobsAbility.php
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,16 @@ public function execute( array $input ): array {
$filters_applied['since'] = $args['since'];
}

if ( isset( $input['parent_job_id'] ) ) {
$args['parent_job_id'] = (int) $input['parent_job_id'];
$filters_applied['parent_job_id'] = $args['parent_job_id'];
}

if ( ! empty( $input['hide_children'] ) ) {
$args['hide_children'] = true;
$filters_applied['hide_children'] = true;
}

$jobs = $this->db_jobs->get_jobs_for_list_table( $args );
$total = $this->db_jobs->get_jobs_count( $args );

Expand Down
29 changes: 23 additions & 6 deletions inc/Api/Jobs.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,24 @@ public static function register_routes() {
'type' => 'string',
'description' => __( 'Filter by job status', 'data-machine' ),
),
'user_id' => array(
'required' => false,
'type' => 'integer',
'description' => __( 'Filter by user ID (admin only, non-admins always see own data)', 'data-machine' ),
'sanitize_callback' => 'absint',
),
'user_id' => array(
'required' => false,
'type' => 'integer',
'description' => __( 'Filter by user ID (admin only, non-admins always see own data)', 'data-machine' ),
'sanitize_callback' => 'absint',
),
'parent_job_id' => array(
'required' => false,
'type' => 'integer',
'description' => __( 'Filter by parent job ID (for batch child jobs)', 'data-machine' ),
),
'hide_children' => array(
'required' => false,
'type' => 'boolean',
'default' => false,
'description' => __( 'Hide child jobs from top-level list', 'data-machine' ),
),
),
)
);

Expand Down Expand Up @@ -198,6 +209,12 @@ public static function handle_get_jobs( $request ) {
if ( $request->get_param( 'status' ) ) {
$input['status'] = sanitize_text_field( $request->get_param( 'status' ) );
}
if ( $request->get_param( 'parent_job_id' ) ) {
$input['parent_job_id'] = (int) $request->get_param( 'parent_job_id' );
}
if ( $request->get_param( 'hide_children' ) ) {
$input['hide_children'] = true;
}

$result = self::getAbilities()->executeGetJobs( $input );

Expand Down
95 changes: 95 additions & 0 deletions inc/Core/Admin/Pages/Jobs/assets/css/jobs-page.css
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,95 @@
margin: 16px 0 0;
}

/* ========================================================================
BATCH HIERARCHY
======================================================================== */

/* Batch parent row */
.datamachine-batch-parent {
background: #f9f9f9;
}

.datamachine-batch-parent:hover {
background: #f0f0f1;
}

.datamachine-batch-parent.is-expanded {
background: #eef3f8;
border-bottom: none;
}

/* Expand/collapse arrow */
.datamachine-batch-arrow {
display: inline-block;
width: 16px;
font-size: 10px;
color: #646970;
margin-right: 4px;
}

/* Batch progress badge */
.datamachine-batch-badge {
display: inline-block;
font-size: 11px;
font-weight: 500;
padding: 2px 8px;
border-radius: 3px;
margin-left: 8px;
vertical-align: middle;
background: #f0f0f1;
color: #646970;
}

.datamachine-batch-badge--complete {
background: #d1f5d3;
color: #00a32a;
}

.datamachine-batch-badge--warning {
background: #fce4e4;
color: #d63638;
}

.datamachine-batch-badge--progress {
background: #e7f3ff;
color: #0073aa;
}

/* Child rows */
.datamachine-child-row {
background: #f6f7f7 !important;
}

.datamachine-child-row td {
border-top: 1px solid #eee;
}

.datamachine-child-id {
padding-left: 24px !important;
}

.datamachine-child-indicator {
color: #a0a5aa;
margin-right: 6px;
font-size: 14px;
}

.datamachine-child-loading {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 0;
color: #646970;
font-size: 13px;
}

.datamachine-child-empty {
color: #646970;
font-style: italic;
padding: 8px 24px !important;
}

/* Responsive */
@media screen and (max-width: 782px) {
.datamachine-jobs-header {
Expand All @@ -188,4 +277,10 @@
.datamachine-col-completed {
display: none;
}

.datamachine-batch-badge {
display: block;
margin-left: 0;
margin-top: 4px;
}
}
24 changes: 23 additions & 1 deletion inc/Core/Admin/Pages/Jobs/assets/react/api/jobs.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,19 @@ import { client } from '@shared/utils/api';
* @param {string} params.status Optional status filter
* @return {Promise<Object>} Jobs list response
*/
export const fetchJobs = ( { page = 1, perPage = 50, status } = {} ) => {
export const fetchJobs = ( {
page = 1,
perPage = 50,
status,
hideChildren = true,
} = {} ) => {
const offset = ( page - 1 ) * perPage;
const params = {
orderby: 'job_id',
order: 'DESC',
per_page: perPage,
offset,
hide_children: hideChildren ? 1 : 0,
};

if ( status && status !== 'all' ) {
Expand All @@ -36,6 +42,22 @@ export const fetchJobs = ( { page = 1, perPage = 50, status } = {} ) => {
return client.get( '/jobs', params );
};

/**
* Fetch child jobs for a batch parent
*
* @param {number} parentJobId Parent job ID
* @return {Promise<Object>} Child jobs list response
*/
export const fetchChildJobs = ( parentJobId ) => {
return client.get( '/jobs', {
parent_job_id: parentJobId,
orderby: 'job_id',
order: 'ASC',
per_page: 100,
offset: 0,
} );
};

/**
* Clear jobs
*
Expand Down
Loading
Loading