Cum să adaugi un câmp personalizat în editarea rapidă

27 apr. 2020, 03:06:45
Vizualizări: 16.9K
Voturi: 4

Cum pot adăuga o coloană nouă în editarea rapidă și să pun un câmp personalizat în ea? Am citit această întrebare dar unul dintre linkuri duce la o eroare 404. Am nevoie de o coloană nouă pentru meta cheia mea personalizată "summary" și pentru tipurile de postări "post" și "episode".

0
Toate răspunsurile la întrebare 3
12
14

Există câțiva pași pentru a crea o casetă de editare rapidă personalizată și o coloană personalizată

  1. creați o cheie meta personalizată (se presupune că aveți deja una)
  2. adăugați titlul și datele coloanei personalizate în administrare (se presupune că doriți să afișați cheia meta personalizată în coloană, dacă nu, puteți modifica puțin logica pentru a obține același efect deoarece principiul este același)
  3. adăugați caseta de editare rapidă personalizată
  4. adăugați logica de salvare
  5. încărcați scriptul pentru a modifica funcția originală inline-edit-post pentru a suporta valoarea meta personalizată
  6. pregătiți fișierul de script

Acest exemplu va adăuga o casetă de introducere rapidă în tipul de postare Pagină. Următorul cod a fost testat și funcționează prin plasarea în functions.php.

1. creați o cheie meta personalizată (se presupune că aveți deja una)

Am pregătit o cheie meta personalizată remark pentru tipul de postare page

2. adăugați titlul și datele coloanei personalizate în administrare

pentru tipul de postare personalizat, puteți utiliza

Adăugați titlul coloanei

Adăugați conținutul coloanei

Următorul este un exemplu pentru tipul de postare Pagină, precum și pentru tipul de postare personalizat + implicit Post ca exemplu pentru configurarea mai multor tipuri de postări.

// adăugați titlul coloanei personalizate pentru valoarea meta personalizată
add_filter('manage_edit-page_columns', 'ws365150_add_custom_columns_title' );
function ws365150_add_custom_columns_title( $columns ) {
    $columns['page_remark'] = 'Remarcă'; // puteți utiliza __() mai târziu pentru suport de traducere
    
    return $columns;
}
    
// adăugați datele coloanei personalizate cu valoarea meta personalizată
add_action('manage_pages_custom_column', 'ws365150_add_custom_column_data', 10, 2 );
function ws365150_add_custom_column_data( $column_name, $post_id ) {
    switch ( $column_name ) {
        case 'page_remark':
            echo get_post_meta( $post_id, 'remark', true );
            break;
        
        default:
            break;
    }
}

Următorul este un exemplu pentru tipul de postare personalizat episode + implicit Post cu cheia meta summary

// adăugați titlul coloanei personalizate pentru valoarea meta personalizată
// 'manage_pages_columns' sau 'manage_edit-post_columns' ambele funcționează
add_filter('manage_posts_columns', 'ws365150_add_custom_columns_title_pt', 10, 2 );
function ws365150_add_custom_columns_title_pt( $columns, $post_type ) {
    switch ( $post_type ) {
        case 'post':
        case 'episode':
            $columns['ws365150_summary'] = 'Rezumat'; // puteți utiliza __() mai târziu pentru suport de traducere
            break;
        
        default:
            
            break;
    }
    
    return $columns;
}
    
// adăugați datele coloanei personalizate cu valoarea meta personalizată pentru tipuri de postări personalizate
add_action('manage_posts_custom_column', 'ws365150_add_custom_column_data_pt', 10, 2 );
function ws365150_add_custom_column_data_pt( $column_name, $post_id ) {
    switch ( $column_name ) {
        case 'ws365150_summary': // specificat pentru această coloană asignată în titlul coloanei
            echo get_post_meta( $post_id, 'summary', true );
            break;
        
        default:
            break;
    }
}

3. adăugați caseta de editare rapidă personalizată

