' . esc_html__('New', 'ai-content-generation') . ''; add_submenu_page( self::PARENT_SLUG, __('Automated Posts', 'ai-content-generation'), $menu_title, 'edit_posts', self::PAGE_SLUG, [$this, 'render'], 30 // order: after Bulk Posts (25), before History (35) ); add_action('admin_head', static function () { echo ''; }); } public function render(): void { // JS-free skeleton paints instantly; React's createRoot() clears it on mount. See Skeleton. // Title mirrors the app's own in-page heading so the header text doesn't change on hand-off. echo '

'; echo Skeleton::panel(__('Automated Posts', 'ai-content-generation'), [], 4); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped inside Skeleton echo '
'; } public function enqueue(string $hook): void { if (substr($hook, -strlen(self::PAGE_SLUG)) !== self::PAGE_SLUG) { return; } $asset_file = WPWAND_NEW_DIR . 'build/automation.asset.php'; if (!is_readable($asset_file)) { return; } $asset = require $asset_file; wp_enqueue_script(self::HANDLE, WPWAND_NEW_URL . 'build/automation.js', $asset['dependencies'], $asset['version'], true); // No webfont request here on purpose: hitting fonts.googleapis.com from wp-admin is a // third-party round trip nobody asked for and a wordpress.org review flag. Every rule in the // stylesheet reads --wpwand-font, which names Inter first and then the platform UI stack, so // a machine without Inter renders one consistent typeface rather than two. if (is_readable(WPWAND_NEW_DIR . 'build/style-automation.css')) { wp_enqueue_style(self::HANDLE, WPWAND_NEW_URL . 'build/style-automation.css', [], (string) filemtime(WPWAND_NEW_DIR . 'build/style-automation.css')); } ScriptConfig::merge(self::HANDLE, ScriptConfig::base() + [ 'brand' => \WPWand\Data\Brand::resolve()['color'], 'isPro' => \WPWand\Generation\UsageLimits::is_pro(), // The server clamps a saved schedule to this (Schedules::normalize). Ship it so the form // cannot offer a number the save will silently reduce. 'automationPerRun' => \WPWand\Automation\Schedules::max_count(), ]); if (function_exists('wp_set_script_translations')) { wp_set_script_translations(self::HANDLE, 'ai-content-generation'); } } }