diff --git a/dt-core/admin/js/dt-options.js b/dt-core/admin/js/dt-options.js index 9544f5c0ca..52ef4b1a6f 100644 --- a/dt-core/admin/js/dt-options.js +++ b/dt-core/admin/js/dt-options.js @@ -1,7 +1,7 @@ jQuery(document).ready(function ($) { - $('.expand_translations').click(function () { - event.preventDefault(); - display_translation_dialog($(this).siblings(), $(this).data('form_name')); + $('.expand_translations').click(function (e) { + e.preventDefault(); + display_translation_dialog($(this).siblings(), $(this).data('form_name'), $(this).data('source')); }); $('.change-icon-button').click(function (e) { @@ -42,12 +42,12 @@ jQuery(document).ready(function ($) { * Translation modal dialog */ - function display_translation_dialog(container, form_name) { + function display_translation_dialog(container, form_name, source = '') { let dialog = $('#dt_translation_dialog'); if (container && form_name && dialog) { // Update dialog div - $(dialog).empty().append($(container).find('table').clone()); + $(dialog).empty().append($($(container).find('table')[0]).clone()); // Refresh dialog config dialog.dialog({ @@ -68,8 +68,12 @@ jQuery(document).ready(function ($) { // Close dialog $(this).dialog('close'); - // Finally, auto save changes - $('form[name="' + form_name + '"]').submit(); + // Finally, auto save changes, accordingly, based on source. + if (window.lodash.includes(['fields'], source)) { + handle_custom_field_save_request(null, $('.dt-custom-fields-save-button')[0], true); + } else { + $('form[name="' + form_name + '"]').submit(); + } } } @@ -558,4 +562,154 @@ jQuery(document).ready(function ($) { /** * Tile Display Help Modal - [END] */ + + /** + * Alternative Save Flow - [START] + */ + + $(document).on('click', '.dt-custom-fields-save-button', function (e) { + handle_custom_field_save_request(e, $(e.currentTarget), false); + }); + + function handle_custom_field_save_request(event, save_button, translate_update_only) { + + // If defined, short-circuit default save flow and adopt ajax approach if needed. + if (event) { + event.preventDefault(); + } + + // Determine which save path is to be taken. + if (!translate_update_only) { + $('form[name="' + $(save_button).data('form_id') + '"]').submit(); + } else { + + // Always capture field parent level name & description translations; which is present across all fields. + let payload = { + 'post_type': $(save_button).data('post_type'), + 'field_id': $(save_button).data('field_id'), + 'field_type': $(save_button).data('field_type'), + 'translations': package_custom_field_translations($(save_button).data('field_id')), + 'option_translations': window.lodash.includes(['key_select', 'multi_select', 'link'], $(save_button).data('field_type')) ? package_custom_field_option_translations():[] + }; + + // Have core endpoint process field translations accordingly. + $.ajax({ + type: 'POST', + contentType: 'application/json; charset=utf-8', + dataType: 'json', + data: JSON.stringify(payload), + url: `${window.dt_admin_scripts.rest_root}dt-admin/scripts/update_custom_field_translations`, + beforeSend: (xhr) => { + xhr.setRequestHeader('X-WP-Nonce', window.dt_admin_scripts.nonce); + } + }).done(function (response) { + console.log(response); + + // Update translation counts. + $('#custom_name_translation_count').html((response['translations']) ? Object.keys(response['translations']).length:0); + $('#custom_description_translation_count').html((response['description_translations']) ? Object.keys(response['description_translations']).length:0); + if ((response['defaults']) && window.lodash.includes(['key_select', 'multi_select', 'link'], $(save_button).data('field_type'))) { + $('.sortable-field-options').find('tr.ui-sortable-handle').each(function (idx, tr) { + let option_key = $(tr).find('.sortable-field-options-key').text().trim(); + $(tr).find('#option_name_translation_count').html((response['defaults'] && response['defaults'][option_key] && response['defaults'][option_key]['translations']) ? Object.keys(response['defaults'][option_key]['translations']).length:0); + $(tr).find('#option_description_translation_count').html((response['defaults'] && response['defaults'][option_key] && response['defaults'][option_key]['description_translations']) ? Object.keys(response['defaults'][option_key]['description_translations']).length:0); + }); + } + + }).fail(function (error) { + console.log("error"); + console.log(error); + }); + } + } + + function package_custom_field_translations(field_id) { + let packaged_translations = { + 'translations': [], + 'description_translations': [] + }; + + // Locate field name translations. + let field_name_prefix = 'field_key_' + field_id + '_translation-'; + $("input[id^='" + field_name_prefix + "']").each(function (idx, input) { + let locale = window.lodash.split($(input).attr('id'), '-')[1]; + let value = $(input).val(); + if (locale && value) { + packaged_translations['translations'].push({ + 'locale': locale, + 'value': value + }); + } + }); + + // Locate field description translations. + let field_description_prefix = 'field_description_translation-'; + $("input[id^='" + field_description_prefix + "']").each(function (idx, input) { + let locale = window.lodash.split($(input).attr('id'), '-')[1]; + let value = $(input).val(); + if (locale && value) { + packaged_translations['description_translations'].push({ + 'locale': locale, + 'value': value + }); + } + }); + + return packaged_translations; + } + + function package_custom_field_option_translations() { + let packaged_translations = []; + + $('.sortable-field-options').find('tr.ui-sortable-handle').each(function (idx, tr) { + let translations = { + 'option_key': '', + 'option_translations': [], + 'option_description_translations': [] + }; + + // Determine option key. + let option_key = $(tr).find('.sortable-field-options-key').text().trim(); + if (option_key) { + translations['option_key'] = option_key; + + // Locate option key translations. + let option_key_prefix = 'field_option_' + option_key + '_translation-'; + $(tr).find("input[id^='" + option_key_prefix + "']").each(function (okt_idx, okt_input) { + let locale = window.lodash.split($(okt_input).attr('id'), '-')[1]; + let value = $(okt_input).val(); + if (locale && value) { + translations['option_translations'].push({ + 'locale': locale, + 'value': $(okt_input).val() + }); + } + }); + + // Locate option key description translations. + let option_key_description_prefix = 'option_description_' + option_key + '_translation-'; + $(tr).find("input[id^='" + option_key_description_prefix + "']").each(function (okdt_idx, okdt_input) { + let locale = window.lodash.split($(okdt_input).attr('id'), '-')[1]; + let value = $(okdt_input).val(); + if (locale && value) { + translations['option_description_translations'].push({ + 'locale': locale, + 'value': $(okdt_input).val() + }); + } + }); + + // Package recent translations. + packaged_translations.push(translations); + } + }); + + return packaged_translations; + } + + /** + * Alternative Save Flow - [END] + */ + + }) diff --git a/dt-core/admin/menu/tabs/admin-endpoints.php b/dt-core/admin/menu/tabs/admin-endpoints.php index b720b5a250..2815849f44 100644 --- a/dt-core/admin/menu/tabs/admin-endpoints.php +++ b/dt-core/admin/menu/tabs/admin-endpoints.php @@ -25,6 +25,15 @@ public function add_api_routes(){ }, ] ); + register_rest_route( + $this->namespace, '/scripts/update_custom_field_translations', [ + 'methods' => 'POST', + 'callback' => [ $this, 'update_custom_field_translations' ], + 'permission_callback' => function(){ + return current_user_can( 'manage_dt' ); + }, + ] + ); } public function reset_count_field( WP_REST_Request $request ){ @@ -61,6 +70,83 @@ public function reset_count_field_progress( WP_REST_Request $request ){ } } + public function update_custom_field_translations( WP_REST_Request $request ){ + $params = $request->get_params(); + if ( isset( $params['post_type'], $params['field_id'], $params['field_type'], $params['translations'] ) ){ + $post_type = $params['post_type']; + $field_id = $params['field_id']; + $field_type = $params['field_type']; + $translations = $params['translations']; + $option_translations = $params['option_translations'] ?? []; + + // Fetch existing field customizations and if needed, create relevant spaces! + $field_customizations = dt_get_option( 'dt_field_customizations' ); + if ( !isset( $field_customizations[$post_type][$field_id] ) ){ + $field_customizations[$post_type][$field_id] = []; + } + $custom_field = $field_customizations[$post_type][$field_id]; + + // Capture available field name translations. + $custom_field['translations'] = []; + foreach ( $translations['translations'] ?? [] as $translation ){ + if ( !empty( $translation['locale'] ) && !empty( $translation['value'] ) ){ + $custom_field['translations'][$translation['locale']] = $translation['value']; + } + } + + // Capture available field description translations. + $custom_field['description_translations'] = []; + foreach ( $translations['description_translations'] ?? [] as $translation ){ + if ( !empty( $translation['locale'] ) && !empty( $translation['value'] ) ){ + $custom_field['description_translations'][$translation['locale']] = $translation['value']; + } + } + + // If required, update custom field default options. + if ( in_array( $field_type, [ 'key_select', 'multi_select', 'link' ] ) ){ + $defaults = []; + foreach ( $option_translations as $option ){ + $option_key = $option['option_key']; + + if ( !empty( $option_key ) ){ + $defaults[$option_key] = []; + $defaults[$option_key]['translations'] = []; + $defaults[$option_key]['description_translations'] = []; + + // Capture option translations. + foreach ( $option['option_translations'] ?? [] as $option_translation ){ + if ( !empty( $option_translation['locale'] ) && !empty( $option_translation['value'] ) ){ + $defaults[$option_key]['translations'][$option_translation['locale']] = $option_translation['value']; + } + } + + // Capture option description translations. + foreach ( $option['option_description_translations'] ?? [] as $option_description_translations ){ + if ( !empty( $option_description_translations['locale'] ) && !empty( $option_description_translations['value'] ) ){ + $defaults[$option_key]['description_translations'][$option_description_translations['locale']] = $option_description_translations['value']; + } + } + } + } + $custom_field['default'] = $defaults; + } + + // Persist updated custom field option translations. + $field_customizations[$post_type][$field_id] = $custom_field; + update_option( 'dt_field_customizations', $field_customizations ); + + // For completeness, return updated shape! + return [ + 'translations' => $custom_field['translations'] ?? [], + 'description_translations' => $custom_field['description_translations'] ?? [], + 'defaults' => $custom_field['default'] ?? [] + ]; + + } else { + return new WP_Error( __FILE__, 'Missing required parameters.' ); + } + } + } use WP_Queue\Job; diff --git a/dt-core/admin/menu/tabs/tab-custom-fields.php b/dt-core/admin/menu/tabs/tab-custom-fields.php index eeebb5d345..e454c83b75 100644 --- a/dt-core/admin/menu/tabs/tab-custom-fields.php +++ b/dt-core/admin/menu/tabs/tab-custom-fields.php @@ -597,7 +597,8 @@ private function edit_field( $field_key, $post_type ){