CLASS zcl_abapgit_gui_page_commit DEFINITION PUBLIC INHERITING FROM zcl_abapgit_gui_component FINAL CREATE PRIVATE. PUBLIC SECTION. INTERFACES zif_abapgit_gui_event_handler. INTERFACES zif_abapgit_gui_renderable. CLASS-METHODS create IMPORTING !ii_repo_online TYPE REF TO zif_abapgit_repo_online !io_stage TYPE REF TO zcl_abapgit_stage !iv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result DEFAULT zif_abapgit_definitions=>c_sci_result-no_run RETURNING VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable RAISING zcx_abapgit_exception. METHODS constructor IMPORTING !ii_repo_online TYPE REF TO zif_abapgit_repo_online !io_stage TYPE REF TO zcl_abapgit_stage !iv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result RAISING zcx_abapgit_exception. PROTECTED SECTION. PRIVATE SECTION. CONSTANTS: BEGIN OF c_id, committer TYPE string VALUE 'committer', committer_name TYPE string VALUE 'committer_name', committer_email TYPE string VALUE 'committer_email', message TYPE string VALUE 'message', comment TYPE string VALUE 'comment', body TYPE string VALUE 'body', author TYPE string VALUE 'author', author_name TYPE string VALUE 'author_name', author_email TYPE string VALUE 'author_email', new_branch_name TYPE string VALUE 'new_branch_name', END OF c_id. CONSTANTS: BEGIN OF c_event, commit TYPE string VALUE 'commit', END OF c_event. DATA mo_form TYPE REF TO zcl_abapgit_html_form. DATA mo_form_data TYPE REF TO zcl_abapgit_string_map. DATA mo_form_util TYPE REF TO zcl_abapgit_html_form_utils. DATA mo_validation_log TYPE REF TO zcl_abapgit_string_map. DATA mo_settings TYPE REF TO zcl_abapgit_settings. DATA mi_repo_online TYPE REF TO zif_abapgit_repo_online. DATA mo_stage TYPE REF TO zcl_abapgit_stage. DATA mt_stage TYPE zif_abapgit_definitions=>ty_stage_tt. DATA ms_commit TYPE zif_abapgit_services_git=>ty_commit_fields. DATA mv_sci_result TYPE zif_abapgit_definitions=>ty_sci_result. METHODS render_stage_summary RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception. METHODS render_stage_details RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING zcx_abapgit_exception. METHODS validate_form IMPORTING !io_form_data TYPE REF TO zcl_abapgit_string_map RETURNING VALUE(ro_validation_log) TYPE REF TO zcl_abapgit_string_map RAISING zcx_abapgit_exception. METHODS get_form_schema RETURNING VALUE(ro_form) TYPE REF TO zcl_abapgit_html_form. METHODS get_defaults RAISING zcx_abapgit_exception. METHODS get_committer_name RETURNING VALUE(rv_user) TYPE string RAISING zcx_abapgit_exception. METHODS get_committer_email RETURNING VALUE(rv_email) TYPE string RAISING zcx_abapgit_exception. METHODS get_comment_default RETURNING VALUE(rv_text) TYPE string. METHODS get_comment_object IMPORTING !it_stage TYPE zif_abapgit_definitions=>ty_stage_tt RETURNING VALUE(rv_text) TYPE string. METHODS get_comment_file IMPORTING !it_stage TYPE zif_abapgit_definitions=>ty_stage_tt RETURNING VALUE(rv_text) TYPE string. METHODS branch_name_to_internal IMPORTING iv_branch_name TYPE string RETURNING VALUE(rv_new_branch_name) TYPE string. ENDCLASS. CLASS zcl_abapgit_gui_page_commit IMPLEMENTATION. METHOD branch_name_to_internal. rv_new_branch_name = zcl_abapgit_git_branch_list=>complete_heads_branch_name( zcl_abapgit_git_branch_list=>normalize_branch_name( iv_branch_name ) ). ENDMETHOD. METHOD constructor. super->constructor( ). mi_repo_online = ii_repo_online. mo_stage = io_stage. mt_stage = mo_stage->get_all( ). mv_sci_result = iv_sci_result. " Get settings from DB mo_settings = zcl_abapgit_persist_factory=>get_settings( )->read( ). CREATE OBJECT mo_validation_log. CREATE OBJECT mo_form_data. mo_form = get_form_schema( ). mo_form_util = zcl_abapgit_html_form_utils=>create( mo_form ). ENDMETHOD. METHOD create. DATA lo_component TYPE REF TO zcl_abapgit_gui_page_commit. CREATE OBJECT lo_component EXPORTING ii_repo_online = ii_repo_online io_stage = io_stage iv_sci_result = iv_sci_result. ri_page = zcl_abapgit_gui_page_hoc=>create( iv_page_title = 'Commit' ii_child_component = lo_component ). ENDMETHOD. METHOD get_comment_default. rv_text = mo_settings->get_commitmsg_comment_default( ). IF rv_text IS INITIAL. RETURN. ENDIF. REPLACE '$FILE' IN rv_text WITH get_comment_file( mt_stage ). REPLACE '$OBJECT' IN rv_text WITH get_comment_object( mt_stage ). ENDMETHOD. METHOD get_comment_file. DATA lv_count TYPE i. FIELD-SYMBOLS LIKE LINE OF it_stage. lv_count = lines( it_stage ). IF lv_count = 1. " Just one file so we use the file name READ TABLE it_stage ASSIGNING INDEX 1. ASSERT sy-subrc = 0. rv_text = -file-filename. ELSE. " For multiple file we use the count instead rv_text = |{ lv_count } files|. ENDIF. ENDMETHOD. METHOD get_comment_object. DATA: lv_count TYPE i, ls_item TYPE zif_abapgit_definitions=>ty_item, lt_items TYPE zif_abapgit_definitions=>ty_items_tt. FIELD-SYMBOLS LIKE LINE OF it_stage. " Get objects LOOP AT it_stage ASSIGNING . CLEAR ls_item. ls_item-obj_type = -status-obj_type. ls_item-obj_name = -status-obj_name. COLLECT ls_item INTO lt_items. ENDLOOP. lv_count = lines( lt_items ). IF lv_count = 1. " Just one object so we use the object name READ TABLE lt_items INTO ls_item INDEX 1. ASSERT sy-subrc = 0. CONCATENATE ls_item-obj_type ls_item-obj_name INTO rv_text SEPARATED BY space. ELSE. " For multiple objects we use the count instead rv_text = |{ lv_count } objects|. ENDIF. ENDMETHOD. METHOD get_committer_email. DATA li_user TYPE REF TO zif_abapgit_persist_user. li_user = zcl_abapgit_persistence_user=>get_instance( ). rv_email = li_user->get_repo_git_user_email( mi_repo_online->get_url( ) ). IF rv_email IS INITIAL. rv_email = li_user->get_default_git_user_email( ). ENDIF. IF rv_email IS INITIAL. " get default from user record rv_email = zcl_abapgit_env_factory=>get_user_record( )->get_email( sy-uname ). ENDIF. ENDMETHOD. METHOD get_committer_name. DATA li_user TYPE REF TO zif_abapgit_persist_user. li_user = zcl_abapgit_persistence_user=>get_instance( ). rv_user = li_user->get_repo_git_user_name( mi_repo_online->get_url( ) ). IF rv_user IS INITIAL. rv_user = li_user->get_default_git_user_name( ). ENDIF. IF rv_user IS INITIAL. " get default from user record rv_user = zcl_abapgit_env_factory=>get_user_record( )->get_name( sy-uname ). ENDIF. ENDMETHOD. METHOD get_defaults. ms_commit-committer_name = get_committer_name( ). ms_commit-committer_email = get_committer_email( ). ms_commit-comment = get_comment_default( ). " Committer mo_form_data->set( iv_key = c_id-committer_name iv_val = ms_commit-committer_name ). mo_form_data->set( iv_key = c_id-committer_email iv_val = ms_commit-committer_email ). " Message mo_form_data->set( iv_key = c_id-comment iv_val = ms_commit-comment ). ENDMETHOD. METHOD get_form_schema. DATA lv_commitmsg_comment_length TYPE i. CONSTANTS lc_commitmsg_comment_min_len TYPE i VALUE 1. CONSTANTS lc_commitmsg_comment_max_len TYPE i VALUE 255. ro_form = zcl_abapgit_html_form=>create( iv_form_id = 'commit-form' iv_help_page = 'https://docs.abapgit.org/guide-stage-commit.html' ). lv_commitmsg_comment_length = mo_settings->get_commitmsg_comment_length( ). ro_form->text( iv_name = c_id-comment iv_label = 'Comment' iv_required = abap_true iv_min = lc_commitmsg_comment_min_len iv_max = lv_commitmsg_comment_length iv_placeholder = |Add a mandatory comment with max { lc_commitmsg_comment_max_len } characters| )->textarea( iv_name = c_id-body iv_label = 'Body' iv_rows = 6 iv_cols = mo_settings->get_commitmsg_body_size( ) iv_placeholder = 'Add an optional description...' )->text( iv_name = c_id-committer_name iv_label = 'Committer Name' iv_required = abap_true )->text( iv_name = c_id-committer_email iv_label = 'Committer Email' iv_required = abap_true ). IF mo_settings->get_commitmsg_hide_author( ) IS INITIAL. ro_form->text( iv_name = c_id-author_name iv_label = 'Author Name' iv_placeholder = 'Optionally, specify an author (same as committer by default)' )->text( iv_name = c_id-author_email iv_label = 'Author Email' ). ENDIF. ro_form->text( iv_name = c_id-new_branch_name iv_label = 'New Branch Name' iv_placeholder = 'Optionally, enter a new branch name for this commit' iv_condense = abap_true ). ro_form->command( iv_label = 'Commit' iv_cmd_type = zif_abapgit_html_form=>c_cmd_type-input_main iv_action = c_event-commit )->command( iv_label = 'Back' iv_action = zif_abapgit_definitions=>c_action-go_back ). ENDMETHOD. METHOD render_stage_details. FIELD-SYMBOLS LIKE LINE OF mt_stage. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). LOOP AT mt_stage ASSIGNING . ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ri_html->add( '' ). ENDLOOP. ri_html->add( '' ). ri_html->add( '
Staged Files (See Summary Above)
' ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_item_state( iv_lstate = -status-lstate iv_rstate = -status-rstate ) ). ri_html->add( '' ). ri_html->add( zcl_abapgit_stage=>method_description( -method ) ). ri_html->add( '' ). ri_html->add( -file-path && -file-filename ). ri_html->add( '
' ). ENDMETHOD. METHOD render_stage_summary. DATA: BEGIN OF ls_sum, method TYPE string, count TYPE i, END OF ls_sum, lt_sum LIKE STANDARD TABLE OF ls_sum WITH DEFAULT KEY. FIELD-SYMBOLS LIKE LINE OF mt_stage. CREATE OBJECT ri_html TYPE zcl_abapgit_html. LOOP AT mt_stage ASSIGNING . ls_sum-method = -method. ls_sum-count = 1. COLLECT ls_sum INTO lt_sum. ENDLOOP. ri_html->add( 'Stage Summary: ' ). READ TABLE lt_sum INTO ls_sum WITH TABLE KEY method = zif_abapgit_definitions=>c_method-add. IF sy-subrc = 0. ri_html->add( |+ { ls_sum-count }| ). ENDIF. READ TABLE lt_sum INTO ls_sum WITH TABLE KEY method = zif_abapgit_definitions=>c_method-rm. IF sy-subrc = 0. ri_html->add( |- { ls_sum-count }| ). ENDIF. READ TABLE lt_sum INTO ls_sum WITH TABLE KEY method = zif_abapgit_definitions=>c_method-ignore. IF sy-subrc = 0. ri_html->add( |~ { ls_sum-count }| ). ENDIF. IF lines( mt_stage ) = 1. ri_html->add( 'file' ). ELSE. ri_html->add( 'files' ). ENDIF. ri_html->add( '(See Details Below)' ). ENDMETHOD. METHOD validate_form. DATA: lt_branches TYPE zif_abapgit_git_definitions=>ty_git_branch_list_tt, lv_new_branch_name TYPE string. ro_validation_log = mo_form_util->validate( io_form_data ). IF zcl_abapgit_utils=>is_valid_email( io_form_data->get( c_id-committer_email ) ) = abap_false. ro_validation_log->set( iv_key = c_id-committer_email iv_val = |Invalid email address| ). ENDIF. IF zcl_abapgit_utils=>is_valid_email( io_form_data->get( c_id-author_email ) ) = abap_false. ro_validation_log->set( iv_key = c_id-author_email iv_val = |Invalid email address| ). ENDIF. lv_new_branch_name = io_form_data->get( c_id-new_branch_name ). IF lv_new_branch_name IS NOT INITIAL. " check if branch already exists lt_branches = zcl_abapgit_git_factory=>get_git_transport( )->branches( mi_repo_online->get_url( ) )->get_branches_only( ). READ TABLE lt_branches TRANSPORTING NO FIELDS WITH TABLE KEY name_key COMPONENTS name = branch_name_to_internal( lv_new_branch_name ). IF sy-subrc = 0. ro_validation_log->set( iv_key = c_id-new_branch_name iv_val = |Branch already exists| ). ENDIF. ENDIF. ENDMETHOD. METHOD zif_abapgit_gui_event_handler~on_event. DATA lv_new_branch_name TYPE string. mo_form_data = mo_form_util->normalize( ii_event->form_data( ) ). CASE ii_event->mv_action. WHEN c_event-commit. " Validate form entries before committing mo_validation_log = validate_form( mo_form_data ). IF mo_validation_log->is_empty( ) = abap_true. " new branch fields not needed in commit data mo_form_data->strict( abap_false ). mo_form_data->to_abap( CHANGING cs_container = ms_commit ). REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN ms_commit-body WITH cl_abap_char_utilities=>newline. lv_new_branch_name = mo_form_data->get( c_id-new_branch_name ). " create new branch and commit to it if branch name is not empty IF lv_new_branch_name IS NOT INITIAL. lv_new_branch_name = branch_name_to_internal( lv_new_branch_name ). " creates a new branch and automatically switches to it mi_repo_online->create_branch( lv_new_branch_name ). ENDIF. zcl_abapgit_services_git=>commit( is_commit = ms_commit ii_repo_online = mi_repo_online io_stage = mo_stage ). MESSAGE 'Commit was successful' TYPE 'S'. rs_handled-state = zcl_abapgit_gui=>c_event_state-go_back_to_bookmark. ELSE. rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. ENDIF. WHEN OTHERS. ASSERT 1 = 1. ENDCASE. ENDMETHOD. METHOD zif_abapgit_gui_renderable~render. register_handlers( ). IF mo_form_util->is_empty( mo_form_data ) = abap_true. get_defaults( ). ENDIF. CREATE OBJECT ri_html TYPE zcl_abapgit_html. ri_html->add( '
' ). ri_html->add( '
' ). ri_html->add( zcl_abapgit_gui_chunk_lib=>render_repo_top( mi_repo_online ) ). ri_html->add( '
' ). ri_html->add( '
' ). ri_html->add( render_stage_summary( ) ). ri_html->add( '
' ). ri_html->add( mo_form->render( iv_form_class = 'w800px' io_values = mo_form_data io_validation_log = mo_validation_log ) ). ri_html->add( '
' ). ri_html->add( render_stage_details( ) ). ri_html->add( '
' ). ri_html->add( '
' ). ENDMETHOD. ENDCLASS.