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( ''
- && 'Empty package'
- && ' |
' ) ##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( '
' ).
- 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( |{ mv_cur_dir } | | ).
+ ro_html->add( '' ).
+ ro_html->add( lo_toolbar->render( ) ).
+ ro_html->add( ' | ' ).
+ 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
+
+
+
+
+
+