Changeset 3469054
- Timestamp:
- 02/25/2026 05:30:42 AM (5 weeks ago)
- Location:
- pap-afiliados-pro/trunk
- Files:
-
- 11 edited
-
assets/css/papafpro-template-builder.css (modified) (1 diff)
-
assets/js/papafpro-settings.js (modified) (1 diff)
-
assets/js/papafpro-template-builder.js (modified) (1 diff)
-
includes/class-papafpro-help-page.php (modified) (5 diffs)
-
includes/class-papafpro-shortcodes.php (modified) (11 diffs)
-
languages/pap-afiliados-pro-pt_BR.mo (modified) (previous)
-
languages/pap-afiliados-pro-pt_BR.po (modified) (1 diff)
-
languages/pap-afiliados-pro.pot (modified) (1 diff)
-
pap-afiliados-pro.php (modified) (2 diffs)
-
readme.txt (modified) (3 diffs)
-
views/papafpro-template-builder.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
pap-afiliados-pro/trunk/assets/css/papafpro-template-builder.css
r3468187 r3469054 229 229 } 230 230 231 /* ============================================= 232 Preset List Table 233 ============================================= */ 234 231 235 .papafpro-preset-list { 232 list-style: none; 233 padding: 0; 234 margin: 0; 235 } 236 237 .papafpro-preset-item { 238 display: flex; 239 justify-content: space-between; 240 align-items: center; 236 border-collapse: collapse; 237 width: 100%; 238 margin-top: 8px; 239 } 240 241 /* ----- Header ----- */ 242 243 .papafpro-preset-list thead th { 244 background-color: #f1f1f1; 245 border-bottom: 2px solid #ddd; 246 font-weight: 600; 247 font-size: 12px; 248 color: #555; 249 text-transform: uppercase; 250 letter-spacing: 0.5px; 251 padding: 8px 12px; 252 text-align: left; 253 } 254 255 .papafpro-preset-list thead th.papafpro-col-check { 256 width: 30px; 257 padding: 8px; 258 text-align: center; 259 } 260 261 .papafpro-preset-list thead th.papafpro-col-id { 262 width: 60px; 263 text-align: center; 264 } 265 266 .papafpro-preset-list thead th.papafpro-col-actions { 267 width: 220px; 268 text-align: center; 269 } 270 271 /* ----- Body rows ----- */ 272 273 .papafpro-preset-list tbody td { 241 274 padding: 8px 12px; 242 275 border-bottom: 1px solid #eee; 243 } 244 245 .papafpro-preset-item:hover { 246 background: #f5f5f5; 247 } 248 249 .papafpro-preset-item label { 250 display: flex; 251 align-items: center; 252 gap: 8px; 253 cursor: pointer; 254 } 276 vertical-align: middle; 277 } 278 279 .papafpro-preset-list tbody td.papafpro-col-check { 280 width: 30px; 281 padding: 8px; 282 text-align: center; 283 } 284 285 .papafpro-preset-list tbody td.papafpro-col-id { 286 text-align: center; 287 } 288 289 .papafpro-preset-list tbody td.papafpro-col-actions { 290 text-align: center; 291 } 292 293 /* ----- Zebra striping ----- */ 294 295 .papafpro-preset-list tbody tr:nth-child(even) { 296 background-color: #f9f9f9; 297 } 298 299 /* ----- Hover ----- */ 300 301 .papafpro-preset-list tbody tr:hover { 302 background-color: #e8f4fd; 303 } 304 305 /* ----- Name column ----- */ 306 307 .papafpro-preset-list td.papafpro-col-name label { 308 display: block; 309 cursor: default; 310 overflow: hidden; 311 text-overflow: ellipsis; 312 white-space: nowrap; 313 max-width: 400px; 314 } 315 316 /* ----- ID badge ----- */ 317 318 .papafpro-preset-id { 319 display: inline-block; 320 font-size: 11px; 321 color: #888; 322 background: #f0f0f0; 323 padding: 2px 6px; 324 border-radius: 3px; 325 font-family: monospace; 326 white-space: nowrap; 327 cursor: default; 328 } 329 330 /* ----- Action buttons ----- */ 255 331 256 332 .papafpro-preset-actions { 257 333 display: flex; 258 gap: 8px; 334 gap: 6px; 335 justify-content: center; 259 336 } 260 337 -
pap-afiliados-pro/trunk/assets/js/papafpro-settings.js
r3468187 r3469054 35 35 action: 'papafpro_save_settings', 36 36 nonce: papafproTemplateBuilder.nonce, 37 keep_data_on_uninstall: $keepData.is( ':checked' ) ? 1 : 0 37 settings: { 38 keep_data_on_uninstall: $keepData.is( ':checked' ) ? 1 : 0 39 } 38 40 }, 39 41 success: function( response ) { -
pap-afiliados-pro/trunk/assets/js/papafpro-template-builder.js
r3468187 r3469054 475 475 */ 476 476 function renderPresetList( presets ) { 477 var $list = $( '.papafpro-preset-list' ); 478 $list.empty(); 479 477 var $table = $( '.papafpro-preset-list' ); 478 var $thead = $table.find( 'thead' ); 479 var $tbody = $table.find( 'tbody' ); 480 481 $thead.empty(); 482 $tbody.empty(); 483 484 // Empty state. 480 485 if ( ! presets.length ) { 481 $list.append( '<li class="papafpro-preset-item"><em>Nenhum preset salvo.</em></li>' ); 486 $thead.append( 487 '<tr><th colspan="4"><em>Nenhum preset salvo.</em></th></tr>' 488 ); 482 489 return; 483 490 } 484 491 492 // Header row. 493 var headerHtml = '<tr class="papafpro-preset-header">' + 494 '<th class="papafpro-col-check"> </th>' + 495 '<th class="papafpro-col-name">Name</th>' + 496 '<th class="papafpro-col-id">ID</th>' + 497 '<th class="papafpro-col-actions">Actions</th>' + 498 '</tr>'; 499 $thead.append( headerHtml ); 500 501 // Data rows. 485 502 $.each( presets, function( i, preset ) { 486 var $item = $( '<li>' ).addClass( 'papafpro-preset-item' ); 487 var $label = $( '<label>' ) 488 .append( $( '<input>' ).attr({ type: 'checkbox', value: preset.id }).addClass( 'papafpro-preset-checkbox' ) ) 503 var $row = $( '<tr>' ).addClass( 'papafpro-preset-item' ); 504 505 // Column 1: Checkbox. 506 var $cellCheck = $( '<td>' ).addClass( 'papafpro-col-check' ); 507 var $checkbox = $( '<input>' ) 508 .attr({ type: 'checkbox', value: preset.id }) 509 .addClass( 'papafpro-preset-checkbox' ); 510 $cellCheck.append( $checkbox ); 511 512 // Column 2: Name. 513 var $cellName = $( '<td>' ).addClass( 'papafpro-col-name' ); 514 var $nameLabel = $( '<label>' ) 489 515 .append( document.createTextNode( preset.name ) ); 490 516 $cellName.append( $nameLabel ); 517 518 // Column 3: ID badge. 519 var $cellId = $( '<td>' ).addClass( 'papafpro-col-id' ); 520 var $idBadge = $( '<span>' ) 521 .addClass( 'papafpro-preset-id' ) 522 .attr( 'title', 'preset_id="' + preset.id + '"' ) 523 .text( '#' + preset.id ); 524 $cellId.append( $idBadge ); 525 526 // Column 4: Actions. 527 var $cellActions = $( '<td>' ).addClass( 'papafpro-col-actions' ); 491 528 var $actions = $( '<div>' ).addClass( 'papafpro-preset-actions' ) 492 529 .append( 493 $( '<button>' ) 494 .addClass( 'button papafpro-preset-load' ) 495 .attr( 'data-id', preset.id ) 496 .text( 'Carregar' ) 530 $( '<button>' ).addClass( 'button papafpro-preset-load' ) 531 .attr( 'data-id', preset.id ).text( 'Carregar' ) 497 532 ) 498 533 .append( 499 $( '<button>' ) 500 .addClass( 'button papafpro-preset-preview' ) 501 .attr( 'data-id', preset.id ) 502 .text( 'Preview' ) 534 $( '<button>' ).addClass( 'button papafpro-preset-preview' ) 535 .attr( 'data-id', preset.id ).text( 'Preview' ) 503 536 ) 504 537 .append( 505 $( '<button>' ) 506 .addClass( 'button papafpro-preset-delete' ) 507 .attr( 'data-id', preset.id ) 508 .text( 'Excluir' ) 538 $( '<button>' ).addClass( 'button papafpro-preset-delete' ) 539 .attr( 'data-id', preset.id ).text( 'Excluir' ) 509 540 ); 510 511 $item.append( $label ).append( $actions ); 512 $list.append( $item ); 541 $cellActions.append( $actions ); 542 543 $row.append( $cellCheck ).append( $cellName ) 544 .append( $cellId ).append( $cellActions ); 545 $tbody.append( $row ); 513 546 }); 514 547 } -
pap-afiliados-pro/trunk/includes/class-papafpro-help-page.php
r3468187 r3469054 188 188 'type' => 'preset', 189 189 'required' => false, 190 'description' => __( ' Appearance preset ID', 'pap-afiliados-pro' ),190 'description' => __( 'Preset ID or name', 'pap-afiliados-pro' ), 191 191 ), 192 192 ), … … 214 214 'type' => 'preset', 215 215 'required' => false, 216 'description' => __( 'Preset ID ', 'pap-afiliados-pro' ),216 'description' => __( 'Preset ID or name', 'pap-afiliados-pro' ), 217 217 ), 218 218 ), … … 246 246 'type' => 'preset', 247 247 'required' => false, 248 'description' => __( 'Preset ID ', 'pap-afiliados-pro' ),248 'description' => __( 'Preset ID or name', 'pap-afiliados-pro' ), 249 249 ), 250 250 ), … … 272 272 'type' => 'preset', 273 273 'required' => false, 274 'description' => __( 'Preset ID ', 'pap-afiliados-pro' ),274 'description' => __( 'Preset ID or name', 'pap-afiliados-pro' ), 275 275 ), 276 276 ), … … 286 286 'type' => 'preset', 287 287 'required' => true, 288 'description' => __( 'Preset ID ', 'pap-afiliados-pro' ),288 'description' => __( 'Preset ID or name', 'pap-afiliados-pro' ), 289 289 ), 290 290 array( -
pap-afiliados-pro/trunk/includes/class-papafpro-shortcodes.php
r3468187 r3469054 159 159 160 160 /** 161 * Load preset settings by ID , falling back to global settings.161 * Load preset settings by ID or name, falling back to global settings. 162 162 * 163 163 * @since 2.0.0 164 164 * @access private 165 * @param int $preset_id Preset ID(0 = global settings).165 * @param mixed $preset_id Preset ID or name (0 = global settings). 166 166 * @return array Settings array merged with defaults. 167 167 */ 168 168 private function get_preset_settings( $preset_id ) { 169 $preset_id = absint( $preset_id );169 $preset_id = $this->resolve_preset_id( $preset_id ); 170 170 $defaults = get_option( 'papafpro_settings', array() ); 171 171 … … 209 209 210 210 /** 211 * Resolve preset identifier to numeric ID. 212 * 213 * Accepts a numeric ID (passthrough) or a preset name (database lookup). 214 * Used by get_preset_settings() to support both preset_id="3" and 215 * preset_id="Tema Azul" in shortcodes. 216 * 217 * @since 2.0.2 218 * @access private 219 * @param mixed $preset_id Numeric ID or preset name string. 220 * @return int Resolved preset ID. Returns 0 if not found or invalid. 221 */ 222 private function resolve_preset_id( $preset_id ) { 223 // Numeric ID — passthrough. 224 if ( is_numeric( $preset_id ) ) { 225 return absint( $preset_id ); 226 } 227 228 // Empty or non-string — return 0 (global settings). 229 if ( empty( $preset_id ) || ! is_string( $preset_id ) ) { 230 return 0; 231 } 232 233 // Name lookup with cache. 234 $sanitized_name = sanitize_text_field( $preset_id ); 235 $cache_key = 'papafpro_preset_name_' . md5( $sanitized_name ); 236 $cached = wp_cache_get( $cache_key, 'papafpro' ); 237 238 if ( false !== $cached ) { 239 return absint( $cached ); 240 } 241 242 global $wpdb; 243 $table_name = $wpdb->prefix . 'papafpro_presets'; 244 245 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Custom table, no WP API available. 246 $result = $wpdb->get_var( 247 $wpdb->prepare( 248 'SELECT id FROM %i WHERE name = %s LIMIT 1', 249 $table_name, 250 $sanitized_name 251 ) 252 ); 253 254 $resolved_id = $result ? absint( $result ) : 0; 255 wp_cache_set( $cache_key, $resolved_id, 'papafpro' ); 256 257 return $resolved_id; 258 } 259 260 /** 211 261 * Render single product shortcode. 212 262 * … … 227 277 ); 228 278 229 $id = absint( $atts['id'] ); 230 $preset_id = absint( $atts['preset_id'] ); 279 $id = absint( $atts['id'] ); 231 280 232 281 if ( 0 === $id ) { … … 239 288 } 240 289 241 $settings = $this->get_preset_settings( $ preset_id);290 $settings = $this->get_preset_settings( $atts['preset_id'] ); 242 291 243 292 $this->enqueue_frontend_assets(); … … 283 332 $limite = min( max( absint( $atts['limite'] ), 1 ), 100 ); 284 333 $colunas = absint( $atts['colunas'] ); 285 $preset_id = absint( $atts['preset_id'] );286 334 287 335 // Whitelist tag_relation. … … 290 338 } 291 339 292 $settings = $this->get_preset_settings( $ preset_id);340 $settings = $this->get_preset_settings( $atts['preset_id'] ); 293 341 294 342 // Resolve columns: shortcode attr > global setting > fallback 3. … … 375 423 $ordem = strtoupper( sanitize_text_field( wp_unslash( $atts['ordem'] ) ) ); 376 424 $colunas = absint( $atts['colunas'] ); 377 $preset_id = absint( $atts['preset_id'] );378 425 379 426 // Categoria is required. … … 395 442 } 396 443 397 $settings = $this->get_preset_settings( $ preset_id);444 $settings = $this->get_preset_settings( $atts['preset_id'] ); 398 445 399 446 // Resolve columns: shortcode attr > global setting > fallback 3. … … 461 508 $limite = min( max( absint( $atts['limite'] ), 1 ), 100 ); 462 509 $colunas = absint( $atts['colunas'] ); 463 $preset_id = absint( $atts['preset_id'] );464 510 465 511 // Whitelist tag_relation. … … 468 514 } 469 515 470 $settings = $this->get_preset_settings( $ preset_id);516 $settings = $this->get_preset_settings( $atts['preset_id'] ); 471 517 472 518 // Resolve columns: shortcode attr > global setting > fallback 3. … … 535 581 536 582 // Sanitize. 537 $preset_id = absint( $atts['id'] );583 $preset_id = $this->resolve_preset_id( $atts['id'] ); 538 584 $ids_raw = sanitize_text_field( wp_unslash( $atts['ids'] ) ); 539 585 $tag = sanitize_text_field( wp_unslash( $atts['tag'] ) ); -
pap-afiliados-pro/trunk/languages/pap-afiliados-pro-pt_BR.po
r3468187 r3469054 814 814 815 815 #: includes/class-papafpro-help-pagephp:190 816 msgid "Appearance preset ID"817 msgstr "ID do preset de aparência"818 819 #: includes/class-papafpro-help-pagephp:197820 msgid "Multiple Products"821 msgstr "Múltiplos Produtos"822 823 #: includes/class-papafpro-help-pagephp:198824 msgid "Displays multiple product cards in a grid."825 msgstr "Exibe múltiplos cards de produto em grid."826 827 #: includes/class-papafpro-help-pagephp:204828 msgid "Comma-separated IDs"829 msgstr "IDs separados por vírgula"830 831 #: includes/class-papafpro-help-pagephp:210832 msgid "Number of columns (1-6)"833 msgstr "Número de colunas (1-6)"834 835 816 #: includes/class-papafpro-help-pagephp:216 836 817 #: includes/class-papafpro-help-pagephp:248 837 818 #: includes/class-papafpro-help-pagephp:274 838 819 #: includes/class-papafpro-help-pagephp:288 839 msgid "Preset ID" 840 msgstr "ID do preset" 820 msgid "Preset ID or name" 821 msgstr "ID ou nome do preset" 822 823 #: includes/class-papafpro-help-pagephp:197 824 msgid "Multiple Products" 825 msgstr "Múltiplos Produtos" 826 827 #: includes/class-papafpro-help-pagephp:198 828 msgid "Displays multiple product cards in a grid." 829 msgstr "Exibe múltiplos cards de produto em grid." 830 831 #: includes/class-papafpro-help-pagephp:204 832 msgid "Comma-separated IDs" 833 msgstr "IDs separados por vírgula" 834 835 #: includes/class-papafpro-help-pagephp:210 836 msgid "Number of columns (1-6)" 837 msgstr "Número de colunas (1-6)" 841 838 842 839 #: includes/class-papafpro-help-pagephp:223 -
pap-afiliados-pro/trunk/languages/pap-afiliados-pro.pot
r3468187 r3469054 810 810 811 811 #: includes/class-papafpro-help-pagephp:190 812 msgid "Appearance preset ID"813 msgstr ""814 815 #: includes/class-papafpro-help-pagephp:197816 msgid "Multiple Products"817 msgstr ""818 819 #: includes/class-papafpro-help-pagephp:198820 msgid "Displays multiple product cards in a grid."821 msgstr ""822 823 #: includes/class-papafpro-help-pagephp:204824 msgid "Comma-separated IDs"825 msgstr ""826 827 #: includes/class-papafpro-help-pagephp:210828 msgid "Number of columns (1-6)"829 msgstr ""830 831 812 #: includes/class-papafpro-help-pagephp:216 832 813 #: includes/class-papafpro-help-pagephp:248 833 814 #: includes/class-papafpro-help-pagephp:274 834 815 #: includes/class-papafpro-help-pagephp:288 835 msgid "Preset ID" 816 msgid "Preset ID or name" 817 msgstr "" 818 819 #: includes/class-papafpro-help-pagephp:197 820 msgid "Multiple Products" 821 msgstr "" 822 823 #: includes/class-papafpro-help-pagephp:198 824 msgid "Displays multiple product cards in a grid." 825 msgstr "" 826 827 #: includes/class-papafpro-help-pagephp:204 828 msgid "Comma-separated IDs" 829 msgstr "" 830 831 #: includes/class-papafpro-help-pagephp:210 832 msgid "Number of columns (1-6)" 836 833 msgstr "" 837 834 -
pap-afiliados-pro/trunk/pap-afiliados-pro.php
r3468187 r3469054 4 4 * Plugin URI: https://pap-afiliados-pro.com.br 5 5 * Description: Professional affiliate link management for Brazilian marketplaces (Amazon, Mercado Livre, Shopee, AliExpress, and others). 6 * Version: 2.0. 16 * Version: 2.0.2 7 7 * Requires at least: 6.2 8 8 * Requires PHP: 7.4 … … 24 24 * Constantes do plugin. 25 25 */ 26 define( 'PAPAFPRO_VERSION', '2.0. 1' );26 define( 'PAPAFPRO_VERSION', '2.0.2' ); 27 27 define( 'PAPAFPRO_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 28 28 define( 'PAPAFPRO_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); -
pap-afiliados-pro/trunk/readme.txt
r3468187 r3469054 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 2.0. 17 Stable tag: 2.0.2 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 131 131 == Changelog == 132 132 133 = 2.0.2 = 134 * Added: Preset ID column in Template Builder preset list 135 * Added: Shortcodes now accept preset name in addition to numeric ID (e.g., preset_id="My Theme") 136 * Improved: Preset list migrated to native table layout for better alignment 137 * Improved: Zebra striping in preset list for better readability 138 * Fixed: Settings page save not working correctly 139 133 140 = 2.0.1 = 134 141 * Fixed: Preset system now correctly applies individual visual configurations per shortcode … … 164 171 == Upgrade Notice == 165 172 173 = 2.0.2 = 174 Preset UX improvements: ID column, name-based lookup in shortcodes, native table layout. 175 166 176 = 2.0.1 = 167 177 Bug fixes for preset system, shortcode generator, and click tracking. Block API updated for WordPress 7.0 compatibility. -
pap-afiliados-pro/trunk/views/papafpro-template-builder.php
r3468187 r3469054 368 368 </div> 369 369 <h3><?php esc_html_e( 'Saved Presets', 'pap-afiliados-pro' ); ?></h3> 370 <ul class="papafpro-preset-list"> 371 <!-- Carregado via JS --> 372 </ul> 370 <table class="papafpro-preset-list widefat"> 371 <thead></thead> 372 <tbody></tbody> 373 </table> 373 374 <div class="papafpro-builder-actions" style="margin-top: 12px;"> 374 375 <button class="button" id="papafpro-bulk-duplicate-presets">
Note: See TracChangeset
for help on using the changeset viewer.