diff --git a/src/inspect/zcl_abapgit_where_used_tools.clas.abap b/src/inspect/zcl_abapgit_where_used_tools.clas.abap new file mode 100644 index 000000000..084123603 --- /dev/null +++ b/src/inspect/zcl_abapgit_where_used_tools.clas.abap @@ -0,0 +1,442 @@ +CLASS zcl_abapgit_where_used_tools DEFINITION + PUBLIC + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + + TYPES ty_devc_range TYPE RANGE OF tadir-devclass. + TYPES: + BEGIN OF ty_dependency, + package TYPE devclass, + obj_type TYPE tadir-object, + obj_prog_type TYPE trdir-subc, + obj_name TYPE tadir-obj_name, + obj_cls TYPE rsfindlst-object_cls, + dep_package TYPE devclass, + dep_obj_type TYPE tadir-object, + dep_obj_name TYPE tadir-obj_name, + dep_used_cls TYPE rsfindlst-used_cls, + dep_used_obj TYPE rsfindlst-used_obj, + END OF ty_dependency. + TYPES: + ty_dependency_tt TYPE STANDARD TABLE OF ty_dependency WITH DEFAULT KEY. + + CLASS-METHODS new + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_where_used_tools. + + " the initial version of this utility is also available as a standalone tool + " here: https://github.com/sbcgua/crossdeps + METHODS select_external_usages + IMPORTING + iv_package TYPE tadir-devclass + iv_ignore_subpackages TYPE abap_bool DEFAULT abap_false + ir_package_scope TYPE ty_devc_range OPTIONAL + RETURNING + VALUE(rt_objs) TYPE ty_dependency_tt + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + + TYPES: + BEGIN OF ty_obj_signature, + package TYPE devclass, + obj_type TYPE tadir-object, + obj_name TYPE tadir-obj_name, + END OF ty_obj_signature. + + TYPES ty_where_used_tt TYPE STANDARD TABLE OF rsfindlst WITH DEFAULT KEY. + TYPES ty_seu_obj TYPE STANDARD TABLE OF seu_obj WITH DEFAULT KEY. + TYPES: + BEGIN OF ty_dev_object, + type TYPE seu_stype, + tadir TYPE trobjtype, + END OF ty_dev_object. + + DATA mt_object_packages TYPE HASHED TABLE OF ty_obj_signature WITH UNIQUE KEY obj_type obj_name. + DATA mt_dev_obj_cache TYPE HASHED TABLE OF ty_dev_object WITH UNIQUE KEY type. + + METHODS get_where_used + IMPORTING + iv_obj_type TYPE euobj-id + iv_obj_name TYPE tadir-obj_name + it_scope TYPE ty_seu_obj OPTIONAL + ir_package_scope TYPE ty_devc_range OPTIONAL + RETURNING + VALUE(rt_findings) TYPE ty_where_used_tt + RAISING + zcx_abapgit_exception. + + METHODS get_obj_package + IMPORTING + iv_obj_type TYPE tadir-object + iv_obj_name TYPE tadir-obj_name + RETURNING + VALUE(rv_package) TYPE tadir-devclass. + + METHODS get_func_package + IMPORTING + iv_func_name TYPE tadir-obj_name + RETURNING + VALUE(rv_package) TYPE tadir-devclass. + + METHODS get_incl_package + IMPORTING + iv_prog_name TYPE tadir-obj_name + RETURNING + VALUE(rv_package) TYPE tadir-devclass. + + METHODS build_package_scope + IMPORTING + it_tadir TYPE STANDARD TABLE + ir_package_scope TYPE ty_devc_range + RETURNING + VALUE(rt_package_scope) TYPE ty_devc_range. + + METHODS collect_where_used + IMPORTING + it_tadir TYPE STANDARD TABLE + ir_package_scope TYPE ty_devc_range + RETURNING + VALUE(rt_objs) TYPE ty_dependency_tt + RAISING + zcx_abapgit_exception. + + METHODS convert_list + IMPORTING + iv_package TYPE ty_dependency-dep_package + iv_obj_type TYPE ty_dependency-dep_obj_type + iv_obj_name TYPE ty_dependency-dep_obj_name + it_where_used TYPE ty_where_used_tt + RETURNING + VALUE(rt_objs) TYPE ty_dependency_tt. + + METHODS decode_obj_type + IMPORTING + iv_type TYPE rsfindlst-object_cls + RETURNING + VALUE(rv_type) TYPE ty_dev_object-tadir. + +ENDCLASS. + + + +CLASS ZCL_ABAPGIT_WHERE_USED_TOOLS IMPLEMENTATION. + + + METHOD build_package_scope. + + FIELD-SYMBOLS TYPE zif_abapgit_definitions=>ty_tadir. + FIELD-SYMBOLS LIKE LINE OF rt_package_scope. + + rt_package_scope = ir_package_scope. + LOOP AT it_tadir ASSIGNING . + CHECK -object = 'DEVC'. + APPEND INITIAL LINE TO rt_package_scope ASSIGNING . + -sign = 'E'. + -option = 'EQ'. + -low = -obj_name. + ENDLOOP. + + ENDMETHOD. + + + METHOD collect_where_used. + + DATA li_progress TYPE REF TO zif_abapgit_progress. + DATA lt_where_used TYPE ty_where_used_tt. + DATA lt_objs_portion LIKE rt_objs. + + FIELD-SYMBOLS TYPE zif_abapgit_definitions=>ty_tadir. + + li_progress = zcl_abapgit_progress=>get_instance( lines( it_tadir ) ). + + LOOP AT it_tadir ASSIGNING . + CHECK -object <> 'DEVC'. + + li_progress->show( + iv_current = sy-tabix + iv_text = |{ -object } { -obj_name }| ). + + lt_where_used = get_where_used( + iv_obj_type = |{ -object }| + iv_obj_name = -obj_name + ir_package_scope = ir_package_scope ). + + lt_objs_portion = convert_list( + iv_package = -devclass + iv_obj_type = -object + iv_obj_name = -obj_name + it_where_used = lt_where_used ). + + APPEND LINES OF lt_objs_portion TO rt_objs. + + ENDLOOP. + + li_progress->off( ). + + ENDMETHOD. + + + METHOD convert_list. + + " See also CL_FINB_GN_BBI=>GET_CROSSREF + + FIELD-SYMBOLS LIKE LINE OF rt_objs. + FIELD-SYMBOLS LIKE LINE OF it_where_used. + + LOOP AT it_where_used ASSIGNING . + + APPEND INITIAL LINE TO rt_objs ASSIGNING . + -dep_package = iv_package. + -dep_obj_type = iv_obj_type. + -dep_obj_name = iv_obj_name. + + -dep_used_obj = -used_obj. + -dep_used_cls = -used_cls. + + -obj_cls = -object_cls. + -obj_name = -encl_objec. + IF -obj_name IS INITIAL. + -obj_name = -object. + ENDIF. + + IF -object_cls = 'FF'. " Function module + -obj_type = 'FUNC'. + -package = get_func_package( -obj_name ). + + ELSE. + -obj_type = decode_obj_type( -object_cls ). + + -package = get_obj_package( + iv_obj_type = -obj_type + iv_obj_name = -obj_name ). + + IF -package IS INITIAL AND -obj_type = 'CLAS'. + -package = get_obj_package( + iv_obj_type = 'INTF' + iv_obj_name = -obj_name ). + IF -package IS NOT INITIAL. + -obj_type = 'INTF'. + ENDIF. + ENDIF. + ENDIF. + + IF -package IS INITIAL. + IF -obj_type = 'PROG'. " Maybe it is an include + + -package = get_incl_package( -obj_name ). + IF -package IS INITIAL. + SELECT SINGLE subc INTO -obj_prog_type FROM trdir WHERE name = -obj_name. + IF -obj_prog_type IS NOT INITIAL AND -obj_prog_type <> '1'. " Exec. prog + -obj_type = 'INCL'. + ENDIF. + ENDIF. + + ENDIF. + + IF -package IS INITIAL. + -package = '????'. + ENDIF. + ENDIF. + + ENDLOOP. + + " some includes are ENHO ... + " include detection TRDIR, D010INC ??? + " how to find connection with ENHO ? + " Useful: https://github.com/abaplint/abaplint-sci-client/blob/main/src/deps/zcl_abaplint_deps_find.clas.abap + " And cl_wb_manager->if_wb_manager~request_tool_access + " And discussions in https://github.com/abapGit/abapGit/pull/6897 + + ENDMETHOD. + + + METHOD decode_obj_type. + + FIELD-SYMBOLS LIKE LINE OF mt_dev_obj_cache. + + IF mt_dev_obj_cache IS INITIAL. + SELECT type tadir INTO TABLE mt_dev_obj_cache + FROM euobjedit. + ENDIF. + + READ TABLE mt_dev_obj_cache ASSIGNING WITH KEY type = iv_type. + IF sy-subrc = 0. + rv_type = -tadir. + ENDIF. + + ENDMETHOD. + + + METHOD get_func_package. + + " See also: FUNCTION_INCLUDE_INFO, TFDIR, find main program -> get its pkg + + DATA ls_obj_sig LIKE LINE OF mt_object_packages. + + READ TABLE mt_object_packages INTO ls_obj_sig WITH KEY obj_type = 'FUNC' obj_name = iv_func_name. + + IF sy-subrc <> 0. + SELECT SINGLE devclass INTO ls_obj_sig-package + FROM info_func + WHERE funcname = iv_func_name. + IF ls_obj_sig-package IS NOT INITIAL. + ls_obj_sig-obj_type = 'FUNC'. + ls_obj_sig-obj_name = iv_func_name. + INSERT ls_obj_sig INTO TABLE mt_object_packages. + ENDIF. + ENDIF. + + rv_package = ls_obj_sig-package. + + ENDMETHOD. + + + METHOD get_incl_package. + + DATA lv_program TYPE progname. + DATA lv_area TYPE rs38l_area. + + lv_program = iv_prog_name. + + CALL FUNCTION 'FUNCTION_INCLUDE_CONCATENATE' + CHANGING + program = lv_program + complete_area = lv_area + EXCEPTIONS + not_enough_input = 1 + no_function_pool = 2 + delimiter_wrong_position = 3 + OTHERS = 4. + + IF lv_area IS INITIAL. + SELECT SINGLE master FROM d010inc INTO lv_program + WHERE include = iv_prog_name. + + CALL FUNCTION 'FUNCTION_INCLUDE_CONCATENATE' + CHANGING + program = lv_program + complete_area = lv_area + EXCEPTIONS + not_enough_input = 1 + no_function_pool = 2 + delimiter_wrong_position = 3 + OTHERS = 4. + ENDIF. + + IF lv_area IS NOT INITIAL. + rv_package = get_obj_package( + iv_obj_type = 'FUGR' + iv_obj_name = |{ lv_area }| ). + RETURN. + ENDIF. + + " TODO more ... + + ENDMETHOD. + + + METHOD get_obj_package. + + " see also zcl_abapgit_tadir->get_object_package for checks + + DATA ls_obj_sig LIKE LINE OF mt_object_packages. + + READ TABLE mt_object_packages INTO ls_obj_sig WITH KEY obj_type = iv_obj_type obj_name = iv_obj_name. + + IF sy-subrc <> 0. + ls_obj_sig-package = zcl_abapgit_factory=>get_tadir( )->read_single( + iv_object = iv_obj_type + iv_obj_name = iv_obj_name )-devclass. + IF ls_obj_sig-package IS NOT INITIAL. + ls_obj_sig-obj_type = iv_obj_type. + ls_obj_sig-obj_name = iv_obj_name. + INSERT ls_obj_sig INTO TABLE mt_object_packages. + ENDIF. + ENDIF. + + rv_package = ls_obj_sig-package. + + ENDMETHOD. + + + METHOD get_where_used. + + DATA lt_findstrings TYPE string_table. + DATA lt_scope LIKE it_scope. + DATA lv_findstring LIKE LINE OF lt_findstrings. + + IF iv_obj_name IS INITIAL. + RETURN. + ENDIF. + + lt_scope = it_scope. + + lv_findstring = iv_obj_name. + INSERT lv_findstring INTO TABLE lt_findstrings. + + CALL FUNCTION 'RS_EU_CROSSREF' + EXPORTING + i_find_obj_cls = iv_obj_type + no_dialog = abap_true + without_text = abap_true + TABLES + i_findstrings = lt_findstrings + o_founds = rt_findings + i_scope_object_cls = lt_scope + i_scope_devclass = ir_package_scope + EXCEPTIONS + not_executed = 1 + not_found = 2 + illegal_object = 3 + no_cross_for_this_object = 4 + batch = 5 + batchjob_error = 6 + wrong_type = 7 + object_not_exist = 8 + OTHERS = 9. + + IF sy-subrc = 1 OR sy-subrc = 2 OR lines( rt_findings ) = 0. + RETURN. + ELSEIF sy-subrc > 2. + zcx_abapgit_exception=>raise( |RS_EU_CROSSREF({ sy-subrc }) for { iv_obj_type } { iv_obj_name }| ). + ENDIF. + + ENDMETHOD. + + + METHOD new. + CREATE OBJECT ro_instance. + ENDMETHOD. + + + METHOD select_external_usages. + + DATA lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt. + DATA lt_package_scope LIKE ir_package_scope. + + lt_tadir = zcl_abapgit_factory=>get_tadir( )->read( + iv_package = iv_package + iv_ignore_subpackages = iv_ignore_subpackages ). + + lt_package_scope = build_package_scope( + ir_package_scope = ir_package_scope + it_tadir = lt_tadir ). + + rt_objs = collect_where_used( + ir_package_scope = lt_package_scope + it_tadir = lt_tadir ). + + SORT rt_objs. + DELETE ADJACENT DUPLICATES FROM rt_objs. + " Duplicates happen e.g. because where-used is found by method. + " However here this functionality aggregates them to the object + " These are not true duplicates, so if ever the method name (or any other duplicate cause) + " will be extracted, this sort can be removed + + ENDMETHOD. +ENDCLASS. diff --git a/src/inspect/zcl_abapgit_where_used_tools.clas.xml b/src/inspect/zcl_abapgit_where_used_tools.clas.xml new file mode 100644 index 000000000..bcbde1723 --- /dev/null +++ b/src/inspect/zcl_abapgit_where_used_tools.clas.xml @@ -0,0 +1,16 @@ + + + + + + ZCL_ABAPGIT_WHERE_USED_TOOLS + E + abapGit where used utilities + 1 + X + X + X + + + + diff --git a/src/ui/core/zcl_abapgit_gui.clas.abap b/src/ui/core/zcl_abapgit_gui.clas.abap index d1d18d09d..ef5e6f477 100644 --- a/src/ui/core/zcl_abapgit_gui.clas.abap +++ b/src/ui/core/zcl_abapgit_gui.clas.abap @@ -115,7 +115,7 @@ ENDCLASS. -CLASS zcl_abapgit_gui IMPLEMENTATION. +CLASS ZCL_ABAPGIT_GUI IMPLEMENTATION. METHOD back. @@ -412,7 +412,7 @@ CLASS zcl_abapgit_gui IMPLEMENTATION. ENDIF. li_html = mi_cur_page->render( ). - lv_html = li_html->render( abap_true ). + lv_html = li_html->render( iv_no_indent_jscss = abap_true ). IF mi_html_processor IS BOUND. lv_html = mi_html_processor->process( diff --git a/src/ui/core/zcl_abapgit_html.clas.abap b/src/ui/core/zcl_abapgit_html.clas.abap index 003a52868..633e34d8f 100644 --- a/src/ui/core/zcl_abapgit_html.clas.abap +++ b/src/ui/core/zcl_abapgit_html.clas.abap @@ -482,6 +482,8 @@ CLASS ZCL_ABAPGIT_HTML IMPLEMENTATION. iv_tag = 'div' iv_content = iv_content ii_content = ii_content + is_data_attr = is_data_attr + it_data_attrs = it_data_attrs iv_id = iv_id iv_class = iv_class ). ri_self = me. @@ -512,14 +514,18 @@ CLASS ZCL_ABAPGIT_HTML IMPLEMENTATION. FIELD-SYMBOLS: LIKE LINE OF lt_temp, LIKE LINE OF lt_temp. - ls_context-no_indent_jscss = iv_no_indent_jscss. + IF iv_no_line_breaks = abap_true. + CONCATENATE LINES OF mt_buffer INTO rv_html. + ELSE. + ls_context-no_indent_jscss = iv_no_indent_jscss. - LOOP AT mt_buffer ASSIGNING . - APPEND TO lt_temp ASSIGNING . - indent_line( CHANGING cs_context = ls_context cv_line = ). - ENDLOOP. + LOOP AT mt_buffer ASSIGNING . + APPEND TO lt_temp ASSIGNING . + indent_line( CHANGING cs_context = ls_context cv_line = ). + ENDLOOP. - CONCATENATE LINES OF lt_temp INTO rv_html SEPARATED BY cl_abap_char_utilities=>newline. + CONCATENATE LINES OF lt_temp INTO rv_html SEPARATED BY cl_abap_char_utilities=>newline. + ENDIF. ENDMETHOD. @@ -538,7 +544,8 @@ CLASS ZCL_ABAPGIT_HTML IMPLEMENTATION. ii_content = ii_content iv_id = iv_id iv_class = iv_class - is_data_attr = is_data_attr + is_data_attr = is_data_attr + it_data_attrs = it_data_attrs iv_hint = iv_hint ). ri_self = me. ENDMETHOD. @@ -552,7 +559,8 @@ CLASS ZCL_ABAPGIT_HTML IMPLEMENTATION. ii_content = ii_content iv_id = iv_id iv_class = iv_class - is_data_attr = is_data_attr + is_data_attr = is_data_attr + it_data_attrs = it_data_attrs iv_hint = iv_hint ). ri_self = me. ENDMETHOD. @@ -562,6 +570,7 @@ CLASS ZCL_ABAPGIT_HTML IMPLEMENTATION. DATA lv_open_tag TYPE string. DATA lv_close_tag TYPE string. + DATA ls_data_attr LIKE LINE OF it_data_attrs. DATA: lv_class TYPE string, lv_id TYPE string, @@ -584,6 +593,10 @@ CLASS ZCL_ABAPGIT_HTML IMPLEMENTATION. lv_data_attr = | data-{ is_data_attr-name }="{ is_data_attr-value }"|. ENDIF. + LOOP AT it_data_attrs INTO ls_data_attr. + lv_data_attr = lv_data_attr && | data-{ ls_data_attr-name }="{ ls_data_attr-value }"|. + ENDLOOP. + lv_open_tag = |<{ iv_tag }{ lv_id }{ lv_class }{ lv_data_attr }{ lv_title }>|. lv_close_tag = ||. diff --git a/src/ui/core/zif_abapgit_gui_hotkeys.intf.abap b/src/ui/core/zif_abapgit_gui_hotkeys.intf.abap index 9bbbd925d..df292542d 100644 --- a/src/ui/core/zif_abapgit_gui_hotkeys.intf.abap +++ b/src/ui/core/zif_abapgit_gui_hotkeys.intf.abap @@ -15,6 +15,8 @@ INTERFACE zif_abapgit_gui_hotkeys METHODS get_hotkey_actions RETURNING - VALUE(rt_hotkey_actions) TYPE ty_hotkeys_with_descr . + VALUE(rt_hotkey_actions) TYPE ty_hotkeys_with_descr + RAISING + zcx_abapgit_exception. ENDINTERFACE. diff --git a/src/ui/core/zif_abapgit_html.intf.abap b/src/ui/core/zif_abapgit_html.intf.abap index 5c00ef8ee..d1d0d47ec 100644 --- a/src/ui/core/zif_abapgit_html.intf.abap +++ b/src/ui/core/zif_abapgit_html.intf.abap @@ -4,7 +4,8 @@ INTERFACE zif_abapgit_html PUBLIC. BEGIN OF ty_data_attr, name TYPE string, value TYPE string, - END OF ty_data_attr. + END OF ty_data_attr, + ty_data_attrs TYPE STANDARD TABLE OF ty_data_attr WITH KEY name. CONSTANTS: BEGIN OF c_action_type, @@ -40,7 +41,8 @@ INTERFACE zif_abapgit_html PUBLIC. METHODS render IMPORTING - !iv_no_indent_jscss TYPE abap_bool OPTIONAL + !iv_no_indent_jscss TYPE abap_bool DEFAULT abap_false + !iv_no_line_breaks TYPE abap_bool DEFAULT abap_false RETURNING VALUE(rv_html) TYPE string . @@ -111,6 +113,7 @@ INTERFACE zif_abapgit_html PUBLIC. !iv_hint TYPE string OPTIONAL !iv_format_single_line TYPE abap_bool DEFAULT abap_false !is_data_attr TYPE ty_data_attr OPTIONAL + !it_data_attrs TYPE ty_data_attrs OPTIONAL RETURNING VALUE(ri_self) TYPE REF TO zif_abapgit_html. @@ -123,6 +126,7 @@ INTERFACE zif_abapgit_html PUBLIC. !iv_hint TYPE string OPTIONAL !iv_format_single_line TYPE abap_bool DEFAULT abap_true !is_data_attr TYPE ty_data_attr OPTIONAL + !it_data_attrs TYPE ty_data_attrs OPTIONAL PREFERRED PARAMETER iv_content RETURNING VALUE(ri_self) TYPE REF TO zif_abapgit_html. @@ -136,6 +140,7 @@ INTERFACE zif_abapgit_html PUBLIC. !iv_hint TYPE string OPTIONAL !iv_format_single_line TYPE abap_bool DEFAULT abap_true !is_data_attr TYPE ty_data_attr OPTIONAL + !it_data_attrs TYPE ty_data_attrs OPTIONAL PREFERRED PARAMETER iv_content RETURNING VALUE(ri_self) TYPE REF TO zif_abapgit_html. @@ -147,6 +152,7 @@ INTERFACE zif_abapgit_html PUBLIC. !iv_id TYPE string OPTIONAL !iv_class TYPE string OPTIONAL !is_data_attr TYPE ty_data_attr OPTIONAL + !it_data_attrs TYPE ty_data_attrs OPTIONAL PREFERRED PARAMETER iv_content RETURNING VALUE(ri_self) TYPE REF TO zif_abapgit_html. diff --git a/src/ui/lib/zcl_abapgit_gui_chunk_lib.clas.abap b/src/ui/lib/zcl_abapgit_gui_chunk_lib.clas.abap index b87f4cf4a..7ee0d3f67 100644 --- a/src/ui/lib/zcl_abapgit_gui_chunk_lib.clas.abap +++ b/src/ui/lib/zcl_abapgit_gui_chunk_lib.clas.abap @@ -19,6 +19,11 @@ CLASS zcl_abapgit_gui_chunk_lib DEFINITION !iv_extra_style TYPE string OPTIONAL RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . + CLASS-METHODS render_success + IMPORTING + iv_message TYPE string + RETURNING + VALUE(ri_html) TYPE REF TO zif_abapgit_html . CLASS-METHODS render_repo_top IMPORTING !io_repo TYPE REF TO zcl_abapgit_repo @@ -184,6 +189,7 @@ CLASS zcl_abapgit_gui_chunk_lib DEFINITION CLASS-METHODS render_help_hint IMPORTING iv_text_to_wrap TYPE string + iv_add_class TYPE string OPTIONAL RETURNING VALUE(rv_html) TYPE string. @@ -195,7 +201,10 @@ CLASS zcl_abapgit_gui_chunk_lib DEFINITION CLASS-METHODS get_item_link IMPORTING - !is_item TYPE zif_abapgit_definitions=>ty_repo_item + !is_item TYPE zif_abapgit_definitions=>ty_repo_item OPTIONAL + !iv_obj_type TYPE zif_abapgit_definitions=>ty_repo_item-obj_type OPTIONAL + !iv_obj_name TYPE zif_abapgit_definitions=>ty_repo_item-obj_name OPTIONAL + PREFERRED PARAMETER is_item RETURNING VALUE(rv_html) TYPE string. @@ -234,7 +243,7 @@ ENDCLASS. -CLASS zcl_abapgit_gui_chunk_lib IMPLEMENTATION. +CLASS ZCL_ABAPGIT_GUI_CHUNK_LIB IMPLEMENTATION. METHOD class_constructor. @@ -288,15 +297,23 @@ CLASS zcl_abapgit_gui_chunk_lib IMPLEMENTATION. DATA lv_encode TYPE string. DATA li_html TYPE REF TO zif_abapgit_html. + DATA ls_item LIKE is_item. + + IF is_item IS INITIAL. + ls_item-obj_type = iv_obj_type. + ls_item-obj_name = iv_obj_name. + ELSE. + ls_item = is_item. + ENDIF. CREATE OBJECT li_html TYPE zcl_abapgit_html. lv_encode = zcl_abapgit_html_action_utils=>jump_encode( - iv_obj_type = is_item-obj_type - iv_obj_name = is_item-obj_name ). + iv_obj_type = ls_item-obj_type + iv_obj_name = ls_item-obj_name ). rv_html = li_html->a( - iv_txt = |{ is_item-obj_name }| + iv_txt = |{ ls_item-obj_name }| iv_act = |{ zif_abapgit_definitions=>c_action-jump }?{ lv_encode }| ). ENDMETHOD. @@ -542,22 +559,25 @@ CLASS zcl_abapgit_gui_chunk_lib IMPLEMENTATION. METHOD render_help_hint. - " TODO potentially move to or integrate with zcl_abapgit_html_form - - DATA lt_fragments TYPE string_table. DATA li_html TYPE REF TO zif_abapgit_html. + DATA lv_add_class TYPE string. + li_html = zcl_abapgit_html=>create( ). - APPEND `
` TO lt_fragments. - APPEND li_html->icon( - iv_name = 'question-circle-solid' - iv_class = 'blue' ) TO lt_fragments. - APPEND `
` TO lt_fragments. - APPEND iv_text_to_wrap TO lt_fragments. - APPEND `
` TO lt_fragments. - APPEND `
` TO lt_fragments. + IF iv_add_class IS NOT INITIAL. + lv_add_class = ` ` && iv_add_class. + ENDIF. - rv_html = concat_lines_of( lt_fragments ). + li_html->add( |
| ). + li_html->add_icon( + iv_name = 'question-circle-solid' + iv_class = 'blue' ). + li_html->add( `
` ). + li_html->add( iv_text_to_wrap ). + li_html->add( `
` ). + li_html->add( `
` ). + + rv_html = li_html->render( iv_no_line_breaks = abap_true ). ENDMETHOD. @@ -1110,6 +1130,17 @@ CLASS zcl_abapgit_gui_chunk_lib IMPLEMENTATION. ENDMETHOD. + METHOD render_success. + + ri_html = zcl_abapgit_html=>create( ). + ri_html->add( '
' ). + ri_html->add_icon( 'check' ). + ri_html->add( iv_message ). + ri_html->add( '
' ). + + ENDMETHOD. + + METHOD render_table_footer. CREATE OBJECT ri_html TYPE zcl_abapgit_html. diff --git a/src/ui/lib/zcl_abapgit_html_table.clas.abap b/src/ui/lib/zcl_abapgit_html_table.clas.abap index 81be70d4c..81c387f03 100644 --- a/src/ui/lib/zcl_abapgit_html_table.clas.abap +++ b/src/ui/lib/zcl_abapgit_html_table.clas.abap @@ -8,11 +8,12 @@ CLASS zcl_abapgit_html_table DEFINITION CLASS-METHODS create IMPORTING - !ii_renderer TYPE REF TO zif_abapgit_html_table OPTIONAL + !ii_renderer TYPE REF TO zif_abapgit_html_table OPTIONAL " Can be passed to renderer + !is_initial_sorting_state TYPE zif_abapgit_html_table=>ty_sorting_state OPTIONAL + PREFERRED PARAMETER ii_renderer RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_html_table . - " probably th css_class - " maybe auto class for td + " maybe also th css_class METHODS define_column IMPORTING !iv_column_id TYPE string @@ -21,8 +22,17 @@ CLASS zcl_abapgit_html_table DEFINITION !iv_sortable TYPE abap_bool DEFAULT abap_true RETURNING VALUE(ro_self) TYPE REF TO zcl_abapgit_html_table . + METHODS define_column_group + IMPORTING + !iv_group_id TYPE string OPTIONAL " not mandatory, but can be used for CSS (TODO data-gid) + !iv_group_title TYPE string OPTIONAL " can be empty ! + PREFERRED PARAMETER iv_group_title + RETURNING + VALUE(ro_self) TYPE REF TO zcl_abapgit_html_table + RAISING + zcx_abapgit_exception . " Maybe also data_provider - " Record Limit + " TODO record Limiter METHODS render IMPORTING !ii_renderer TYPE REF TO zif_abapgit_html_table OPTIONAL @@ -37,12 +47,17 @@ CLASS zcl_abapgit_html_table DEFINITION RAISING zcx_abapgit_exception . - " Static utils + " Sorting utils CLASS-METHODS detect_sorting_request IMPORTING iv_event TYPE string RETURNING VALUE(rs_sorting_request) TYPE zif_abapgit_html_table=>ty_sorting_state. + METHODS process_sorting_request + IMPORTING + iv_event TYPE string + RETURNING + VALUE(rv_processed) TYPE abap_bool. PROTECTED SECTION. PRIVATE SECTION. @@ -56,6 +71,8 @@ CLASS zcl_abapgit_html_table DEFINITION column_title TYPE string, from_field TYPE abap_compname, sortable TYPE abap_bool, + is_group TYPE abap_bool, + group_span TYPE i, END OF ty_column, ty_columns TYPE STANDARD TABLE OF ty_column WITH KEY column_id. @@ -65,6 +82,7 @@ CLASS zcl_abapgit_html_table DEFINITION DATA mv_with_cids TYPE abap_bool. DATA mv_table_id TYPE string. DATA ms_sorting_state TYPE zif_abapgit_html_table=>ty_sorting_state. + DATA mr_last_grp TYPE REF TO ty_column. " potentially receive from outside DATA mv_sort_span_class TYPE string VALUE `sort-arrow`. @@ -101,6 +119,16 @@ CLASS zcl_abapgit_html_table DEFINITION RETURNING VALUE(rs_data_attr) TYPE zif_abapgit_html=>ty_data_attr. + CLASS-METHODS gid_attr + IMPORTING + iv_column_id TYPE string + RETURNING + VALUE(rs_data_attr) TYPE zif_abapgit_html=>ty_data_attr. + + METHODS apply_sorting + CHANGING + ct_data TYPE STANDARD TABLE. + ENDCLASS. @@ -108,6 +136,38 @@ ENDCLASS. CLASS ZCL_ABAPGIT_HTML_TABLE IMPLEMENTATION. + METHOD apply_sorting. + + DATA lv_field TYPE abap_compname. + DATA ls_col LIKE LINE OF mt_columns. + + IF ms_sorting_state-column_id IS INITIAL. + RETURN. + ENDIF. + + READ TABLE mt_columns INTO ls_col WITH KEY column_id = ms_sorting_state-column_id. + IF sy-subrc <> 0. + RETURN. " ??? but let's not throw errors here + ENDIF. + + IF ls_col-from_field IS NOT INITIAL. + lv_field = to_upper( ls_col-from_field ). + ELSE. + lv_field = to_upper( ms_sorting_state-column_id ). + ENDIF. + + " What to do if column_id is not a table field ? + " Well ... then it is a complex case for an external sorting, don't use the simple one + + IF ms_sorting_state-descending = abap_true. + SORT ct_data BY (lv_field) DESCENDING. + ELSE. + SORT ct_data BY (lv_field) ASCENDING. + ENDIF. + + ENDMETHOD. + + METHOD cid_attr. rs_data_attr-name = 'cid'. @@ -119,6 +179,7 @@ CLASS ZCL_ABAPGIT_HTML_TABLE IMPLEMENTATION. METHOD create. CREATE OBJECT ro_instance. ro_instance->mi_renderer = ii_renderer. + ro_instance->ms_sorting_state = is_initial_sorting_state. ENDMETHOD. @@ -135,6 +196,28 @@ CLASS ZCL_ABAPGIT_HTML_TABLE IMPLEMENTATION. -from_field = to_upper( iv_from_field ). -sortable = iv_sortable. + IF mr_last_grp IS NOT INITIAL. + mr_last_grp->group_span = mr_last_grp->group_span + 1. + ENDIF. + + ENDMETHOD. + + + METHOD define_column_group. + + IF lines( mt_columns ) > 0 AND mr_last_grp IS INITIAL. + " Groups should cover all columns + " you can create a group with empty title if groups start later VISUALLY + zcx_abapgit_exception=>raise( 'Start groups from the beginning' ). + ENDIF. + + ro_self = me. + + APPEND INITIAL LINE TO mt_columns REFERENCE INTO mr_last_grp. + mr_last_grp->is_group = abap_true. + mr_last_grp->column_id = iv_group_id. + mr_last_grp->column_title = iv_group_title. + ENDMETHOD. @@ -158,9 +241,32 @@ CLASS ZCL_ABAPGIT_HTML_TABLE IMPLEMENTATION. ENDMETHOD. + METHOD gid_attr. + + rs_data_attr-name = 'gid'. + rs_data_attr-value = iv_column_id. + + ENDMETHOD. + + + METHOD process_sorting_request. + + DATA ls_sorting_req LIKE ms_sorting_state. + + ls_sorting_req = detect_sorting_request( iv_event ). + IF ls_sorting_req IS NOT INITIAL. + ms_sorting_state = ls_sorting_req. + rv_processed = abap_true. + ENDIF. + + ENDMETHOD. + + METHOD render. DATA lv_attrs TYPE string. + DATA lr_data_copy TYPE REF TO data. + FIELD-SYMBOLS TYPE ANY TABLE. IF ii_renderer IS BOUND. mi_renderer = ii_renderer. @@ -170,7 +276,20 @@ CLASS ZCL_ABAPGIT_HTML_TABLE IMPLEMENTATION. mv_with_cids = iv_with_cids. mv_table_id = iv_id. - ms_sorting_state = is_sorting_state. + ASSIGN it_data TO . + + IF is_sorting_state IS NOT INITIAL. + ms_sorting_state = is_sorting_state. + ELSEIF ms_sorting_state IS NOT INITIAL. + " If sorting state is not passed, + " but there is non empty sort state then suppose simple sorting mode + " so that table sorts the data itself before rendering + " TODO not efficient, maybe bind changing data from outside + CREATE DATA lr_data_copy LIKE it_data. + ASSIGN lr_data_copy->* TO . + = it_data. + apply_sorting( CHANGING ct_data = ). + ENDIF. IF iv_id IS NOT INITIAL. lv_attrs = lv_attrs && | id="{ iv_id }"|. @@ -189,7 +308,7 @@ CLASS ZCL_ABAPGIT_HTML_TABLE IMPLEMENTATION. mi_html->add( || ). render_thead( ). - render_tbody( it_data ). + render_tbody( ). mi_html->add( '' ). IF iv_wrap_in_div IS NOT INITIAL. @@ -240,11 +359,18 @@ CLASS ZCL_ABAPGIT_HTML_TABLE IMPLEMENTATION. DATA ls_render TYPE zif_abapgit_html_table=>ty_cell_render. DATA lv_dummy TYPE string. - DATA ls_cid TYPE zif_abapgit_html=>ty_data_attr. + DATA lt_attrs TYPE zif_abapgit_html=>ty_data_attrs. + FIELD-SYMBOLS LIKE LINE OF mt_columns. + FIELD-SYMBOLS LIKE LINE OF mt_columns. FIELD-SYMBOLS TYPE any. LOOP AT mt_columns ASSIGNING . + IF -is_group = abap_true. + ASSIGN TO . + CONTINUE. + ENDIF. + IF -from_field IS NOT INITIAL AND -from_field <> '-'. ASSIGN COMPONENT -from_field OF STRUCTURE is_row TO . IF sy-subrc <> 0. @@ -269,13 +395,17 @@ CLASS ZCL_ABAPGIT_HTML_TABLE IMPLEMENTATION. iv_value = |{ }| ). IF mv_with_cids = abap_true. - ls_cid = cid_attr( -column_id ). + CLEAR lt_attrs. + APPEND cid_attr( -column_id ) TO lt_attrs. + IF IS ASSIGNED AND -column_id IS NOT INITIAL. + APPEND gid_attr( -column_id ) TO lt_attrs. + ENDIF. ENDIF. mi_html->td( iv_content = ls_render-content ii_content = ls_render-html - is_data_attr = ls_cid + it_data_attrs = lt_attrs iv_class = ls_render-css_class ). ENDLOOP. @@ -320,19 +450,58 @@ CLASS ZCL_ABAPGIT_HTML_TABLE IMPLEMENTATION. METHOD render_thead. FIELD-SYMBOLS LIKE LINE OF mt_columns. - DATA ls_cid TYPE zif_abapgit_html=>ty_data_attr. + FIELD-SYMBOLS LIKE LINE OF mt_columns. + DATA lt_attrs TYPE zif_abapgit_html=>ty_data_attrs. + DATA ls_grp_span TYPE string. + DATA lv_grp_data TYPE string. mi_html->add( '' ). + + " Group headers + IF mr_last_grp IS NOT INITIAL. " Has groups + + mi_html->add( '' ). + + LOOP AT mt_columns ASSIGNING WHERE is_group = abap_true. + IF mv_with_cids = abap_true AND -column_id IS NOT INITIAL. + lv_grp_data = | data-gid="{ -column_id }"|. + ELSE. + CLEAR lv_grp_data. + ENDIF. + + IF -group_span > 1. + ls_grp_span = | colspan="{ -group_span }"|. + ELSE. + CLEAR ls_grp_span. + ENDIF. + + mi_html->add( |{ -column_title }| ). + ENDLOOP. + + mi_html->add( '' ). + + ENDIF. + + " Regular headers mi_html->add( '' ). LOOP AT mt_columns ASSIGNING . + IF -is_group = abap_true. + ASSIGN TO . + CONTINUE. + ENDIF. + IF mv_with_cids = abap_true. - ls_cid = cid_attr( -column_id ). + CLEAR lt_attrs. + APPEND cid_attr( -column_id ) TO lt_attrs. + IF IS ASSIGNED AND -column_id IS NOT INITIAL. + APPEND gid_attr( -column_id ) TO lt_attrs. + ENDIF. ENDIF. mi_html->th( - iv_content = render_column_title( ) - is_data_attr = ls_cid ). + iv_content = render_column_title( ) + it_data_attrs = lt_attrs ). ENDLOOP. mi_html->add( '' ). diff --git a/src/ui/lib/zcl_abapgit_html_table.clas.testclasses.abap b/src/ui/lib/zcl_abapgit_html_table.clas.testclasses.abap index 2291048ba..d7c92be16 100644 --- a/src/ui/lib/zcl_abapgit_html_table.clas.testclasses.abap +++ b/src/ui/lib/zcl_abapgit_html_table.clas.testclasses.abap @@ -17,6 +17,7 @@ CLASS ltcl_test_simple_table DEFINITION FINAL METHODS simple_render FOR TESTING RAISING zcx_abapgit_exception. METHODS with_cids FOR TESTING RAISING zcx_abapgit_exception. METHODS with_sort FOR TESTING RAISING zcx_abapgit_exception. + METHODS with_groups FOR TESTING RAISING zcx_abapgit_exception. METHODS test_data_set RETURNING @@ -98,7 +99,8 @@ CLASS ltcl_test_simple_table IMPLEMENTATION. 'Col 2' )->add( '' )->add( '' )->add( - '' )->add( + '' ). + li_html_exp->add( '' )->add( '' )->add( 'Hello' )->add( @@ -149,7 +151,8 @@ CLASS ltcl_test_simple_table IMPLEMENTATION. 'Col 1' )->add( 'Col 2' )->add( '' )->add( - '' )->add( + '' ). + li_html_exp->add( '' )->add( '' )->add( 'Hello' )->add( @@ -200,12 +203,81 @@ CLASS ltcl_test_simple_table IMPLEMENTATION. '' )->add( '' )->add( '' )->add( - '' - )->add( + '' )->add( '' )->add( '' )->add( '' )->add( - '' )->add( + '' ). + li_html_exp->add( + '' )->add( + '' )->add( + '' )->add( + '' )->add( + '' )->add( + '' )->add( + '' )->add( + '' )->add( + '' )->add( + '' )->add( + '' )->add( + '' )->add( + '
Col 1Col 1' && + 'Col 2Col 3
Hello110
World220
' ). + + cl_abap_unit_assert=>assert_equals( + act = lv_html_act + exp = li_html_exp->render( ) ). + + ENDMETHOD. + + METHOD with_groups. + + DATA lo_tab TYPE REF TO zcl_abapgit_html_table. + DATA lv_html_act TYPE string. + DATA li_html_exp TYPE REF TO zif_abapgit_html. + DATA ls_sort TYPE zif_abapgit_html_table=>ty_sorting_state. + + lo_tab = zcl_abapgit_html_table=>create( me + )->define_column_group( + )->define_column( + iv_column_id = 'col1' + iv_column_title = 'Col 1' + )->define_column_group( + iv_group_title = 'Group' + iv_group_id = '' + )->define_column( + iv_column_id = 'col2' + iv_column_title = 'Col 2' + )->define_column( + iv_column_id = 'col3' + iv_column_title = 'Col 3' + iv_sortable = abap_false ). + + ls_sort-column_id = 'col1'. + + lv_html_act = lo_tab->render( + is_sorting_state = ls_sort + iv_id = 'with-sort' + it_data = test_data_set( ) )->render( ). + + CREATE OBJECT li_html_exp TYPE zcl_abapgit_html. + + li_html_exp->add( + '' )->add( + '' )->add( + '' )->add( + '' )->add( + '' )->add( + '' ). + li_html_exp->add( + '' )->add( + '' )->add( + '' )->add( + '' )->add( + '' )->add( + '' ). + li_html_exp->add( '' )->add( '' )->add( '' )->add( diff --git a/src/ui/lib/zcl_abapgit_html_toolbar.clas.abap b/src/ui/lib/zcl_abapgit_html_toolbar.clas.abap index eef86a515..65f6cae38 100644 --- a/src/ui/lib/zcl_abapgit_html_toolbar.clas.abap +++ b/src/ui/lib/zcl_abapgit_html_toolbar.clas.abap @@ -26,6 +26,7 @@ CLASS zcl_abapgit_html_toolbar DEFINITION !iv_id TYPE string OPTIONAL !iv_title TYPE string OPTIONAL !iv_class TYPE string OPTIONAL + !iv_hotkey TYPE string OPTIONAL !iv_li_class TYPE string OPTIONAL RETURNING VALUE(ro_self) TYPE REF TO zcl_abapgit_html_toolbar . @@ -47,6 +48,11 @@ CLASS zcl_abapgit_html_toolbar DEFINITION !iv_action TYPE string OPTIONAL RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html . + METHODS get_hotkeys + IMPORTING + iv_component_name TYPE string OPTIONAL + RETURNING + VALUE(rt_hotkeys) TYPE zif_abapgit_gui_hotkeys=>ty_hotkeys_with_descr. PROTECTED SECTION. PRIVATE SECTION. @@ -65,6 +71,7 @@ CLASS zcl_abapgit_html_toolbar DEFINITION title TYPE string, class TYPE string, li_class TYPE string, + hotkey TYPE string, END OF ty_item . TYPES: ty_items TYPE STANDARD TABLE OF ty_item . @@ -81,7 +88,7 @@ ENDCLASS. -CLASS zcl_abapgit_html_toolbar IMPLEMENTATION. +CLASS ZCL_ABAPGIT_HTML_TOOLBAR IMPLEMENTATION. METHOD add. @@ -95,6 +102,8 @@ CLASS zcl_abapgit_html_toolbar IMPLEMENTATION. ASSERT NOT ( iv_chk <> abap_undefined AND io_sub IS NOT INITIAL ). + ASSERT iv_hotkey IS INITIAL OR strlen( iv_hotkey ) = 1. + ls_item-txt = iv_txt. ls_item-act = iv_act. ls_item-ico = iv_ico. @@ -108,6 +117,7 @@ CLASS zcl_abapgit_html_toolbar IMPLEMENTATION. ls_item-title = iv_title. ls_item-class = iv_class. ls_item-li_class = iv_li_class. + ls_item-hotkey = to_lower( iv_hotkey ). APPEND ls_item TO mt_items. @@ -120,6 +130,12 @@ CLASS zcl_abapgit_html_toolbar IMPLEMENTATION. mv_id = iv_id. ENDMETHOD. + + METHOD count_items. + rv_count = lines( mt_items ). + ENDMETHOD. + + METHOD create. CREATE OBJECT ro_instance EXPORTING @@ -127,8 +143,20 @@ CLASS zcl_abapgit_html_toolbar IMPLEMENTATION. ENDMETHOD. - METHOD count_items. - rv_count = lines( mt_items ). + METHOD get_hotkeys. + + DATA ls_hotkey_action LIKE LINE OF rt_hotkeys. + FIELD-SYMBOLS LIKE LINE OF mt_items. + + ls_hotkey_action-ui_component = iv_component_name. + + LOOP AT mt_items ASSIGNING WHERE hotkey IS NOT INITIAL. + ls_hotkey_action-description = -txt. + ls_hotkey_action-action = -act. + ls_hotkey_action-hotkey = -hotkey. + INSERT ls_hotkey_action INTO TABLE rt_hotkeys. + ENDLOOP. + ENDMETHOD. @@ -185,6 +213,8 @@ CLASS zcl_abapgit_html_toolbar IMPLEMENTATION. lv_id TYPE string, lv_check TYPE string, lv_aux TYPE string, + lv_txt TYPE string, + lv_hkidx TYPE i, lv_has_icons TYPE abap_bool. FIELD-SYMBOLS LIKE LINE OF mt_items. @@ -212,9 +242,29 @@ CLASS zcl_abapgit_html_toolbar IMPLEMENTATION. " Render items LOOP AT mt_items ASSIGNING . CLEAR: lv_class, lv_class_value, lv_icon. + lv_txt = -txt. + + IF -hotkey IS NOT INITIAL. + ASSERT strlen( -hotkey ) = 1. + lv_hkidx = find( + val = lv_txt + sub = to_upper( -hotkey ) ). + IF lv_hkidx < 0. + lv_hkidx = find( + val = lv_txt + sub = -hotkey ). + ENDIF. + IF lv_hkidx >= 0. + lv_txt = replace( + val = lv_txt + off = lv_hkidx + len = 1 + with = |{ lv_txt+lv_hkidx(1) }| ). + ENDIF. + ENDIF. IF -typ = zif_abapgit_html=>c_action_type-separator. - ri_html->add( |
  • { -txt }
  • | ). + ri_html->add( |
  • { lv_txt }
  • | ). CONTINUE. ENDIF. @@ -250,7 +300,7 @@ CLASS zcl_abapgit_html_toolbar IMPLEMENTATION. ri_html->add( || ). IF -sub IS INITIAL. - ri_html->add_a( iv_txt = lv_icon && -txt + ri_html->add_a( iv_txt = lv_icon && lv_txt iv_typ = -typ iv_act = -act iv_id = -id @@ -258,7 +308,7 @@ CLASS zcl_abapgit_html_toolbar IMPLEMENTATION. iv_title = -title iv_class = -class ). ELSE. - ri_html->add_a( iv_txt = lv_icon && -txt + ri_html->add_a( iv_txt = lv_icon && lv_txt iv_typ = zif_abapgit_html=>c_action_type-dummy iv_act = '' iv_id = -id diff --git a/src/ui/pages/codi/zcl_abapgit_gui_page_whereused.clas.abap b/src/ui/pages/codi/zcl_abapgit_gui_page_whereused.clas.abap new file mode 100644 index 000000000..1352a6f53 --- /dev/null +++ b/src/ui/pages/codi/zcl_abapgit_gui_page_whereused.clas.abap @@ -0,0 +1,298 @@ +CLASS zcl_abapgit_gui_page_whereused DEFINITION + PUBLIC + FINAL + INHERITING FROM zcl_abapgit_gui_component + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + zif_abapgit_gui_page_title, + zif_abapgit_gui_event_handler, + zif_abapgit_gui_hotkeys, + zif_abapgit_gui_menu_provider, + zif_abapgit_gui_renderable, + zif_abapgit_html_table. + + CLASS-METHODS create + IMPORTING + iv_package TYPE devclass OPTIONAL + ii_repo TYPE REF TO zif_abapgit_repo OPTIONAL + PREFERRED PARAMETER iv_package + RETURNING + VALUE(ri_page) TYPE REF TO zif_abapgit_gui_renderable + RAISING + zcx_abapgit_exception. + + METHODS constructor + IMPORTING + iv_package TYPE devclass OPTIONAL + ii_repo TYPE REF TO zif_abapgit_repo OPTIONAL + RAISING + zcx_abapgit_exception. + + PROTECTED SECTION. + PRIVATE SECTION. + CONSTANTS: + BEGIN OF c_action, + refresh TYPE string VALUE 'refresh', + show_used_obj TYPE string VALUE 'show_used_obj', + END OF c_action. + + CONSTANTS c_title TYPE string VALUE 'Where Used'. + DATA mv_package TYPE devclass. + DATA mv_ignore_subpackages TYPE abap_bool. + DATA mi_table TYPE REF TO zcl_abapgit_html_table. + DATA mv_show_used_obj TYPE abap_bool. + DATA mt_where_used TYPE zcl_abapgit_where_used_tools=>ty_dependency_tt. + + METHODS init_table_component + RAISING + zcx_abapgit_exception. + + METHODS render_filter_help_hint + RETURNING + VALUE(rv_html) TYPE string. + METHODS render_header + IMPORTING + ii_html TYPE REF TO zif_abapgit_html + RAISING + zcx_abapgit_exception. + METHODS run_where_used + RAISING + zcx_abapgit_exception. + +ENDCLASS. + + + +CLASS ZCL_ABAPGIT_GUI_PAGE_WHEREUSED IMPLEMENTATION. + + + METHOD constructor. + super->constructor( ). + IF ii_repo IS BOUND. + mv_package = ii_repo->get_package( ). + mv_ignore_subpackages = ii_repo->get_local_settings( )-ignore_subpackages. + ELSE. + mv_package = iv_package. + ENDIF. + + IF mv_package IS INITIAL OR zcl_abapgit_factory=>get_sap_package( mv_package )->exists( ) = abap_false. + zcx_abapgit_exception=>raise( |Package { mv_package } does not exist| ). + ENDIF. + + run_where_used( ). + + ENDMETHOD. + + + METHOD create. + + DATA lo_component TYPE REF TO zcl_abapgit_gui_page_whereused. + + CREATE OBJECT lo_component + EXPORTING + ii_repo = ii_repo + iv_package = iv_package. + + ri_page = zcl_abapgit_gui_page_hoc=>create( lo_component ). + + ENDMETHOD. + + + METHOD init_table_component. + + DATA ls_sorting_state TYPE zif_abapgit_html_table=>ty_sorting_state. + + IF mi_table IS BOUND. + RETURN. + ENDIF. + + IF ls_sorting_state-column_id IS INITIAL. + ls_sorting_state-column_id = 'package'. + ENDIF. + + mi_table = zcl_abapgit_html_table=>create( + ii_renderer = me + is_initial_sorting_state = ls_sorting_state ). + mi_table->define_column_group( + iv_group_title = 'Repo object' + iv_group_id = '' " No need + )->define_column( + iv_column_id = 'dep_package' + iv_column_title = 'Package' + )->define_column( + iv_column_id = 'dep_obj_type' + iv_column_title = 'Type' + )->define_column( + iv_column_id = 'dep_obj_name' + iv_column_title = 'Name' ). + mi_table->define_column_group( + iv_group_title = 'Used in' + iv_group_id = 'where' " Needed for CSS + )->define_column( + iv_column_id = 'package' + iv_column_title = 'Package' + )->define_column( + iv_column_id = 'obj_type' + iv_column_title = 'Type' + )->define_column( + iv_column_id = 'obj_name' + iv_column_title = 'Name' ). + + ENDMETHOD. + + + METHOD render_filter_help_hint. + + DATA li_html TYPE REF TO zif_abapgit_html. + + li_html = zcl_abapgit_html=>create( + )->add( `

    This tool cycles through all objects in the repo ` + )->add( `and runs the standard where-used function against it. ` + )->add( `The result is displayed here less the usages ` + )->add( `inside the repo itself.

    ` + )->add( `

    The tool can be used to detect ` + )->add( `potential regressions in the code which uses the repo ` + )->add( `and external to it (e.g. when deploying updates ` + )->add( `to a library-like repo).

    ` ). + + rv_html = zcl_abapgit_gui_chunk_lib=>render_help_hint( li_html->render( iv_no_line_breaks = abap_true ) ). + + ENDMETHOD. + + + METHOD render_header. + + DATA lv_sub_hint TYPE string. + + IF mv_ignore_subpackages = abap_false. + lv_sub_hint = ' and its subpackages'. + ENDIF. + + ii_html->div( + iv_class = 'wu-header' + iv_content = |Where used for package { + zcl_abapgit_gui_chunk_lib=>render_package_name( mv_package )->render( iv_no_line_breaks = abap_true ) + }{ lv_sub_hint } in other packages. { render_filter_help_hint( ) }| ). + + ENDMETHOD. + + + METHOD run_where_used. + mt_where_used = zcl_abapgit_where_used_tools=>new( )->select_external_usages( + iv_ignore_subpackages = mv_ignore_subpackages + iv_package = mv_package ). + ENDMETHOD. + + + METHOD zif_abapgit_gui_event_handler~on_event. + + IF mi_table->process_sorting_request( ii_event->mv_action ) = abap_true. + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + RETURN. + ENDIF. + + CASE ii_event->mv_action. + WHEN c_action-refresh. + run_where_used( ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + WHEN c_action-show_used_obj. + mv_show_used_obj = boolc( mv_show_used_obj = abap_false ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-re_render. + ENDCASE. + + ENDMETHOD. + + + METHOD zif_abapgit_gui_hotkeys~get_hotkey_actions. + rt_hotkey_actions = zif_abapgit_gui_menu_provider~get_menu( )->get_hotkeys( c_title ). + ENDMETHOD. + + + METHOD zif_abapgit_gui_menu_provider~get_menu. + + DATA lv_show_used_txt TYPE string. + + IF mv_show_used_obj = abap_true. + lv_show_used_txt = 'Hide Used Type'. + ELSE. + lv_show_used_txt = 'Show Used Type'. + ENDIF. + + ro_toolbar = zcl_abapgit_html_toolbar=>create( + )->add( + iv_txt = lv_show_used_txt + iv_title = 'Show/Hide used type or object (when available)' + iv_act = c_action-show_used_obj + iv_hotkey = 'u' + )->add( + iv_txt = 'Refresh' + iv_act = c_action-refresh + iv_hotkey = 'r' ). + + ENDMETHOD. + + + METHOD zif_abapgit_gui_page_title~get_page_title. + rv_title = c_title. + ENDMETHOD. + + + METHOD zif_abapgit_gui_renderable~render. + + register_handlers( ). + init_table_component( ). + + ri_html = zcl_abapgit_html=>create( ). + + render_header( ri_html ). + + IF mt_where_used IS INITIAL. + ri_html->add( zcl_abapgit_gui_chunk_lib=>render_success( 'No usages found' ) ). + ELSE. + ri_html->div( + iv_class = 'wu' + ii_content = mi_table->render( + iv_wrap_in_div = 'default-table-container' + iv_css_class = 'default-table' + iv_with_cids = abap_true + it_data = mt_where_used ) ). + ENDIF. + + ENDMETHOD. + + + METHOD zif_abapgit_html_table~get_row_attrs. + ENDMETHOD. + + + METHOD zif_abapgit_html_table~render_cell. + + FIELD-SYMBOLS TYPE zcl_abapgit_where_used_tools=>ty_dependency. + + ASSIGN is_row TO . + + CASE iv_column_id. + WHEN 'dep_obj_name'. + rs_render-content = -dep_obj_name. + IF mv_show_used_obj = abap_true. + rs_render-content = rs_render-content && |{ -dep_used_obj }|. + ENDIF. + WHEN 'obj_type'. + IF -obj_prog_type IS INITIAL. + rs_render-content = -obj_type. + ELSE. + rs_render-content = -obj_type && ':' && -obj_prog_type. + ENDIF. + WHEN 'obj_name'. + rs_render-content = zcl_abapgit_gui_chunk_lib=>get_item_link( + iv_obj_type = -obj_type + iv_obj_name = -obj_name ). + WHEN OTHERS. + rs_render-content = iv_value. + ENDCASE. + " TODO maybe add title for object cls ? + + ENDMETHOD. +ENDCLASS. diff --git a/src/ui/pages/codi/zcl_abapgit_gui_page_whereused.clas.xml b/src/ui/pages/codi/zcl_abapgit_gui_page_whereused.clas.xml new file mode 100644 index 000000000..1f1873811 --- /dev/null +++ b/src/ui/pages/codi/zcl_abapgit_gui_page_whereused.clas.xml @@ -0,0 +1,16 @@ + + + + + + ZCL_ABAPGIT_GUI_PAGE_WHEREUSED + E + abapGit where-used page + 1 + X + X + X + + + + diff --git a/src/ui/pages/zcl_abapgit_gui_page_repo_view.clas.abap b/src/ui/pages/zcl_abapgit_gui_page_repo_view.clas.abap index 78792c67d..135fb8801 100644 --- a/src/ui/pages/zcl_abapgit_gui_page_repo_view.clas.abap +++ b/src/ui/pages/zcl_abapgit_gui_page_repo_view.clas.abap @@ -201,7 +201,7 @@ ENDCLASS. -CLASS zcl_abapgit_gui_page_repo_view IMPLEMENTATION. +CLASS ZCL_ABAPGIT_GUI_PAGE_REPO_VIEW IMPLEMENTATION. METHOD apply_order_by. @@ -312,6 +312,8 @@ CLASS zcl_abapgit_gui_page_repo_view IMPLEMENTATION. iv_act = |{ c_actions-go_unit }| ). ro_advanced_dropdown->add( iv_txt = 'Run Code Inspector' iv_act = |{ zif_abapgit_definitions=>c_action-repo_code_inspector }?key={ mv_key }| ). + ro_advanced_dropdown->add( iv_txt = 'Where Used' + iv_act = |{ zif_abapgit_definitions=>c_action-where_used }?key={ mv_key }| ). ro_advanced_dropdown->add( iv_txt = 'Very Advanced' iv_typ = zif_abapgit_html=>c_action_type-separator ). diff --git a/src/ui/routing/zcl_abapgit_gui_router.clas.abap b/src/ui/routing/zcl_abapgit_gui_router.clas.abap index d9d36f968..8ab198aff 100644 --- a/src/ui/routing/zcl_abapgit_gui_router.clas.abap +++ b/src/ui/routing/zcl_abapgit_gui_router.clas.abap @@ -865,6 +865,10 @@ CLASS ZCL_ABAPGIT_GUI_ROUTER IMPLEMENTATION. WHEN zif_abapgit_definitions=>c_action-zip_object. " Export object as ZIP rs_handled-page = zcl_abapgit_gui_page_ex_object=>create( ). rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. + WHEN zif_abapgit_definitions=>c_action-where_used. + lo_repo ?= zcl_abapgit_repo_srv=>get_instance( )->get( lv_key ). + rs_handled-page = zcl_abapgit_gui_page_whereused=>create( ii_repo = lo_repo ). + rs_handled-state = zcl_abapgit_gui=>c_event_state-new_page. ENDCASE. ENDMETHOD. diff --git a/src/ui/zabapgit_css_common.w3mi.data.css b/src/ui/zabapgit_css_common.w3mi.data.css index 8d6c205e9..de581007a 100644 --- a/src/ui/zabapgit_css_common.w3mi.data.css +++ b/src/ui/zabapgit_css_common.w3mi.data.css @@ -238,6 +238,10 @@ span.transport-box { display: inline-block; } +span.package-box i.icon { + margin-right: 0.15em; +} + /* MISC AND REFACTOR */ .hidden-submit { @@ -1164,6 +1168,7 @@ table ul.repo-labels li { z-index: 1; border: 1px solid; padding: 0.4em 0.6em; + text-align: justify; } .form-field-help-tooltip .form-field-help-tooltip-text p { margin: 0px; @@ -1189,6 +1194,7 @@ div.default-table-container { padding: 6px 0.5em; background-color: white; border-radius: 6px; + overflow-x: hidden; } table.default-table { @@ -1196,15 +1202,9 @@ table.default-table { width: 100%; } -table.default-table thead tr { +table.default-table thead tr:last-child { border-bottom: #efefef solid 1px; } -/*table.default-table tbody tr { - border-bottom: #efefef solid 1px; -} -table.default-table tbody tr:last-child { - border-bottom: none; -}*/ table.default-table td, table.default-table th { @@ -1212,6 +1212,10 @@ table.default-table th { text-align: left; } +table.default-table th { + white-space: nowrap; +} + table.default-table th span.sort-arrow { display: inline-block; color: hsla(0, 0%, 0%, 0.15); @@ -1629,3 +1633,33 @@ table.unit_tests { .modal .radio-container label:hover { background-color: rgba(0, 0, 0, 0.1); } + +/* WHERE USED PAGE */ + +div.wu-header { + padding: 8px 0.5em; + margin: 0px 0.5em; +} +div.wu { + padding: 8px 0.5em; +} +div.wu table thead tr:first-child { + /* TODO: maybe move this to default table style */ + color: hsl(0, 0%, 80%); + text-transform: uppercase; + font-size: 90%; +} +div.wu table tbody { + font-size: 90%; + vertical-align: baseline; /* for second lines, used type */ +} +div.wu table td[data-cid="dep_obj_name"] span.used-obj { + display: block; + color: hsl(0, 0%, 70%); + font-size: smaller; + text-transform: lowercase; +} +div.wu table td[data-gid="where"], +div.wu table th[data-gid="where"] { + background-color: hsl(0, 0%, 97%); +} diff --git a/src/zif_abapgit_definitions.intf.abap b/src/zif_abapgit_definitions.intf.abap index 08c678306..2b6ac8642 100644 --- a/src/zif_abapgit_definitions.intf.abap +++ b/src/zif_abapgit_definitions.intf.abap @@ -371,6 +371,7 @@ INTERFACE zif_abapgit_definitions sponsor TYPE string VALUE 'sponsor', toggle_favorites TYPE string VALUE 'toggle_favorites', url TYPE string VALUE 'url', + where_used TYPE string VALUE 'where_used', yank_to_clipboard TYPE string VALUE 'yank_to_clipboard', zip_export TYPE string VALUE 'zip_export', zip_export_transport TYPE string VALUE 'zip_export_transport',
    Group
    Col 1' && + 'Col 2Col 3
    Hello