// pentru pagină
add_action( 'quick_edit_custom_box', 'ws365150_custom_edit_box', 10, 3 );
function ws365150_custom_edit_box( $column_name, $post_type, $taxonomy ) {
    global $post;

    switch ( $post_type ) {
        case 'page':

        if( $column_name === 'page_remark' ): // același titlu de coloană ca cel definit în pasul anterior
        ?>
                <?php // echo get_post_meta( $post->ID, 'remark', true ); ?>
            <fieldset class="inline-edit-col-right" id="#edit-">
                <div class="inline-edit-col">
                    <label>
                        <span class="title">Remarcă</span>
                        <span class="input-text-wrap"><input type="text" name="remark" class="inline-edit-menu-order-input" value=""></span>
                    </label>
                </div>
            </fieldset>
            <?php
        endif;
            // echo 'custom page field';
            break;
        
        default:
            break;
    }
}

// pentru Post + tip de postare personalizat
add_action( 'quick_edit_custom_box', 'ws365150_custom_edit_box_pt', 10, 3 );
function ws365150_custom_edit_box_pt( $column_name, $post_type, $taxonomy ) {
    global $post;

    switch ( $post_type ) {
        case 'post':
        case 'episode':

        if( $column_name === 'ws365150_summary' ): // același titlu de coloană ca cel definit în pasul anterior
        ?>
                <?php // echo get_post_meta( $post->ID, 'remark', true ); ?>
            <fieldset class="inline-edit-col-right" id="#edit-">
                <div class="inline-edit-col">
                    <label>
                        <span class="title">Rezumat</span>
                        <span class="input-text-wrap"><input type="text" name="summary" class="inline-edit-menu-order-input" value=""></span>
                    </label>
                </div>
            </fieldset>
            <?php
        endif;
            // echo 'custom page field';
            break;
        
        default:
            break;
    }
}

4. adăugați logica de salvare

add_action( 'save_post', 'ws365150_update_custom_quickedit_box' );
function ws365150_update_custom_quickedit_box() {
    // orice logică de verificare aici, omițând și păstrând simplu pentru scopul ilustrării simple (nonce, existența $_POST['remark'], salvare ajax și așa mai departe
    
    // remarcă în Pagină
    if( isset( $_POST ) && isset( $_POST['remark'] ) ) { // unde remark este definit în <input name="remark">
        update_post_meta($_POST['post_ID'], 'remark', $_POST['remark']);
    }

    // rezumat în Post, tip de postare personalizat
    if( isset( $_POST ) && isset( $_POST['summary'] ) ) { // unde summary este definit în <input name="summary">
        update_post_meta($_POST['post_ID'], 'summary', $_POST['summary']);
    }
    
    // pentru depanare în inspector, nu este necesar, activarea acestuia va întrerupe salvarea dar puteți vedea răspunsul ajax
    // wp_send_json_success( array(
    //  'message' => 'Save test!',
    //  'post_data' => $_POST,
    // ) );
    return; // finalizează apelul funcției
}

5. încărcați scriptul pentru a modifica funcția originală inline-edit-post

add_action( 'admin_enqueue_scripts', function( $page ) {

    // adăugați logica de verificare a paginii, aceasta este una simplă, puteți testa tipul de postare și așa mai departe...
    if ( 'edit.php' != $page ) {
        return;
    }
    
    wp_enqueue_script( 'custom-quickedit-box', get_stylesheet_directory_uri() . '/ws365150_custom_quickedit_box.js', array( 'jquery', 'inline-edit-post' ) );
});

6. pregătiți fișierul de script (ws365150_custom_quickedit_box.js, când testați codul de mai sus, puneți-l în folderul temei)

