feat: Pipeline Settings M2 — decompose Content/AI Models/Sources into per-step panels + Global Content Context (#172, v0.24.0)

Relocates Content/AI Models/Sources fields into the per-step Pipeline panels; adds a Global Content Context block; retires the 3 duplicate Settings tabs. Option keys unchanged (no migration). QA APPROVE for 80d8e5f; CI green.

Agent-Session: pipeline-settings-m2-merge
This commit is contained in:
peptiderepo
2026-06-23 12:03:03 +07:00
committed by GitHub
parent 37cfb2f244
commit 8b789b3f1b
17 changed files with 1308 additions and 380 deletions

View File

@@ -12,26 +12,30 @@
* array $view['step_data'] — assembled view data for the active step.
* float $view['monthly_spend']— current month's LLM spend in USD.
* float $view['budget'] — configured monthly budget cap in USD.
* array $view['global_fields']— field defs + current values for global context.
* string $view['step_context'] — context id matching the active step, or null.
* array $view['step_fields'] — field defs + current values for active step context.
*
* Prompt panels are rendered via the pipeline-settings-prompt-panel.php partial.
*
* @see admin/class-pipeline-settings-renderer.php — Provides $view.
* @see admin/class-pipeline-settings-page.php — Includes this template.
* @see templates/admin/pipeline-settings-prompt-panel.php — Prompt editor partial.
* @see admin/class-pipeline-settings-renderer.php — Provides $view.
* @see templates/admin/pipeline-settings-prompt-panel.php — Prompt editor partial.
* @see templates/admin/pipeline-settings-step-options.php — Step option fields partial.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
$steps = $view['steps'];
$active_step = $view['active_step'];
$save_result = $view['save_result'];
$nonce_field = $view['nonce_field'];
$nonce_action = $view['nonce_action'];
$page_slug = $view['page_slug'];
$step_data = $view['step_data'];
$steps = $view['steps'];
$active_step = $view['active_step'];
$save_result = $view['save_result'];
$nonce_field = $view['nonce_field'];
$nonce_action = $view['nonce_action'];
$page_slug = $view['page_slug'];
$step_data = $view['step_data'];
$monthly_spend = $view['monthly_spend'];
$budget = $view['budget'];
$global_fields = $view['global_fields'];
$step_context = $view['step_context'];
$step_fields = $view['step_fields'];
$base_url = admin_url( 'admin.php?page=' . rawurlencode( $page_slug ) );
?>
@@ -80,23 +84,13 @@ $base_url = admin_url( 'admin.php?page=' . rawurlencode( $page_slug ) );
<?php endif; ?>
<?php
$niche = (string) get_option( 'prautoblogger_niche_description', '' );
$niche_preview = '' !== $niche ? mb_strimwidth( $niche, 0, 80, '…' ) : '';
// ── Global Content Context block (editable — M2) ─────────────────────────
$context = 'global';
$section_title = __( 'Global Content Context', 'prautoblogger' );
$step_id = 'global';
$fields = $global_fields;
include PRAUTOBLOGGER_PLUGIN_DIR . 'templates/admin/pipeline-settings-step-options.php';
?>
<div class="pab-global-context-note">
<span class="dashicons dashicons-info-outline"></span>
<?php if ( '' !== $niche_preview ) : ?>
<?php
printf(
/* translators: %s = truncated niche description */
esc_html__( 'Niche context (used by all stages): "%s"', 'prautoblogger' ),
esc_html( $niche_preview )
);
?>
<?php else : ?>
<?php esc_html_e( 'Niche description not set — edit in Settings → Content.', 'prautoblogger' ); ?>
<?php endif; ?>
</div>
<div class="pab-pipeline-layout">
@@ -122,6 +116,17 @@ $base_url = admin_url( 'admin.php?page=' . rawurlencode( $page_slug ) );
<?php endif; ?>
</div>
<?php
// ── Step option fields (M2) ───────────────────────────────────────
if ( null !== $step_context && ! empty( $step_fields ) ) :
$context = $step_context;
$section_title = __( 'Step Settings', 'prautoblogger' );
$step_id = $active_step['id'];
$fields = $step_fields;
include PRAUTOBLOGGER_PLUGIN_DIR . 'templates/admin/pipeline-settings-step-options.php';
endif;
?>
<?php if ( ! empty( $step_data['model_option'] ) ) : ?>
<div class="pab-section">
<h3 class="pab-section-title"><?php esc_html_e( 'Model', 'prautoblogger' ); ?></h3>

View File

@@ -0,0 +1,127 @@
<?php
/**
* Partial: Pipeline Settings — editable step-option fields.
*
* Renders a save form containing every option field for the current step
* context (research / analysis / writer / editorial) or the global context.
*
* Variables expected in scope (provided by pipeline-settings-page.php):
* string $nonce_action — nonce action string.
* string $nonce_field — nonce field name.
* string $step_id — active step id (for form action URL, e.g. 'writer').
* string $base_url — admin.php?page=prautoblogger-pipeline base URL.
* string $context — step context key passed as step_context POST field.
* array $fields — array of field defs with 'current' key (from renderer).
* string $section_title — h3 title for this options block.
*
* @see admin/class-pipeline-settings-option-fields.php — Field definitions + sanitizer.
* @see admin/class-pipeline-settings-renderer.php — Provides $fields via build_option_field_values().
* @see templates/admin/pipeline-settings-page.php — Includes this partial.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<div class="pab-section">
<h3 class="pab-section-title"><?php echo esc_html( $section_title ); ?></h3>
<form method="post"
action="<?php echo esc_url( add_query_arg( 'step', $step_id, $base_url ) ); ?>"
class="pab-step-options-form">
<?php wp_nonce_field( $nonce_action, $nonce_field ); ?>
<input type="hidden" name="pipeline_action" value="save_step_settings" />
<input type="hidden" name="step_context" value="<?php echo esc_attr( $context ); ?>" />
<table class="form-table pab-options-table">
<tbody>
<?php foreach ( $fields as $field ) : ?>
<?php
$fid = (string) $field['id'];
$ftype = (string) ( $field['type'] ?? 'textarea' );
$current = $field['current'] ?? ( $field['default'] ?? '' );
?>
<tr>
<th scope="row">
<label for="pab-opt-<?php echo esc_attr( $fid ); ?>">
<?php echo esc_html( $field['label'] ?? $fid ); ?>
</label>
</th>
<td>
<?php if ( 'textarea' === $ftype ) : ?>
<textarea id="pab-opt-<?php echo esc_attr( $fid ); ?>"
name="<?php echo esc_attr( $fid ); ?>"
rows="5"
class="large-text code"><?php echo esc_textarea( (string) $current ); ?></textarea>
<?php elseif ( 'select' === $ftype ) : ?>
<select id="pab-opt-<?php echo esc_attr( $fid ); ?>"
name="<?php echo esc_attr( $fid ); ?>">
<?php foreach ( (array) ( $field['options'] ?? array() ) as $val => $label ) : ?>
<option value="<?php echo esc_attr( (string) $val ); ?>"
<?php selected( (string) $current, (string) $val ); ?>>
<?php echo esc_html( (string) $label ); ?>
</option>
<?php endforeach; ?>
</select>
<?php elseif ( 'number' === $ftype ) : ?>
<input type="number"
id="pab-opt-<?php echo esc_attr( $fid ); ?>"
name="<?php echo esc_attr( $fid ); ?>"
value="<?php echo esc_attr( (string) $current ); ?>"
class="small-text"
<?php echo isset( $field['min'] ) ? 'min="' . esc_attr( (string) $field['min'] ) . '"' : ''; ?>
<?php echo isset( $field['max'] ) ? 'max="' . esc_attr( (string) $field['max'] ) . '"' : ''; ?>
/>
<?php elseif ( 'toggle' === $ftype ) : ?>
<label class="pab-toggle-wrap">
<input type="checkbox"
id="pab-opt-<?php echo esc_attr( $fid ); ?>"
name="<?php echo esc_attr( $fid ); ?>"
value="1"
<?php checked( '1', (string) $current ); ?> />
<span class="pab-toggle-label">
<?php esc_html_e( 'Enabled', 'prautoblogger' ); ?>
</span>
</label>
<?php elseif ( 'checkboxes' === $ftype ) : ?>
<?php
// current is stored as JSON array string.
$checked_vals = array();
if ( is_string( $current ) && '' !== $current ) {
$decoded = json_decode( $current, true );
if ( is_array( $decoded ) ) {
$checked_vals = $decoded;
}
}
?>
<fieldset>
<?php foreach ( (array) ( $field['choices'] ?? array() ) as $val => $label ) : ?>
<label>
<input type="checkbox"
name="<?php echo esc_attr( $fid ); ?>[]"
value="<?php echo esc_attr( (string) $val ); ?>"
<?php checked( in_array( (string) $val, array_map( 'strval', $checked_vals ), true ) ); ?> />
<?php echo esc_html( (string) $label ); ?>
</label><br />
<?php endforeach; ?>
</fieldset>
<?php endif; ?>
<?php if ( ! empty( $field['description'] ) ) : ?>
<p class="description"><?php echo esc_html( $field['description'] ); ?></p>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<p class="submit">
<button type="submit" class="ab-btn ab-btn-secondary ab-btn-sm">
<?php esc_html_e( 'Save Settings', 'prautoblogger' ); ?>
</button>
</p>
</form>
</div>