diff --git a/src/zabapgit.prog.abap b/src/zabapgit.prog.abap index 322c9d428..ebb165793 100644 --- a/src/zabapgit.prog.abap +++ b/src/zabapgit.prog.abap @@ -43,7 +43,7 @@ INCLUDE zabapgit_html. INCLUDE zabapgit_util. INCLUDE zabapgit_xml. -INCLUDE zabapgit_app. " Some deferred definitions here +INCLUDE zabapgit_app. " Some deferred definitions here INCLUDE zabapgit_persistence_old. INCLUDE zabapgit_persistence. INCLUDE zabapgit_dot_abapgit. @@ -61,14 +61,14 @@ INCLUDE zabapgit_popups. INCLUDE zabapgit_zip. INCLUDE zabapgit_objects_impl. -INCLUDE zabapgit_object_serializing. " All serializing classes here +INCLUDE zabapgit_object_serializing. " All serializing classes here INCLUDE zabapgit_repo_impl. INCLUDE zabapgit_background. INCLUDE zabapgit_transport. -INCLUDE zabapgit_services. " All services here -INCLUDE zabapgit_gui_pages. " All GUI pages here +INCLUDE zabapgit_services. " All services here +INCLUDE zabapgit_gui_pages. " All GUI pages here INCLUDE zabapgit_gui_pages_userexit IF FOUND. INCLUDE zabapgit_gui_router. INCLUDE zabapgit_gui. diff --git a/src/zabapgit_html_action_utils.prog.abap b/src/zabapgit_html_action_utils.prog.abap index 0e79640a0..bf425fa06 100644 --- a/src/zabapgit_html_action_utils.prog.abap +++ b/src/zabapgit_html_action_utils.prog.abap @@ -32,6 +32,15 @@ CLASS lcl_html_action_utils DEFINITION FINAL. ev_obj_name TYPE tadir-obj_name RAISING lcx_exception. + CLASS-METHODS dir_encode + IMPORTING iv_path TYPE string + RETURNING VALUE(rv_string) TYPE string. + + CLASS-METHODS dir_decode + IMPORTING iv_string TYPE clike + RETURNING VALUE(rv_path) TYPE string + RAISING lcx_exception. + CLASS-METHODS file_encode IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key ig_file TYPE any "assuming ty_file @@ -162,6 +171,22 @@ CLASS lcl_html_action_utils IMPLEMENTATION. ENDMETHOD. "jump_decode + METHOD dir_encode. + + DATA: lt_fields TYPE tihttpnvp. + add_field( EXPORTING name = 'PATH' iv = iv_path CHANGING ct = lt_fields ). + rv_string = cl_http_utility=>if_http_utility~fields_to_string( lt_fields ). + + ENDMETHOD. "dir_encode + + METHOD dir_decode. + + DATA: lt_fields TYPE tihttpnvp. + lt_fields = cl_http_utility=>if_http_utility~string_to_fields( |{ iv_string }| ). + get_field( EXPORTING name = 'PATH' it = lt_fields CHANGING cv = rv_path ). + + ENDMETHOD. "dir_decode + METHOD file_encode. DATA: lt_fields TYPE tihttpnvp. diff --git a/src/zabapgit_page.prog.abap b/src/zabapgit_page.prog.abap index 7e4cdc19e..657d659ee 100644 --- a/src/zabapgit_page.prog.abap +++ b/src/zabapgit_page.prog.abap @@ -29,6 +29,10 @@ CLASS lcl_gui_page_super DEFINITION ABSTRACT. PUBLIC SECTION. INTERFACES lif_gui_page ABSTRACT METHODS render. + CLASS-METHODS render_error + IMPORTING ix_error TYPE REF TO lcx_exception + RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper. + PROTECTED SECTION. METHODS render_repo_top IMPORTING io_repo TYPE REF TO lcl_repo @@ -261,6 +265,16 @@ CLASS lcl_gui_page_super IMPLEMENTATION. ENDMETHOD. "render html footer & logo + METHOD render_error. + + CREATE OBJECT ro_html. + + ro_html->add( '
' ). + ro_html->add( |Error: { ix_error->mv_text }| ). + ro_html->add( '
' ). + + ENDMETHOD. "render_error + METHOD redirect. CREATE OBJECT ro_html. diff --git a/src/zabapgit_page_main.prog.abap b/src/zabapgit_page_main.prog.abap index 43855a673..437da9aed 100644 --- a/src/zabapgit_page_main.prog.abap +++ b/src/zabapgit_page_main.prog.abap @@ -2,6 +2,8 @@ *& Include ZABAPGIT_PAGE_MAIN *&---------------------------------------------------------------------* +INCLUDE zabapgit_view_repo. + CLASS lcl_gui_page_main DEFINITION FINAL INHERITING FROM lcl_gui_page_super. PUBLIC SECTION. @@ -15,32 +17,16 @@ CLASS lcl_gui_page_main DEFINITION FINAL INHERITING FROM lcl_gui_page_super. PRIVATE SECTION. CONSTANTS: BEGIN OF c_actions, show TYPE string VALUE 'show' ##NO_TEXT, - toggle_hide_files TYPE string VALUE 'toggle_hide_files' ##NO_TEXT, END OF c_actions. - CONSTANTS: c_default_sortkey TYPE i VALUE 9999. - - TYPES: BEGIN OF ty_repo_item, - obj_type TYPE tadir-object, - obj_name TYPE tadir-obj_name, - is_first TYPE abap_bool, - files TYPE tt_repo_files, - sortkey TYPE i, - changes TYPE i, - END OF ty_repo_item. - TYPES tt_repo_items TYPE STANDARD TABLE OF ty_repo_item WITH DEFAULT KEY. - - DATA: mv_show TYPE lcl_persistence_db=>ty_value, - mv_hide_files TYPE abap_bool. + DATA: mv_show TYPE lcl_persistence_db=>ty_value, + mo_repo_content TYPE REF TO lcl_gui_view_repo_content. METHODS: - retrieve_active_repo - RAISING lcx_exception, styles RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper, - render_error - IMPORTING ix_error TYPE REF TO lcx_exception - RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper, + retrieve_active_repo + RAISING lcx_exception, render_toc IMPORTING it_list TYPE lcl_repo_srv=>ty_repo_tt RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper @@ -52,46 +38,40 @@ CLASS lcl_gui_page_main DEFINITION FINAL INHERITING FROM lcl_gui_page_super. RAISING lcx_exception, build_main_menu RETURNING VALUE(ro_menu) TYPE REF TO lcl_html_toolbar, - render_repo_menu - IMPORTING io_repo TYPE REF TO lcl_repo + render_explore RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper RAISING lcx_exception, render_repo IMPORTING io_repo TYPE REF TO lcl_repo - RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper - RAISING lcx_exception, - extract_repo_content - IMPORTING io_repo TYPE REF TO lcl_repo - EXPORTING et_repo_items TYPE tt_repo_items - eo_log TYPE REF TO lcl_log - RAISING lcx_exception, - render_repo_item - IMPORTING io_repo TYPE REF TO lcl_repo - is_item TYPE ty_repo_item - RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper - RAISING lcx_exception, - render_obj_jump_link - IMPORTING iv_obj_type TYPE tadir-object - iv_obj_name TYPE tadir-obj_name - RETURNING VALUE(rv_html) TYPE string, - render_explore RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper RAISING lcx_exception. ENDCLASS. + CLASS lcl_gui_page_main IMPLEMENTATION. METHOD constructor. - super->constructor( ). - ENDMETHOD. " constructor METHOD lif_gui_page~on_event. - DATA: lv_key TYPE lcl_persistence_repo=>ty_repo-key, - lv_url TYPE string. + DATA: lv_key TYPE lcl_persistence_repo=>ty_repo-key. + + mo_repo_content->lif_gui_page~on_event( + EXPORTING + iv_action = iv_action + iv_prev_page = iv_prev_page + iv_getdata = iv_getdata + it_postdata = it_postdata + IMPORTING + ei_page = ei_page + ev_state = ev_state ). + + IF ev_state <> gc_event_state-not_handled. + RETURN. + ENDIF. lv_key = iv_getdata. @@ -102,9 +82,8 @@ CLASS lcl_gui_page_main IMPLEMENTATION. lcl_app=>repo_srv( )->get( lv_key )->refresh( ). CATCH lcx_exception. ENDTRY. - ev_state = gc_event_state-re_render. - WHEN c_actions-toggle_hide_files. " Toggle file diplay - lcl_app=>user( )->toggle_hide_files( ). + + CREATE OBJECT mo_repo_content EXPORTING iv_key = lv_key. " Reinit content state ev_state = gc_event_state-re_render. ENDCASE. @@ -121,7 +100,6 @@ CLASS lcl_gui_page_main IMPLEMENTATION. lo_repo LIKE LINE OF lt_repos. retrieve_active_repo( ). " Get and validate key of user default repo - mv_hide_files = lcl_app=>user( )->get_hide_files( ). CREATE OBJECT ro_html. @@ -179,20 +157,6 @@ CLASS lcl_gui_page_main IMPLEMENTATION. ENDMETHOD. "retrieve_active_repo - METHOD render_obj_jump_link. - - DATA: lv_encode TYPE string, - lo_html TYPE REF TO lcl_html_helper. - - lv_encode = lcl_html_action_utils=>jump_encode( iv_obj_type = iv_obj_type - iv_obj_name = iv_obj_name ). - - CREATE OBJECT lo_html. - lo_html->add_anchor( iv_txt = |{ iv_obj_name }| iv_act = |{ gc_action-jump }?{ lv_encode }| ). - rv_html = lo_html->mv_html. - - ENDMETHOD. "render_obj_jump_link - METHOD build_main_menu. DATA lo_betasub TYPE REF TO lcl_html_toolbar. @@ -296,16 +260,6 @@ CLASS lcl_gui_page_main IMPLEMENTATION. ENDMETHOD. "render_toc_line - METHOD render_error. - - CREATE OBJECT ro_html. - - ro_html->add( '
' ). - ro_html->add( |Error: { ix_error->mv_text }| ). - ro_html->add( '
' ). - - ENDMETHOD. "render_error - METHOD render_explore. DATA lo_toolbar TYPE REF TO lcl_html_toolbar. @@ -322,339 +276,21 @@ CLASS lcl_gui_page_main IMPLEMENTATION. ENDMETHOD. "render_explore -********************************************************************** -* SELECTED REPO RENDERING -********************************************************************** - METHOD render_repo. - DATA: lt_repo_items TYPE tt_repo_items, - lo_tab_menu TYPE REF TO lcl_html_toolbar, - lx_error TYPE REF TO lcx_exception, - lo_log TYPE REF TO lcl_log. - - FIELD-SYMBOLS LIKE LINE OF lt_repo_items. - - CREATE OBJECT lo_tab_menu. CREATE OBJECT ro_html. + IF mo_repo_content IS NOT BOUND. + CREATE OBJECT mo_repo_content EXPORTING iv_key = io_repo->get_key( ). + ENDIF. + ro_html->add( |
| ). ro_html->add( render_repo_top( io_repo = io_repo iv_interactive_branch = abap_true ) ). - - TRY. - extract_repo_content( EXPORTING io_repo = io_repo - IMPORTING et_repo_items = lt_repo_items - eo_log = lo_log ). - - " extract_repo_content must be called before rendering the menu - " so that lo_log is filled with errors from the serialization - ro_html->add( render_repo_menu( io_repo ) ). - - IF io_repo->is_offline( ) = abap_false AND lo_log->count( ) > 0. - ro_html->add( '
' ). - ro_html->add( lo_log->to_html( ) ). " shows eg. list of unsupported objects - ro_html->add( '
' ). - ENDIF. - - ro_html->add( '
' ). - IF io_repo->is_offline( ) = abap_false. - IF mv_hide_files = abap_true. - lo_tab_menu->add( iv_txt = 'Show files' iv_act = c_actions-toggle_hide_files ). - ELSE. - lo_tab_menu->add( iv_txt = 'Hide files' iv_act = c_actions-toggle_hide_files ). - ENDIF. - ro_html->add( lo_tab_menu->render( iv_as_angle = abap_true ) ). - ENDIF. - - ro_html->add( '' ). - IF lines( lt_repo_items ) = 0. - ro_html->add( '' ) ##NO_TEXT. - ELSE. - LOOP AT lt_repo_items ASSIGNING . - ro_html->add( render_repo_item( io_repo = io_repo is_item = ) ). - ENDLOOP. - ENDIF. - ro_html->add( '
' - && '
Empty package
' - && '
' ). - ro_html->add( '
' ). - - CATCH lcx_exception INTO lx_error. - ro_html->add( render_repo_menu( io_repo ) ). - ro_html->add( render_error( lx_error ) ). - ENDTRY. - + ro_html->add( mo_repo_content->lif_gui_page~render( ) ). ro_html->add( '
' ). ENDMETHOD. "render_repo - METHOD render_repo_menu. - - DATA: lo_toolbar TYPE REF TO lcl_html_toolbar, - lo_tb_advanced TYPE REF TO lcl_html_toolbar, - lo_tb_branch TYPE REF TO lcl_html_toolbar, - lv_key TYPE lcl_persistence_db=>ty_value, - lv_wp_opt LIKE gc_html_opt-crossout, - lv_pull_opt LIKE gc_html_opt-crossout, - lo_repo_online TYPE REF TO lcl_repo_online. - - CREATE OBJECT ro_html. - CREATE OBJECT lo_toolbar. - CREATE OBJECT lo_tb_branch. - CREATE OBJECT lo_tb_advanced. - - lv_key = io_repo->get_key( ). - IF io_repo->is_offline( ) = abap_false. - lo_repo_online ?= io_repo. - ENDIF. - - IF io_repo->is_write_protected( ) = abap_true. - lv_wp_opt = gc_html_opt-crossout. - lv_pull_opt = gc_html_opt-crossout. - ELSE. - lv_pull_opt = gc_html_opt-emphas. - ENDIF. - - " Build branch drop-down ======================== - IF io_repo->is_offline( ) = abap_false. " Online ? - lo_tb_branch->add( iv_txt = 'Overview' - iv_act = |{ gc_action-go_branch_overview }?{ lv_key }| ). - lo_tb_branch->add( iv_txt = 'Switch' - iv_act = |{ gc_action-git_branch_switch }?{ lv_key }| - iv_opt = lv_wp_opt ). - lo_tb_branch->add( iv_txt = 'Create' - iv_act = |{ gc_action-git_branch_create }?{ lv_key }| ). - lo_tb_branch->add( iv_txt = 'Delete' - iv_act = |{ gc_action-git_branch_delete }?{ lv_key }| ). - ENDIF. - - " Build advanced drop-down ======================== - IF io_repo->is_offline( ) = abap_false. " Online ? - lo_tb_advanced->add( iv_txt = 'Reset local' - iv_act = |{ gc_action-git_reset }?{ lv_key }| - iv_opt = lv_wp_opt ). - lo_tb_advanced->add( iv_txt = 'Background mode' - iv_act = |{ gc_action-go_background }?{ lv_key }| ). - lo_tb_advanced->add( iv_txt = 'Change remote' - iv_act = |{ gc_action-repo_remote_change }?{ lv_key }| ). - lo_tb_advanced->add( iv_txt = 'Make off-line' - iv_act = |{ gc_action-repo_remote_detach }?{ lv_key }| ). - ELSE. - lo_tb_advanced->add( iv_txt = 'Make on-line' - iv_act = |{ gc_action-repo_remote_attach }?{ lv_key }| ). - ENDIF. - lo_tb_advanced->add( iv_txt = 'Remove' - iv_act = |{ gc_action-repo_remove }?{ lv_key }| ). - lo_tb_advanced->add( iv_txt = 'Uninstall' - iv_act = |{ gc_action-repo_purge }?{ lv_key }| - iv_opt = lv_wp_opt ). - - " Build main toolbar ============================== - IF io_repo->is_offline( ) = abap_false. " Online ? - TRY. - IF lo_repo_online->get_sha1_remote( ) <> lo_repo_online->get_sha1_local( ). - lo_toolbar->add( iv_txt = 'Pull' - iv_act = |{ gc_action-git_pull }?{ lv_key }| - iv_opt = lv_pull_opt ). - ENDIF. - IF lcl_stage_logic=>count( lo_repo_online ) > 0. - lo_toolbar->add( iv_txt = 'Stage' - iv_act = |{ gc_action-go_stage }?{ lv_key }| - iv_opt = gc_html_opt-emphas ). - ENDIF. - CATCH lcx_exception ##NO_HANDLER. - " authorization error or repository does not exist - " ignore error - ENDTRY. - lo_toolbar->add( iv_txt = 'Branch' - io_sub = lo_tb_branch ) ##NO_TEXT. - ELSE. - lo_toolbar->add( iv_txt = 'Import ZIP' - iv_act = |{ gc_action-zip_import }?{ lv_key }| - iv_opt = gc_html_opt-emphas ). - lo_toolbar->add( iv_txt = 'Export ZIP' - iv_act = |{ gc_action-zip_export }?{ lv_key }| - iv_opt = gc_html_opt-emphas ). - ENDIF. - - lo_toolbar->add( iv_txt = 'Advanced' - io_sub = lo_tb_advanced ) ##NO_TEXT. - lo_toolbar->add( iv_txt = 'Refresh' - iv_act = |{ gc_action-repo_refresh }?{ lv_key }| ). - - " Render ========================================== - ro_html->add( '
' ). - ro_html->add( lo_toolbar->render( ) ). - ro_html->add( '
' ). - - ENDMETHOD. "render_repo_menu - - METHOD extract_repo_content. - - DATA: lo_repo_online TYPE REF TO lcl_repo_online, - lt_tadir TYPE ty_tadir_tt, - ls_file TYPE ty_repo_file, - lt_results TYPE ty_results_tt. - - FIELD-SYMBOLS: LIKE LINE OF lt_results, - LIKE LINE OF et_repo_items, - LIKE LINE OF lt_tadir. - - - CLEAR et_repo_items. - - IF io_repo->is_offline( ) = abap_true. - lt_tadir = lcl_tadir=>read( io_repo->get_package( ) ). - LOOP AT lt_tadir ASSIGNING . - APPEND INITIAL LINE TO et_repo_items ASSIGNING . - IF sy-tabix = 1. - -is_first = abap_true. - ENDIF. - -obj_type = -object. - -obj_name = -obj_name. - ENDLOOP. - - ELSE. - CREATE OBJECT eo_log. - lo_repo_online ?= io_repo. - lt_results = lo_repo_online->status( eo_log ). - LOOP AT lt_results ASSIGNING . - AT NEW obj_name. "obj_type + obj_name - APPEND INITIAL LINE TO et_repo_items ASSIGNING . - -obj_type = -obj_type. - -obj_name = -obj_name. - -sortkey = c_default_sortkey. " Default sort key - -changes = 0. - ENDAT. - - IF -filename IS NOT INITIAL. - ls_file-path = -path. - ls_file-filename = -filename. - ls_file-is_changed = boolc( NOT -match = abap_true ). - ls_file-new = -new. - APPEND ls_file TO -files. - - IF ls_file-is_changed = abap_true OR ls_file-new IS NOT INITIAL. - -sortkey = 2. " Changed files - -changes = -changes + 1. - ENDIF. - ENDIF. - - AT END OF obj_name. "obj_type + obj_name - IF -obj_type IS INITIAL. - -sortkey = 0. "Virtual objects - ELSEIF lines( -files ) = 0. - -sortkey = 1. "New object to commit - ENDIF. - ENDAT. - ENDLOOP. - - SORT et_repo_items BY sortkey obj_type obj_name ASCENDING. - READ TABLE et_repo_items ASSIGNING INDEX 1. - IF sy-subrc IS INITIAL. - -is_first = abap_true. - ENDIF. - ENDIF. - - - ENDMETHOD. "extract_repo_content - - METHOD render_repo_item. - DATA: - lv_link TYPE string, - lv_icon TYPE string, - lv_difflink TYPE string, - ls_file LIKE LINE OF is_item-files, - lv_trclass TYPE string. - - CREATE OBJECT ro_html. - - IF is_item-is_first = abap_true. " TR class - lv_trclass = 'firstrow' ##NO_TEXT. - ENDIF. - IF is_item-obj_name IS INITIAL. - lv_trclass = lv_trclass && ' unsupported' ##NO_TEXT. - ENDIF. - IF is_item-sortkey > 0 AND is_item-sortkey < c_default_sortkey. - lv_trclass = lv_trclass && ' modified' ##NO_TEXT. - ENDIF. - IF lv_trclass IS NOT INITIAL. - SHIFT lv_trclass LEFT DELETING LEADING space. - lv_trclass = | class="{ lv_trclass }"|. - ENDIF. - - ro_html->add( || ). - - IF is_item-obj_name IS INITIAL. - ro_html->add( '' - && 'non-code and meta files' ). - ELSE. - CASE is_item-obj_type. "TODO ?? - WHEN 'PROG' OR 'CLAS' OR 'FUGR'. - lv_icon = ||. - WHEN 'W3MI' OR 'W3HT'. - lv_icon = ||. - WHEN ''. - lv_icon = space. " no icon - WHEN OTHERS. - lv_icon = ||. - ENDCASE. - - lv_link = render_obj_jump_link( iv_obj_name = is_item-obj_name - iv_obj_type = is_item-obj_type ). - ro_html->add( |{ lv_icon }| ). - ro_html->add( |{ is_item-obj_type }| ). - ro_html->add( |{ lv_link }| ). - ENDIF. - - IF io_repo->is_offline( ) = abap_false. " Files for online repos only - - ro_html->add( '' ). - IF mv_hide_files = abap_false OR is_item-obj_type IS INITIAL. - LOOP AT is_item-files INTO ls_file. - ro_html->add( |{ ls_file-path && ls_file-filename }| ). - ENDLOOP. - ENDIF. - ro_html->add( '' ). - - ro_html->add( '' ). - IF lines( is_item-files ) = 0. - ro_html->add( 'new @local' ). - ELSEIF is_item-changes > 0. - IF mv_hide_files = abap_true AND is_item-obj_name IS NOT INITIAL. - lv_difflink = lcl_html_action_utils=>obj_encode( - iv_key = io_repo->get_key( ) - ig_object = is_item ). - ro_html->add_anchor( - iv_txt = |diff ({ is_item-changes })| - iv_act = |{ gc_action-go_diff }?{ lv_difflink }| ). - ELSE. - LOOP AT is_item-files INTO ls_file. - IF ls_file-new = gc_new-remote. - ro_html->add( 'new @remote' ). - ELSEIF ls_file-new = gc_new-local. - ro_html->add( 'new @local' ). - ELSEIF ls_file-is_changed = abap_true. - lv_difflink = lcl_html_action_utils=>file_encode( - iv_key = io_repo->get_key( ) - ig_file = ls_file ). - ro_html->add_anchor( - iv_txt = 'diff' - iv_act = |{ gc_action-go_diff }?{ lv_difflink }| ). - ELSE. - ro_html->add( | | ). - ENDIF. - ENDLOOP. - ENDIF. - ENDIF. - ro_html->add( '' ). - - ENDIF. - - ro_html->add( '' ). - - ENDMETHOD. "render_repo_item - ********************************************************************** * ASSETS, STYLES, SCRIPTS ********************************************************************** @@ -698,12 +334,13 @@ CLASS lcl_gui_page_main IMPLEMENTATION. _add ' padding-left: 0.5em;'. _add ' padding-right: 1em;'. _add '}'. - _add '.repo_tab tr.unsupported { color: lightgrey; }'. - _add '.repo_tab tr.modified { background: #fbf7e9; }'. - _add '.repo_tab tr.firstrow td { border-top: 0px; }'. - _add '.repo_tab td.files span { display: block; }'. - _add '.repo_tab td.cmd span { display: block; }'. - _add '.repo_tab td.cmd a { display: block; }'. + _add '.repo_tab tr.unsupported { color: lightgrey; }'. + _add '.repo_tab tr.modified { background: #fbf7e9; }'. + _add '.repo_tab tr:first-child td { border-top: 0px; }'. + _add '.repo_tab td.files span { display: block; }'. + _add '.repo_tab td.cmd span { display: block; }'. + _add '.repo_tab td.cmd a { display: block; }'. + _add 'td.current_dir { color: #ccc; }'. ENDMETHOD. "styles @@ -846,6 +483,15 @@ CLASS lcl_gui_page_main IMPLEMENTATION. && 't2jg3Q5rgASaF3KNRwAAAABJRU5ErkJggg=='. APPEND ls_image TO rt_assets. + ls_image-url = 'img/dir' ##NO_TEXT. + ls_image-content = + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAASFBMVEUAAABmksxmksxm' + && 'ksxmksxmksxmksxmksxmksxmksxmksxmksxmksxmksxmksxmksxmksxmksxmksxmksxm' + && 'ksxmksxmksxmksxMwQo8AAAAF3RSTlMABhIYIy1fZmhpe3+IiYuMkZvD7e/x93sipD4A' + && 'AAA+SURBVBhXY2BABzwiokAgzAYXEGdiBAIWIYQAPzcQCApzgwEXM4M4KuBDFxAYKAEx' + && 'VAFeBlYOTiTAzoThewD5hBAcnWM4gwAAAABJRU5ErkJggg=='. + APPEND ls_image TO rt_assets. + ENDMETHOD. "get_assets ENDCLASS. \ No newline at end of file diff --git a/src/zabapgit_page_stage.prog.abap b/src/zabapgit_page_stage.prog.abap index c0b13a82e..248cf4ce0 100644 --- a/src/zabapgit_page_stage.prog.abap +++ b/src/zabapgit_page_stage.prog.abap @@ -108,9 +108,9 @@ CLASS lcl_gui_page_stage IMPLEMENTATION. LOOP AT lt_fields ASSIGNING . - lcl_url=>split_file_location( EXPORTING iv_fullpath = -name - IMPORTING ev_path = ls_file-path - ev_filename = ls_file-filename ). + lcl_path=>split_file_location( EXPORTING iv_fullpath = -name + IMPORTING ev_path = ls_file-path + ev_filename = ls_file-filename ). CASE -value. WHEN lcl_stage=>c_method-add. diff --git a/src/zabapgit_persistence.prog.abap b/src/zabapgit_persistence.prog.abap index 159618316..a16349ade 100644 --- a/src/zabapgit_persistence.prog.abap +++ b/src/zabapgit_persistence.prog.abap @@ -404,12 +404,21 @@ CLASS lcl_persistence_user DEFINITION FINAL CREATE PRIVATE FRIENDS lcl_app. RAISING lcx_exception. METHODS toggle_hide_files + RETURNING VALUE(rv_hide) TYPE abap_bool RAISING lcx_exception. METHODS get_hide_files RETURNING VALUE(rv_hide) TYPE abap_bool RAISING lcx_exception. + METHODS toggle_changes_only + RETURNING VALUE(rv_changes_only) TYPE abap_bool + RAISING lcx_exception. + + METHODS get_changes_only + RETURNING VALUE(rv_changes_only) TYPE abap_bool + RAISING lcx_exception. + PRIVATE SECTION. CONSTANTS c_type_user TYPE lcl_persistence_db=>ty_type VALUE 'USER'. @@ -428,11 +437,12 @@ CLASS lcl_persistence_user DEFINITION FINAL CREATE PRIVATE FRIENDS lcl_app. TYPES: ty_repo_config_tt TYPE STANDARD TABLE OF ty_repo_config WITH DEFAULT KEY. TYPES: BEGIN OF ty_user, - username TYPE string, - email TYPE string, - repo_show TYPE lcl_persistence_repo=>ty_repo-key, - repo_config TYPE ty_repo_config_tt, - hide_files TYPE abap_bool, + username TYPE string, + email TYPE string, + repo_show TYPE lcl_persistence_repo=>ty_repo-key, + repo_config TYPE ty_repo_config_tt, + hide_files TYPE abap_bool, + changes_only TYPE abap_bool, END OF ty_user. METHODS constructor @@ -648,6 +658,8 @@ CLASS lcl_persistence_user IMPLEMENTATION. ls_user-hide_files = boolc( ls_user-hide_files = abap_false ). update( ls_user ). + rv_hide = ls_user-hide_files. + ENDMETHOD. "toggle_hide_files METHOD get_hide_files. @@ -656,6 +668,25 @@ CLASS lcl_persistence_user IMPLEMENTATION. ENDMETHOD. "get_hide_files + METHOD toggle_changes_only. + + DATA ls_user TYPE ty_user. + + ls_user = read( ). + ls_user-changes_only = boolc( ls_user-changes_only = abap_false ). + update( ls_user ). + + rv_changes_only = ls_user-changes_only. + + ENDMETHOD. "toggle_changes_only + + METHOD get_changes_only. + + rv_changes_only = read( )-changes_only. + + ENDMETHOD. "get_changes_only + + ENDCLASS. CLASS lcl_persistence_db IMPLEMENTATION. diff --git a/src/zabapgit_unit_test.prog.abap b/src/zabapgit_unit_test.prog.abap index df226946d..9c8f61b24 100644 --- a/src/zabapgit_unit_test.prog.abap +++ b/src/zabapgit_unit_test.prog.abap @@ -1617,4 +1617,133 @@ CLASS ltcl_html_action_utils IMPLEMENTATION. ENDMETHOD. "get_field -ENDCLASS. "ltcl_html_action_utils \ No newline at end of file +ENDCLASS. "ltcl_html_action_utils + +CLASS ltcl_path DEFINITION + FOR TESTING RISK LEVEL HARMLESS DURATION SHORT FINAL + INHERITING FROM CL_AUNIT_ASSERT. + + PUBLIC SECTION. + METHODS is_root FOR TESTING. + METHODS split_file_location FOR TESTING. + METHODS is_subdir FOR TESTING. + METHODS change_dir FOR TESTING. + +ENDCLASS. "ltcl_path + +CLASS ltcl_path IMPLEMENTATION. + + + METHOD is_root. + + assert_equals( exp = abap_true act = lcl_path=>is_root( '/' ) ). + assert_equals( exp = abap_false act = lcl_path=>is_root( '' ) ). + assert_equals( exp = abap_false act = lcl_path=>is_root( 'somedir' ) ). + assert_equals( exp = abap_false act = lcl_path=>is_root( '/somedir' ) ). + + ENDMETHOD. + + METHOD split_file_location. + + DATA: lv_path TYPE string, + lv_name TYPE string. + + lcl_path=>split_file_location( EXPORTING iv_fullpath = '' + IMPORTING ev_path = lv_path ev_filename = lv_name ). + assert_equals( act = lv_path exp = '' ). + assert_equals( act = lv_name exp = '' ). + + lcl_path=>split_file_location( EXPORTING iv_fullpath = 'somefile' + IMPORTING ev_path = lv_path ev_filename = lv_name ). + assert_equals( act = lv_path exp = '' ). + assert_equals( act = lv_name exp = 'somefile' ). + + lcl_path=>split_file_location( EXPORTING iv_fullpath = '/' + IMPORTING ev_path = lv_path ev_filename = lv_name ). + assert_equals( act = lv_path exp = '/' ). + assert_equals( act = lv_name exp = '' ). + + lcl_path=>split_file_location( EXPORTING iv_fullpath = '/somefile' + IMPORTING ev_path = lv_path ev_filename = lv_name ). + assert_equals( act = lv_path exp = '/' ). + assert_equals( act = lv_name exp = 'somefile' ). + + lcl_path=>split_file_location( EXPORTING iv_fullpath = '/somedir/' + IMPORTING ev_path = lv_path ev_filename = lv_name ). + assert_equals( act = lv_path exp = '/somedir/' ). + assert_equals( act = lv_name exp = '' ). + + lcl_path=>split_file_location( EXPORTING iv_fullpath = '/somedir/somefile' + IMPORTING ev_path = lv_path ev_filename = lv_name ). + assert_equals( act = lv_path exp = '/somedir/' ). + assert_equals( act = lv_name exp = 'somefile' ). + + + ENDMETHOD. + + METHOD is_subdir. + + DATA lv_yes TYPE abap_bool. + + lv_yes = lcl_path=>is_subdir( iv_path = '/dir/subdir' + iv_parent = '/dir' ). + assert_equals( act = lv_yes exp = abap_true ). + + lv_yes = lcl_path=>is_subdir( iv_path = '/dir/subdir' + iv_parent = '/dir/' ). + assert_equals( act = lv_yes exp = abap_true ). + + lv_yes = lcl_path=>is_subdir( iv_path = '/another' + iv_parent = '/dir' ). + assert_equals( act = lv_yes exp = abap_false ). + + lv_yes = lcl_path=>is_subdir( iv_path = '/dir' + iv_parent = '/dir' ). + assert_equals( act = lv_yes exp = abap_false ). + + lv_yes = lcl_path=>is_subdir( iv_path = '/dir' + iv_parent = '/' ). + assert_equals( act = lv_yes exp = abap_true ). + + lv_yes = lcl_path=>is_subdir( iv_path = '/dir2' + iv_parent = '/dir' ). + assert_equals( act = lv_yes exp = abap_false ). + + ENDMETHOD. + + METHOD change_dir. + + DATA lv_path TYPE string. + + lv_path = lcl_path=>change_dir( iv_cur_dir = '' + iv_cd = '' ). + assert_equals( act = lv_path exp = '' ). + + lv_path = lcl_path=>change_dir( iv_cur_dir = '/dir' + iv_cd = '' ). + assert_equals( act = lv_path exp = '/dir' ). + + lv_path = lcl_path=>change_dir( iv_cur_dir = '/dir' + iv_cd = '.' ). + assert_equals( act = lv_path exp = '/dir' ). + + lv_path = lcl_path=>change_dir( iv_cur_dir = '/dir' + iv_cd = '..' ). + assert_equals( act = lv_path exp = '/' ). + + lv_path = lcl_path=>change_dir( iv_cur_dir = '/dir/sub' + iv_cd = '..' ). + assert_equals( act = lv_path exp = '/dir/' ). + + lv_path = lcl_path=>change_dir( iv_cur_dir = '/dir/' + iv_cd = 'sub' ). + assert_equals( act = lv_path exp = '/dir/sub' ). + + lv_path = lcl_path=>change_dir( iv_cur_dir = '/dir' + iv_cd = 'sub' ). + assert_equals( act = lv_path exp = '/dir/sub' ). + + + ENDMETHOD. + +ENDCLASS. "ltcl_path \ No newline at end of file diff --git a/src/zabapgit_util.prog.abap b/src/zabapgit_util.prog.abap index 7b0ceccd2..9672d95e1 100644 --- a/src/zabapgit_util.prog.abap +++ b/src/zabapgit_util.prog.abap @@ -337,6 +337,108 @@ CLASS lcl_hash IMPLEMENTATION. ENDCLASS. "lcl_hash IMPLEMENTATION +CLASS lcl_path DEFINITION FINAL. + + PUBLIC SECTION. + + CLASS-METHODS split_file_location + IMPORTING iv_fullpath TYPE string + EXPORTING ev_path TYPE string + ev_filename TYPE string. + + CLASS-METHODS is_root + IMPORTING iv_path TYPE string + RETURNING VALUE(rv_yes) TYPE abap_bool. + + CLASS-METHODS is_subdir + IMPORTING iv_path TYPE string + iv_parent TYPE string + RETURNING VALUE(rv_yes) TYPE abap_bool. + + CLASS-METHODS change_dir + IMPORTING iv_cur_dir TYPE string + iv_cd TYPE string + RETURNING VALUE(rv_path) TYPE string. + +ENDCLASS. "lcl_path + +CLASS lcl_path IMPLEMENTATION. + + METHOD split_file_location. + + DATA: lv_cnt TYPE i, + lv_off TYPE i, + lv_len TYPE i. + + FIND FIRST OCCURRENCE OF REGEX '^/(.*/)?' IN iv_fullpath + MATCH COUNT lv_cnt + MATCH OFFSET lv_off + MATCH LENGTH lv_len. + + IF lv_cnt > 0. + ev_path = iv_fullpath+0(lv_len). + ev_filename = iv_fullpath+lv_len. + ELSE. + CLEAR ev_path. + ev_filename = iv_fullpath. + ENDIF. + + ENDMETHOD. "split_file_location + + METHOD is_root. + rv_yes = boolc( iv_path = '/' ). + ENDMETHOD. "is_root + + METHOD is_subdir. + + DATA lv_len TYPE i. + DATA lv_last TYPE i. + + lv_len = strlen( iv_parent ). + lv_last = lv_len - 1. + rv_yes = boolc( strlen( iv_path ) > lv_len + AND iv_path+0(lv_len) = iv_parent + AND ( iv_parent+lv_last(1) = '/' OR iv_path+lv_Len(1) = '/' ) ). + + ENDMETHOD. "is_subdir + + METHOD change_dir. + + DATA lv_last TYPE i. + DATA lv_temp TYPE string. + DATA lv_len TYPE i. + + lv_last = strlen( iv_cur_dir ) - 1. + + IF iv_cd = '' OR iv_cd = '.'. " No change + rv_path = iv_cur_dir. + ELSEIF iv_cd+0(1) = '/'. " Absolute path + rv_path = iv_cd. + ELSEIF iv_cd = '..'. " CD back + IF iv_cur_dir = '/' OR iv_cur_dir = ''. " Back from root = root + rv_path = iv_cur_dir. + ELSE. + lv_temp = reverse( iv_cur_dir ). + IF lv_temp+0(1) = '/'. + SHIFT lv_temp BY 1 PLACES LEFT. + ENDIF. + SHIFT lv_temp UP TO '/' LEFT. + rv_path = reverse( lv_temp ). + ENDIF. + ELSE. + IF iv_cur_dir+lv_last(1) = '/'. " Append cd to cur_dir separated by / + rv_path = iv_cur_dir && iv_cd. + ELSE. + rv_path = iv_cur_dir && '/' && iv_cd. + ENDIF. + ENDIF. + + " TODO: improve logic and cases + + ENDMETHOD. "change_dir + +ENDCLASS. "lcl_path + *----------------------------------------------------------------------* * CLASS lcl_url DEFINITION *----------------------------------------------------------------------* @@ -360,11 +462,6 @@ CLASS lcl_url DEFINITION FINAL. RETURNING VALUE(rv_path_name) TYPE string RAISING lcx_exception. - CLASS-METHODS split_file_location - IMPORTING iv_fullpath TYPE string - EXPORTING ev_path TYPE string - ev_filename TYPE string. - PRIVATE SECTION. CLASS-METHODS regex IMPORTING iv_repo TYPE string @@ -382,27 +479,6 @@ ENDCLASS. "lcl_repo DEFINITION *----------------------------------------------------------------------* CLASS lcl_url IMPLEMENTATION. - METHOD split_file_location. - - DATA: lv_cnt TYPE i, - lv_off TYPE i, - lv_len TYPE i. - - FIND FIRST OCCURRENCE OF REGEX '^/(.*/)?' IN iv_fullpath - MATCH COUNT lv_cnt - MATCH OFFSET lv_off - MATCH LENGTH lv_len. - - IF lv_cnt > 0. - ev_path = iv_fullpath+0(lv_len). - ev_filename = iv_fullpath+lv_len. - ELSE. - CLEAR ev_path. - ev_filename = iv_fullpath. - ENDIF. - - ENDMETHOD. "split_file_location - METHOD host. regex( EXPORTING iv_repo = iv_repo IMPORTING ev_host = rv_host ). diff --git a/src/zabapgit_view_repo.prog.abap b/src/zabapgit_view_repo.prog.abap new file mode 100644 index 000000000..1c8d5b091 --- /dev/null +++ b/src/zabapgit_view_repo.prog.abap @@ -0,0 +1,690 @@ +*&---------------------------------------------------------------------* +*& Include ZABAPGIT_VIEW_REPO +*&---------------------------------------------------------------------* + +CLASS lcl_repo_content_browser DEFINITION FINAL. + + PUBLIC SECTION. + + CONSTANTS: BEGIN OF c_sortkey, + default TYPE i VALUE 9999, + parent_dir TYPE i VALUE 0, + dir TYPE i VALUE 1, + wo_obj TYPE i VALUE 2, + new TYPE i VALUE 3, + changed TYPE i VALUE 4, + END OF c_sortkey. + + TYPES: BEGIN OF ty_repo_item, + obj_type TYPE tadir-object, + obj_name TYPE tadir-obj_name, + sortkey TYPE i, + path TYPE string, + is_dir TYPE abap_bool, + changes TYPE i, + files TYPE tt_repo_files, + END OF ty_repo_item. + TYPES tt_repo_items TYPE STANDARD TABLE OF ty_repo_item WITH DEFAULT KEY. + + METHODS constructor + IMPORTING io_repo TYPE REF TO lcl_repo. + + METHODS list + IMPORTING iv_path TYPE string + iv_by_folders TYPE abap_bool + iv_changes_only TYPE abap_bool + RETURNING VALUE(rt_repo_items) TYPE tt_repo_items + RAISING lcx_exception. + + METHODS get_log + RETURNING VALUE(ro_log) TYPE REF TO lcl_log. + + PRIVATE SECTION. + DATA mo_repo TYPE REF TO lcl_repo. + DATA mo_log TYPE REF TO lcl_log. + + METHODS get_local + RETURNING VALUE(rt_repo_items) TYPE tt_repo_items + RAISING lcx_exception. + + METHODS get_remote + RETURNING VALUE(rt_repo_items) TYPE tt_repo_items + RAISING lcx_exception. + + METHODS build_folders + IMPORTING iv_cur_dir TYPE string + CHANGING ct_repo_items TYPE tt_repo_items + RAISING lcx_exception. + + METHODS filter_changes + CHANGING ct_repo_items TYPE tt_repo_items. + +ENDCLASS. "lcl_repo_content_browser + +CLASS lcl_repo_content_browser IMPLEMENTATION. + + METHOD constructor. + mo_repo = io_repo. + ENDMETHOD. "constructor + + METHOD get_log. + ro_log = mo_log. + ENDMETHOD. "get_log + + METHOD list. + + CREATE OBJECT mo_log. + + IF mo_repo->is_offline( ) = abap_true. + rt_repo_items = get_local( ). + ELSE. + rt_repo_items = get_remote( ). + ENDIF. + + IF iv_by_folders = abap_true. + build_folders( + EXPORTING iv_cur_dir = iv_path + CHANGING ct_repo_items = rt_repo_items ). + ENDIF. + + IF iv_changes_only = abap_true. + filter_changes( CHANGING ct_repo_items = rt_repo_items ). + ENDIF. + + SORT rt_repo_items BY sortkey obj_type obj_name ASCENDING. + + ENDMETHOD. "list + + METHOD build_folders. + + DATA: lv_index TYPE i, + lt_folders LIKE ct_repo_items, + ls_folder LIKE LINE OF ct_repo_items. + + FIELD-SYMBOLS LIKE LINE OF ct_repo_items. + + LOOP AT ct_repo_items ASSIGNING . + lv_index = sy-tabix. + CHECK -path <> iv_cur_dir. " files in target dir - just leave them be + + IF lcl_path=>is_subdir( iv_path = -path iv_parent = iv_cur_dir ) = abap_true. + ls_folder-changes = -changes. + ls_folder-path = -path. + APPEND ls_folder TO lt_folders. + ENDIF. + + DELETE ct_repo_items INDEX lv_index. + ENDLOOP. + + SORT lt_folders BY path. + + LOOP AT lt_folders ASSIGNING . + AT NEW path. + CLEAR ls_folder. + ls_folder-path = -path. + ls_folder-sortkey = c_sortkey-dir. " Directory + ls_folder-is_dir = abap_true. + ENDAT. + + ls_folder-changes = ls_folder-changes + -changes. + + AT END OF path. + APPEND ls_folder TO ct_repo_items. + ENDAT. + ENDLOOP. + + ENDMETHOD. "build_folders + + METHOD filter_changes. + + DATA lt_repo_temp LIKE ct_repo_items. + + FIELD-SYMBOLS LIKE LINE OF ct_repo_items. + + LOOP AT ct_repo_items ASSIGNING . + CHECK -changes > 0. + APPEND TO lt_repo_temp. + ENDLOOP. + + IF lines( lt_repo_temp ) > 0. " Prevent showing empty package if no changes, show all + ct_repo_items = lt_repo_temp. + ENDIF. + + ENDMETHOD. "filter_changes + + METHOD get_local. + + DATA: lt_tadir TYPE ty_tadir_tt. + + FIELD-SYMBOLS: LIKE LINE OF rt_repo_items, + LIKE LINE OF lt_tadir. + + lt_tadir = lcl_tadir=>read( mo_repo->get_package( ) ). + LOOP AT lt_tadir ASSIGNING . + APPEND INITIAL LINE TO rt_repo_items ASSIGNING . + -obj_type = -object. + -obj_name = -obj_name. + -path = '/' && -path. " Add root anchor + -sortkey = c_sortkey-default. " Default sort key + ENDLOOP. + + ENDMETHOD. "get_local + + METHOD get_remote. + + DATA: lo_repo_online TYPE REF TO lcl_repo_online, + ls_file TYPE ty_repo_file, + lt_results TYPE ty_results_tt. + + FIELD-SYMBOLS: LIKE LINE OF lt_results, + LIKE LINE OF rt_repo_items. + + lo_repo_online ?= mo_repo. + lt_results = lo_repo_online->status( mo_log ). + + LOOP AT lt_results ASSIGNING . + AT NEW obj_name. "obj_type + obj_name + APPEND INITIAL LINE TO rt_repo_items ASSIGNING . + -obj_type = -obj_type. + -obj_name = -obj_name. + -sortkey = c_sortkey-default. " Default sort key + -changes = 0. + -path = -path. + ENDAT. + + IF -filename IS NOT INITIAL. + ls_file-path = -path. + ls_file-filename = -filename. + ls_file-is_changed = boolc( NOT -match = abap_true ). + ls_file-new = -new. + APPEND ls_file TO -files. + + IF ls_file-is_changed = abap_true OR ls_file-new IS NOT INITIAL. + -sortkey = c_sortkey-changed. " Changed files + -changes = -changes + 1. + ENDIF. + ENDIF. + + AT END OF obj_name. "obj_type + obj_name + IF -obj_type IS INITIAL. + -sortkey = c_sortkey-wo_obj. "Virtual objects + ELSEIF lines( -files ) = 0. + -sortkey = c_sortkey-new. "New object to commit + ENDIF. + ENDAT. + ENDLOOP. + + ENDMETHOD. "get_remote + +ENDCLASS. "lcl_repo_content_browser + +********************************************************************** +********************************************************************** + +CLASS lcl_gui_view_repo_content DEFINITION FINAL INHERITING FROM lcl_gui_page_super. + PUBLIC SECTION. + + CONSTANTS: BEGIN OF c_actions, + change_dir TYPE string VALUE 'change_dir' ##NO_TEXT, + toggle_hide_files TYPE string VALUE 'toggle_hide_files' ##NO_TEXT, + toggle_folders TYPE string VALUE 'toggle_folders' ##NO_TEXT, + toggle_changes TYPE string VALUE 'toggle_changes' ##NO_TEXT, + END OF c_actions. + + METHODS: lif_gui_page~render REDEFINITION, + lif_gui_page~on_event REDEFINITION. + + METHODS constructor + IMPORTING iv_key TYPE lcl_persistence_repo=>ty_repo-key + RAISING lcx_exception. + + PRIVATE SECTION. + + DATA: mo_repo TYPE REF TO lcl_repo, + mv_cur_dir TYPE string, + mv_hide_files TYPE abap_bool, + mv_show_folders TYPE abap_bool, + mv_changes_only TYPE abap_bool. + + METHODS: + render_repo_menu + RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper + RAISING lcx_exception, + render_tab_menu + RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper + RAISING lcx_exception, + render_repo_item + IMPORTING is_item TYPE lcl_repo_content_browser=>ty_repo_item + RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper + RAISING lcx_exception, + get_item_class + IMPORTING is_item TYPE lcl_repo_content_browser=>ty_repo_item + RETURNING VALUE(rv_html) TYPE string, + get_item_icon + IMPORTING is_item TYPE lcl_repo_content_browser=>ty_repo_item + RETURNING VALUE(rv_html) TYPE string, + render_empty_package + RETURNING VALUE(rv_html) TYPE string, + render_parent_dir_line + RETURNING VALUE(ro_html) TYPE REF TO lcl_html_helper + RAISING lcx_exception. + + METHODS: + build_obj_jump_link + IMPORTING iv_obj_type TYPE tadir-object + iv_obj_name TYPE tadir-obj_name + RETURNING VALUE(rv_html) TYPE string, + build_dir_jump_link + IMPORTING iv_path TYPE string + RETURNING VALUE(rv_html) TYPE string. + +ENDCLASS. "lcl_gui_view_repo_content + +CLASS lcl_gui_view_repo_content IMPLEMENTATION. + + METHOD constructor. + + super->constructor( ). + + mo_repo = lcl_app=>repo_srv( )->get( iv_key ). + mv_cur_dir = '/'. " Root + mv_hide_files = lcl_app=>user( )->get_hide_files( ). + mv_changes_only = lcl_app=>user( )->get_changes_only( ). + + ENDMETHOD. "constructor + + METHOD lif_gui_page~on_event. + + DATA: lv_path TYPE string. + + CASE iv_action. + WHEN c_actions-toggle_hide_files. " Toggle file diplay + mv_hide_files = lcl_app=>user( )->toggle_hide_files( ). + ev_state = gc_event_state-re_render. + WHEN c_actions-change_dir. " Change dir + lv_path = lcl_html_action_utils=>dir_decode( iv_getdata ). + mv_cur_dir = lcl_path=>change_dir( iv_cur_dir = mv_cur_dir iv_cd = lv_path ). + ev_state = gc_event_state-re_render. + WHEN c_actions-toggle_folders. " Toggle folder view + mv_show_folders = boolc( mv_show_folders <> abap_true ). + mv_cur_dir = '/'. " Root + ev_state = gc_event_state-re_render. + WHEN c_actions-toggle_changes. " Toggle changes only view + mv_changes_only = lcl_app=>user( )->toggle_changes_only( ). + ev_state = gc_event_state-re_render. + ENDCASE. + + ENDMETHOD. "lif_gui_page~on_event + + METHOD lif_gui_page~render. + + DATA: lt_repo_items TYPE lcl_repo_content_browser=>tt_repo_items, + lo_browser TYPE REF TO lcl_repo_content_browser, + lx_error TYPE REF TO lcx_exception, + lo_log TYPE REF TO lcl_log. + + FIELD-SYMBOLS LIKE LINE OF lt_repo_items. + + " Reinit, for the case of type change + mo_repo = lcl_app=>repo_srv( )->get( mo_repo->get_key( ) ). + + CREATE OBJECT ro_html. + + TRY. + ro_html->add( render_repo_menu( ) ). + + CREATE OBJECT lo_browser EXPORTING io_repo = mo_repo. + lt_repo_items = lo_browser->list( iv_path = mv_cur_dir + iv_by_folders = mv_show_folders + iv_changes_only = mv_changes_only ). + + lo_log = lo_browser->get_log( ). + IF mo_repo->is_offline( ) = abap_false and lo_log->count( ) > 0. + ro_html->add( '
' ). + ro_html->add( lo_log->to_html( ) ). " shows eg. list of unsupported objects + ro_html->add( '
' ). + ENDIF. + + ro_html->add( '
' ). + ro_html->add( render_tab_menu( ) ). + + " Repo content table + ro_html->add( '' ). + + IF lcl_path=>is_root( mv_cur_dir ) = abap_false. + ro_html->add( render_parent_dir_line( ) ). + ENDIF. + + IF lines( lt_repo_items ) = 0. + ro_html->add( render_empty_package( ) ). + ELSE. + LOOP AT lt_repo_items ASSIGNING . + ro_html->add( render_repo_item( ) ). + ENDLOOP. + ENDIF. + + ro_html->add( '
' ). + ro_html->add( '
' ). + + CATCH lcx_exception INTO lx_error. + ro_html->add( render_repo_menu( ) ). + ro_html->add( lcl_gui_page_super=>render_error( lx_error ) ). + ENDTRY. + + ENDMETHOD. "lif_gui_page~render + + METHOD render_tab_menu. + + DATA lo_tab_menu TYPE REF TO lcl_html_toolbar. + + CREATE OBJECT lo_tab_menu. + + IF mo_repo->is_offline( ) = abap_false. + + " Show/Hide files + IF mv_hide_files = abap_true. + lo_tab_menu->add( iv_txt = 'Show files' iv_act = c_actions-toggle_hide_files ). + ELSE. + lo_tab_menu->add( iv_txt = 'Hide files' iv_act = c_actions-toggle_hide_files ). + ENDIF. + + " Show changes only + IF mv_changes_only = abap_true. + lo_tab_menu->add( iv_txt = 'All objects' iv_act = c_actions-toggle_changes ). + ELSE. + lo_tab_menu->add( iv_txt = 'Changed only' iv_act = c_actions-toggle_changes ). + ENDIF. + + ENDIF. + + " Show/Hide folders + IF mv_show_folders = abap_true. + lo_tab_menu->add( iv_txt = 'Plain list' iv_act = c_actions-toggle_folders ). + ELSE. + lo_tab_menu->add( iv_txt = 'With folders' iv_act = c_actions-toggle_folders ). + ENDIF. + + ro_html = lo_tab_menu->render( iv_as_angle = abap_true ). + + ENDMETHOD. "render_tab_menu + + METHOD render_repo_menu. + + DATA: lo_toolbar TYPE REF TO lcl_html_toolbar, + lo_tb_advanced TYPE REF TO lcl_html_toolbar, + lo_tb_branch TYPE REF TO lcl_html_toolbar, + lv_key TYPE lcl_persistence_db=>ty_value, + lv_wp_opt LIKE gc_html_opt-crossout, + lv_pull_opt LIKE gc_html_opt-crossout, + lo_repo_online TYPE REF TO lcl_repo_online. + + CREATE OBJECT ro_html. + CREATE OBJECT lo_toolbar. + CREATE OBJECT lo_tb_branch. + CREATE OBJECT lo_tb_advanced. + + lv_key = mo_repo->get_key( ). + IF mo_repo->is_offline( ) = abap_false. + lo_repo_online ?= mo_repo. + ENDIF. + + IF mo_repo->is_write_protected( ) = abap_true. + lv_wp_opt = gc_html_opt-crossout. + lv_pull_opt = gc_html_opt-crossout. + ELSE. + lv_pull_opt = gc_html_opt-emphas. + ENDIF. + + " Build branch drop-down ======================== + IF mo_repo->is_offline( ) = abap_false. " Online ? + lo_tb_branch->add( iv_txt = 'Overview' + iv_act = |{ gc_action-go_branch_overview }?{ lv_key }| ). + lo_tb_branch->add( iv_txt = 'Switch' + iv_act = |{ gc_action-git_branch_switch }?{ lv_key }| + iv_opt = lv_wp_opt ). + lo_tb_branch->add( iv_txt = 'Create' + iv_act = |{ gc_action-git_branch_create }?{ lv_key }| ). + lo_tb_branch->add( iv_txt = 'Delete' + iv_act = |{ gc_action-git_branch_delete }?{ lv_key }| ). + ENDIF. + + " Build advanced drop-down ======================== + IF mo_repo->is_offline( ) = abap_false. " Online ? + lo_tb_advanced->add( iv_txt = 'Reset local' + iv_act = |{ gc_action-git_reset }?{ lv_key }| + iv_opt = lv_wp_opt ). + lo_tb_advanced->add( iv_txt = 'Background mode' + iv_act = |{ gc_action-go_background }?{ lv_key }| ). + lo_tb_advanced->add( iv_txt = 'Change remote' + iv_act = |{ gc_action-repo_remote_change }?{ lv_key }| ). + lo_tb_advanced->add( iv_txt = 'Make off-line' + iv_act = |{ gc_action-repo_remote_detach }?{ lv_key }| ). + ELSE. + lo_tb_advanced->add( iv_txt = 'Make on-line' + iv_act = |{ gc_action-repo_remote_attach }?{ lv_key }| ). + ENDIF. + lo_tb_advanced->add( iv_txt = 'Remove' + iv_act = |{ gc_action-repo_remove }?{ lv_key }| ). + lo_tb_advanced->add( iv_txt = 'Uninstall' + iv_act = |{ gc_action-repo_purge }?{ lv_key }| + iv_opt = lv_wp_opt ). + + " Build main toolbar ============================== + IF mo_repo->is_offline( ) = abap_false. " Online ? + TRY. + IF lo_repo_online->get_sha1_remote( ) <> lo_repo_online->get_sha1_local( ). + lo_toolbar->add( iv_txt = 'Pull' + iv_act = |{ gc_action-git_pull }?{ lv_key }| + iv_opt = lv_pull_opt ). + ENDIF. + IF lcl_stage_logic=>count( lo_repo_online ) > 0. + lo_toolbar->add( iv_txt = 'Stage' + iv_act = |{ gc_action-go_stage }?{ lv_key }| + iv_opt = gc_html_opt-emphas ). + ENDIF. + CATCH lcx_exception ##NO_HANDLER. + " authorization error or repository does not exist + " ignore error + ENDTRY. + lo_toolbar->add( iv_txt = 'Branch' + io_sub = lo_tb_branch ) ##NO_TEXT. + ELSE. + lo_toolbar->add( iv_txt = 'Import ZIP' + iv_act = |{ gc_action-zip_import }?{ lv_key }| + iv_opt = gc_html_opt-emphas ). + lo_toolbar->add( iv_txt = 'Export ZIP' + iv_act = |{ gc_action-zip_export }?{ lv_key }| + iv_opt = gc_html_opt-emphas ). + ENDIF. + + lo_toolbar->add( iv_txt = 'Advanced' + io_sub = lo_tb_advanced ) ##NO_TEXT. + lo_toolbar->add( iv_txt = 'Refresh' + iv_act = |{ gc_action-repo_refresh }?{ lv_key }| ). + + " Render ========================================== + ro_html->add( '
' ). + ro_html->add( '' ). + ro_html->add( || ). + ro_html->add( '' ). + ro_html->add( '
{ mv_cur_dir }' ). + ro_html->add( lo_toolbar->render( ) ). + ro_html->add( '
' ). + ro_html->add( '
' ). + + + ENDMETHOD. "render_repo_menu + + METHOD get_item_class. + + DATA lt_class TYPE TABLE OF string. + + "TODO REFACTOR !!! Depends on if folder woth changes should be highlited + + IF is_item-is_dir = abap_true. + APPEND 'folder' TO lt_class. + ElSEIF is_item-changes > 0. + APPEND 'modified' TO lt_class. + ELSEIF is_item-obj_name IS INITIAL. + APPEND 'unsupported' TO lt_class. + ENDIF. + + IF lines( lt_class ) > 0. + rv_html = | class="{ concat_lines_of( table = lt_class sep = ` ` ) }"|. + ENDIF. + + ENDMETHOD. "get_item_class + + METHOD get_item_icon. + + CASE is_item-obj_type. + WHEN 'PROG' OR 'CLAS' OR 'FUGR'. + rv_html = ||. + WHEN 'W3MI' OR 'W3HT'. + rv_html = ||. + WHEN ''. + rv_html = space. " no icon + WHEN OTHERS. + rv_html = ||. + ENDCASE. + + IF is_item-is_dir = abap_true. + rv_html = ||. + ENDIF. + + ENDMETHOD. "get_item_icon + + + METHOD render_repo_item. + DATA: + lv_link TYPE string, + lv_difflink TYPE string, + ls_file LIKE LINE OF is_item-files. + + CREATE OBJECT ro_html. + + + ro_html->add( || ). + + IF is_item-obj_name IS INITIAL AND is_item-is_dir = abap_false. + ro_html->add( '' + && 'non-code and meta files' ). + ELSEIF is_item-is_dir = abap_true. + lv_link = build_dir_jump_link( iv_path = is_item-path ). + ro_html->add( |{ get_item_icon( is_item ) }| ). + ro_html->add( |{ lv_link }| ). + ELSE. + lv_link = build_obj_jump_link( iv_obj_name = is_item-obj_name + iv_obj_type = is_item-obj_type ). + ro_html->add( |{ get_item_icon( is_item ) }| ). + ro_html->add( |{ is_item-obj_type }| ). + ro_html->add( |{ lv_link }| ). + ENDIF. + + IF mo_repo->is_offline( ) = abap_false. + + " Files + ro_html->add( '' ). + IF mv_hide_files = abap_false OR is_item-obj_type IS INITIAL. + LOOP AT is_item-files INTO ls_file. + ro_html->add( |{ ls_file-path && ls_file-filename }| ). + ENDLOOP. + ENDIF. + ro_html->add( '' ). + + " TODO Refactor + " Command + ro_html->add( '' ). + IF is_item-is_dir = abap_true. + ro_html->add( |{ is_item-changes } changes| ). + ELSEIF lines( is_item-files ) = 0. + ro_html->add( 'new @local' ). + ELSEIF is_item-changes > 0. + IF mv_hide_files = abap_true AND is_item-obj_name IS NOT INITIAL. + lv_difflink = lcl_html_action_utils=>obj_encode( + iv_key = mo_repo->get_key( ) + ig_object = is_item ). + ro_html->add_anchor( + iv_txt = |{ is_item-changes } diffs| + iv_act = |{ gc_action-go_diff }?{ lv_difflink }| ). + ELSE. + LOOP AT is_item-files INTO ls_file. + IF ls_file-new = gc_new-remote. + ro_html->add( 'new @remote' ). + ELSEIF ls_file-new = gc_new-local. + ro_html->add( 'new @local' ). + ELSEIF ls_file-is_changed = abap_true. + lv_difflink = lcl_html_action_utils=>file_encode( + iv_key = mo_repo->get_key( ) + ig_file = ls_file ). + ro_html->add_anchor( + iv_txt = 'diff' + iv_act = |{ gc_action-go_diff }?{ lv_difflink }| ). + ELSE. + ro_html->add( | | ). + ENDIF. + ENDLOOP. + ENDIF. + + ENDIF. + ro_html->add( '' ). + + ENDIF. + + ro_html->add( '' ). + + ENDMETHOD. "render_repo_item + + METHOD render_empty_package. + + rv_html = '' + && '
Empty package
' + && '' ##NO_TEXT. + + ENDMETHOD. "render_empty_package + + METHOD render_parent_dir_line. + + CREATE OBJECT ro_html. + + ro_html->add( '' ). + ro_html->add( || ). + ro_html->add( |{ build_dir_jump_link( '..' ) }| ). + IF mo_repo->is_offline( ) = abap_false. + ro_html->add( || ). " Dummy for online + ENDIF. + ro_html->add( '' ). + + ENDMETHOD. "render_parent_dir_line + + METHOD build_dir_jump_link. + + DATA: lv_path TYPE string, + lv_encode TYPE string, + lo_html TYPE REF TO lcl_html_helper. + + lv_path = iv_path. + REPLACE FIRST OCCURRENCE OF mv_cur_dir IN lv_path WITH ''. + lv_encode = lcl_html_action_utils=>dir_encode( lv_path ). + + CREATE OBJECT lo_html. + lo_html->add_anchor( iv_txt = lv_path iv_act = |{ c_actions-change_dir }?{ lv_encode }| ). + rv_html = lo_html->mv_html. + + ENDMETHOD. "build_dir_jump_link + + METHOD build_obj_jump_link. + + DATA: lv_encode TYPE string, + lo_html TYPE REF TO lcl_html_helper. + + lv_encode = lcl_html_action_utils=>jump_encode( iv_obj_type = iv_obj_type + iv_obj_name = iv_obj_name ). + + CREATE OBJECT lo_html. + lo_html->add_anchor( iv_txt = |{ iv_obj_name }| iv_act = |{ gc_action-jump }?{ lv_encode }| ). + rv_html = lo_html->mv_html. + + ENDMETHOD. "build_obj_jump_link + +ENDCLASS. "lcl_gui_view_repo_content \ No newline at end of file diff --git a/src/zabapgit_view_repo.prog.xml b/src/zabapgit_view_repo.prog.xml new file mode 100644 index 000000000..6da1c7449 --- /dev/null +++ b/src/zabapgit_view_repo.prog.xml @@ -0,0 +1,48 @@ + + + + + + ZABAPGIT_VIEW_REPO + A + + + X + + + + + + I + + + + 0000-00-00 + + 0000-00-00 + + + + + E + + + 0000-00-00 + + 0000-00-00 + + + X + + + + R + + Include ZABAPGIT_VIEW_REPO + 26 + + + + + +