( function( $, wp ) {
    // clonare din funcția originală din inline-post-edit.js pentru suprascriere
    // de fapt nu este necesar să creați un alias de obiect, totuși, crearea unui alias poate fi o notă și un marcaj de suprascriere fără a uita pentru întreținerea ulterioară
    window.customInlineEditPost = window.inlineEditPost;

    // suprascriere funcție: adăugați valoare meta personalizată, baza este copiată din sursă
    customInlineEditPost.edit = function(id) {
            // console.log( 'custom edit' );
            var t = this, fields, editRow, rowData, status, pageOpt, pageLevel, nextPage, pageLoop = true, nextLevel, f, val, pw;
            t.revert();

            if ( typeof(id) === 'object' ) {
                id = t.getId(id);
            }

            fields = ['post_title', 'post_name', 'post_author', '_status', 'jj', 'mm', 'aa', 'hh', 'mn', 'ss', 'post_password', 'post_format', 'menu_order', 'page_template'];
            if ( t.type === 'page' ) {
                fields.push('post_parent');
            }

            // Adăugați noul rând de editare cu un rând gol suplimentar dedesubt pentru a menține dungile zebra.
            editRow = $('#inline-edit').clone(true);
            $( 'td', editRow ).attr( 'colspan', $( 'th:visible, td:visible', '.widefat:first thead' ).length );

            $(t.what+id).removeClass('is-expanded').hide().after(editRow).after('<tr class="hidden"></tr>');

            // Populați câmpurile în fereastra de editare rapidă.
            rowData = $('#inline_'+id);
            if ( !$(':input[name="post_author"] option[value="' + $('.post_author', rowData).text() + '"]', editRow).val() ) {

                // Autorul postării nu mai are capacități de editare, așa că trebuie să îi adăugăm în lista de autori.
                $(':input[name="post_author"]', editRow).prepend('<option value="' + $('.post_author', rowData).text() + '">' + $('#' + t.type + '-' + id + ' .author').text() + '</option>');
            }
            if ( $( ':input[name="post_author"] option', editRow ).length === 1 ) {
                $('label.inline-edit-author', editRow).hide();
            }

            // populați valoarea meta personalizată
            if ( $( ':input[name="remark"]', editRow ).length === 1 ) {
                $( ':input[name="remark"]', editRow ).val( $('#post-' + id + ' .page_remark').text() );
            }

            if ( $( ':input[name="summary"]', editRow ).length === 1 ) {
                $( ':input[name="summary"]', editRow ).val( $('#post-' + id + ' .ws365150_summary').text() );
            }

            for ( f = 0; f < fields.length; f++ ) {
                val = $('.'+fields[f], rowData);

                /**
                 * Înlocuiește imaginea pentru un Twemoji(Twitter emoji) cu textul său alternativ.
                 *
                 * @returns Text alternativ din imagine.
                 */
                val.find( 'img' ).replaceWith( function() { return this.alt; } );
                val = val.text();
                $(':input[name="' + fields[f] + '"]', editRow).val( val );
            }

            if ( $( '.comment_status', rowData ).text() === 'open' ) {
                $( 'input[name="comment_status"]', editRow ).prop( 'checked', true );
            }
            if ( $( '.ping_status', rowData ).text() === 'open' ) {
                $( 'input[name="ping_status"]', editRow ).prop( 'checked', true );
            }
            if ( $( '.sticky', rowData ).text() === 'sticky' ) {
                $( 'input[name="sticky"]', editRow ).prop( 'checked', true );
            }

            /**
             * Creează casetele de selectare pentru categorii.
             */
            $('.post_category', rowData).each(function(){
                var taxname,
                    term_ids = $(this).text();

                if ( term_ids ) {
                    taxname = $(this).attr('id').replace('_'+id, '');
                    $('ul.'+taxname+'-checklist :checkbox', editRow).val(term_ids.split(','));
                }
            });

            /**
             * Obține toate taxonomiile pentru sugestii de auto-completare în timp real când tastați numele
             * al unei etichete.
             */
            $('.tags_input', rowData).each(function(){
                var terms = $(this),
                    taxname = $(this).attr('id').replace('_' + id, ''),
                    textarea = $('textarea.tax_input_' + taxname, editRow),
                    comma = inlineEditL10n.comma;

                terms.find( 'img' ).replaceWith( function() { return this.alt; } );
                terms = terms.text();

                if ( terms ) {
                    if ( ',' !== comma ) {
                        terms = terms.replace(/,/g, comma);
                    }
                    textarea.val(terms);
                }

                textarea.wpTagsSuggest();
            });

            // Gestionează starea postării.
            status = $('._status', rowData).text();
            if ( 'future' !== status ) {
                $('select[name="_status"] option[value="future"]', editRow).remove();
            }

            pw = $( '.inline-edit-password-input' ).prop( 'disabled', false );
            if ( 'private' === status ) {
                $('input[name="keep_private"]', editRow).prop('checked', true);
                pw.val( '' ).prop( 'disabled', true );
            }

            // Eliminați pagina curentă și copiii din meniul derulant părinte.
            pageOpt = $('select[name="post_parent"] option[value="' + id + '"]', editRow);
            if ( pageOpt.length > 0 ) {
                pageLevel = pageOpt[0].className.split('-')[1];
                nextPage = pageOpt;
                while ( pageLoop ) {
                    nextPage = nextPage.next('option');
                    if ( nextPage.length === 0 ) {
                        break;
                    }

                    nextLevel = nextPage[0].className.split('-')[1];

                    if ( nextLevel <= pageLevel ) {
                        pageLoop = false;
                    } else {
                        nextPage.remove();
                        nextPage = pageOpt;
                    }
                }
                pageOpt.remove();
            }

            $(editRow).attr('id', 'edit-'+id).addClass('inline-editor').show();
            $('.ptitle', editRow).focus();

            return false;
    };
})( jQuery, window.wp );

Cele de mai sus sunt pentru editarea rapidă folosind hook-ul quick_edit_custom_box, și poate fi necesar să vă ocupați și de editarea în masă. Puteți explora mai multe citind și folosind bulk_edit_custom_box.

27 apr. 2020 10:10:30
Comentarii

Minunat! Poți edita exemplul pentru tipurile de postări post și episode și metacheia personalizată summary? Îmi pare rău, nu îmi place să mă joc cu fișierul functions.php, aș putea să stric accidental WordPress. Trebuie să știu că există o șansă de 100% ca codul să funcționeze.

Gusto Gusto
5 mai 2020 01:12:17

Am adăugat cod exemplu suplimentar pentru post, episode cu câmpul meta summary cu note adiționale despre titlul coloanei și verificarea exemplului la salvare. Poți modifica și adăuga verificări suplimentare în funcție de conținutul de care ai nevoie.

西門 正 Code Guy - JingCodeGuy 西門 正 Code Guy - JingCodeGuy
10 mai 2020 13:06:50

Stai puțin, acest cod nu funcționează și face pur și simplu pagina mea de editare "Toate paginile" să fie goală.

Gusto Gusto
12 mai 2020 23:47:14

Codul a fost actualizat, te rog să schimbi add_filter('manage_posts_columns', 'ws365150_add_custom_columns_title_pt' ); în add_filter('manage_posts_columns', 'ws365150_add_custom_columns_title_pt', 10, 2 ); Te rog să nu te grăbești să marchezi răspunsul înainte de a-l testa.

西門 正 Code Guy - JingCodeGuy 西門 正 Code Guy - JingCodeGuy
13 mai 2020 02:15:54

Hm, când am testat codul de mai sus, noul câmp de introducere summary a fost adăugat în meniul de editare rapidă al tipurilor de postări post și episode,

dar după ce am dat click pe "actualizează", parametrul summary rămâne gol.

Chiar dacă parametrul summary era deja completat (fără a folosi editarea rapidă), câmpul din editarea rapidă tot face ca parametrul să devină gol.

Gusto Gusto
14 mai 2020 00:17:21

Am creat un test case pentru a simula cazul tău și am pus un test. Am actualizat javascript-ul și filtrul save_post. Te rog să te asiguri și că javascript-ul este încărcat corect. Deoarece calea presupune că javascript-ul este plasat în folderul temei. Ar trebui să funcționeze corect acum conform simulării.

西門 正 Code Guy - JingCodeGuy 西門 正 Code Guy - JingCodeGuy
15 mai 2020 16:48:54

Am testat cu ambele tipuri de postări. Funcționează. Mulțumesc.

Gusto Gusto
15 mai 2020 18:22:17

răspuns bun, deși... este oribil în general că trebuie să fie atât de complicat

Toskan Toskan
8 ian. 2021 00:34:46

@Toskan, ar putea fi simplificat. Doar că acest răspuns este specific pentru întrebătorul cu meta key din întrebări. Personal, prefer răspunsuri generice în majoritatea cazurilor, deoarece oamenii au nevoi diferite. Dacă eliminăm exemplele, sunt câțiva pași. În rezumat, există 3 părți: (1)crearea unei meta key personalizate (poate fi făcută manual sau folosind plugin-uri), (2)adaugarea de coloane personalizate pentru afișare și (3)crearea logicii de editare/salvare pentru editarea rapidă. Deoarece editarea rapidă se bazează pe Javascript ajax pentru a oferi o experiență "instantanee", această parte pare puțin exagerată.

西門 正 Code Guy - JingCodeGuy 西門 正 Code Guy - JingCodeGuy
9 ian. 2021 11:45:07

ah da, nu am folosit partea ta de javascript. Există o soluție mult mai simplă pentru partea de js pe undeva...

Toskan Toskan
11 ian. 2021 21:39:15

uită-te la asta: https://pastebin.com/FDQPsau4

Toskan Toskan
12 ian. 2021 04:11:09

@Toskan Mulțumesc pentru share. Dar un punct de notat, javascript-ul pe care îl folosesc aici este copiat/bazat pe javascript-ul original din WordPress Core cu verificări precum tipul și altele. Fără verificări adecvate, deși ar putea fi mai simplu și să funcționeze, poate rezulta în erori în unele cazuri.

西門 正 Code Guy - JingCodeGuy 西門 正 Code Guy - JingCodeGuy
12 ian. 2021 06:50:14
Arată celelalte 7 comentarii
0

Nu am rescris întregul JS În pasul 6 am adăugat doar

(function($){
    lesson_orders={};
    if($('.post_type_page').length && $('.post_type_page').val()=='resource'){
        $('#the-list tr').each(function(){
            id=$(this).find('.check-column input').val();
            val=$(this).find('.lesson_order').text();
            lesson_orders['edit-'+id]=val;
        });
    }
    $(document).on('focus','.ptitle',function(){
        id =$(this).closest('.inline-edit-row').attr('id');
        $('#'+id+' input[name="lesson_order"]').val(lesson_orders[''+id]);
    }); 
})(jQuery);
28 ian. 2021 21:15:48
2

Iată ce am făcut în 2024 pentru a adăuga câmpul meta summary la tipurile de postări post și episode ca coloane și editabile prin editare rapidă.

Adăugare coloană în administrare

Mai întâi, definește coloanele cu filtrul manage_posts_columns.

/**
 * Adaugă coloana Summary la Postări și Episoade
 *
 * @param array $columns Un array asociativ cu antetele coloanelor.
 * @param string $post_type Slug-ul tipului de postare.
 *
 * @return array Un array posibil modificat al coloanelor.
 */
function prefix_add_summary_column($columns, $post_type)
{
    if (in_array($post_type, array('post','episode')) {
        return array_merge($columns, array(
            'summary' => __('Rezumat')
        ));
    }
    return $columns;
}
add_filter('manage_posts_columns', 'prefix_add_summary_column', 10, 2);

Alternativ, poți folosi add_filter('manage_post_posts_columns', 'prefix_add_summary_column'); și add_filter('manage_episode_posts_columns', 'prefix_add_summary_column'); pentru a ținti tipuri specifice de postări și a elimina condiția care verifică tipul de postare în interiorul funcției.

Apoi, definește ce se afișează în conținutul coloanei tale summary folosind acțiunea manage_posts_custom_column. Pentru acest exemplu, se afișează doar valoarea câmpului meta summary.

/**
 * Afișează conținutul coloanei Summary
 *
 * @param string $column_name Numele coloanei de afișat.
 * @param int $post_id ID-ul postării curente afișate.
 *
 * @return void
 */
function prefix_display_summary_column($column_name, $post_id)
{
    if ($column_name === 'summary') {
        echo esc_html(get_post_meta($post_id,'summary',true));
    }
}
add_action('manage_posts_custom_column', 'prefix_display_summary_column', 10, 2);

Din nou, poți folosi add_action('manage_post_posts_custom_column', 'prefix_display_summary_column', 10, 2); și add_action('manage_episode_posts_custom_column', 'prefix_display_summary_column', 10, 2); pentru a aplica acțiunea la tipuri specifice de postări. Motivul pentru care nu există o verificare a tipului de postare este că această coloană nu va exista pe alte tipuri de postări datorită pasului anterior.

Adăugare câmp de editare rapidă

Acum este suficient pentru a afișa coloana personalizată summary și datele sale. Următorul pas este adăugarea funcționalității pentru editarea rapidă. Primul pas este adăugarea acesteia la datele inline ascunse pentru a le stoca pe frontend pentru recuperare ulterioară folosind acțiunea add_inline_data astfel:

/**
 * Adaugă Summary la datele editorului inline
 *
 * @param WP_Post $post Obiectul postării curente.
 *
 * @return void
 */
function prefix_add_summary_inline($post)
{
    if (in_array($post->post_type, array('post','episode'))) {
        printf(
            '<div class="summary">%s</div>',
            esc_html(get_post_meta($post->ID,'summary',true))
        );
    }
}
add_action('add_inline_data', 'prefix_add_summary_inline');

La momentul scrierii acestui cod, nu există o acțiune specifică tipului de postare, deci este necesară verificarea cu if. Folosesc esc_html() aici, dar poți folosi orice funcție de escapare este potrivită pentru datele tale.

Acum pentru a afișa câmpul text în caseta de editare rapidă folosind acțiunea quick_edit_custom_box astfel:

/**
 * Afișează câmpul de introducere Summary în editor
 *
 * @param string $column_name Numele coloanei de editat.
 * @param string $post_type Slug-ul tipului de postare
 *
 * @return void
 */
function prefix_display_summary_field($column_name, $post_type)
{
    if ($column_name == 'summary' && in_array($post_type, array('post', 'episode'))) {
        printf(
            '<fieldset class="inline-edit-col-right">
                <div class="inline-edit-col">
                    <div class="inline-edit-group wp-clearfix">
                        <label class="inline-edit-au-websites alignleft">
                            <span class="title">%s</span>
                            <span class="input-text-wrap">
                                <input type="text" name="%s" autocomplete="off">
                            </span>
                        </label>
                    </div>
                </div>
            </fieldset>',
            esc_html__('Rezumat'),
            esc_attr($column_name)
        );
    }
}
add_action('quick_edit_custom_box', 'prefix_display_summary_field', 10, 2);

Aici verificăm numele coloanei noastre personalizate și tipul de postare și afișăm HTML-ul care folosește un markup similar cu cel al altor câmpuri de editare rapidă. Poți minifica HTML-ul dacă dorești.

Și în final, ultima piesă este să preumplem câmpul de introducere cu datele ascunse! În loc să ne jucăm cu scriptul editorului, aici pur și simplu ascultăm de trigger-ul de focus pe care îl emite când se deschide, apoi luăm valoarea noastră din câmpul ascuns și o setăm (dar numai dacă valoarea noastră ascunsă are date și câmpul editorului este gol)!

Pentru asta, mă conectez la acțiunea admin_enqueue_scripts și folosesc funcția wp_add_inline_script pentru a atașa scriptul nostru JS la scriptul inline editor (inline-edit-post) care este deja încărcat pe pagină. În acest fel, scriptul nostru va apărea mereu după încărcarea inline-edit-post.min.js, dar numai pe tipurile noastre specificate de postări post și episode.

/**
 * Preumple câmpul Summary cu valoarea postării
 *
 * @param string $hook Sufixul hook-ului pentru pagina curentă de administrare
 *
 * @return void
 */
function prefix_prefill_summary_field($hook) {
    if ($hook == 'edit.php' && in_array(get_post_type(), array('post', 'episode'))) {
        wp_add_inline_script(
            'inline-edit-post', // Handle
            '(function($) {
                $(".ptitle").on("focus",function(e){
                    let id = parseInt($(e.target).closest(".quick-edit-row").attr("id").replace("edit-","")),
                        value = $("#inline_"+id+" .summary").text(),
                        $input = $("#edit-"+id+".quick-edit-row input[name=summary]");
                    if(value && !$input.val()) {
                        $input.val(value);
                    }
                });
            })(jQuery);'
        );
    }
}
add_action('admin_enqueue_scripts', 'prefix_prefill_summary_field');

Toate acestea funcționează pentru că extind ceea ce WordPress face în mod nativ, cum salvează datele meta și datele postărilor. De aceea nu trebuie să scriu nimic personalizat pentru o acțiune save_post.

17 ian. 2024 01:20:19
Comentarii

Ce face salvarea să funcționeze? Cum știe WP care este numele câmpului meta în care să salveze?

Bence Szalai Bence Szalai
14 oct. 2024 16:02:03

@bence-szalai WordPress află numele cheii meta prin atributul name al elementului de control din formularul de editare rapidă a postării. În exemplul de mai sus, este valoarea $column_name din funcția prefix_display_summary_field(), de exemplu summary. Personal, aș prefixa toate câmpurile meta pentru a preveni suprascrieri accidentale. Știe să o salveze deoarece va exista în array-ul $_POST la trimiterea formularului, pe care WP îl va citi dinamic și îl va salva în post meta.

AuRise AuRise
17 oct. 2024 17:39:17