Where used page (#6897)

This commit is contained in:
Alexander Tsybulsky 2024-04-19 08:51:59 +03:00 committed by GitHub
parent 9b10bba142
commit 3bfb2be6ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 1219 additions and 63 deletions

View File

@ -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 <ls_tadir> TYPE zif_abapgit_definitions=>ty_tadir.
FIELD-SYMBOLS <ls_pkg> LIKE LINE OF rt_package_scope.
rt_package_scope = ir_package_scope.
LOOP AT it_tadir ASSIGNING <ls_tadir>.
CHECK <ls_tadir>-object = 'DEVC'.
APPEND INITIAL LINE TO rt_package_scope ASSIGNING <ls_pkg>.
<ls_pkg>-sign = 'E'.
<ls_pkg>-option = 'EQ'.
<ls_pkg>-low = <ls_tadir>-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 <ls_tadir> TYPE zif_abapgit_definitions=>ty_tadir.
li_progress = zcl_abapgit_progress=>get_instance( lines( it_tadir ) ).
LOOP AT it_tadir ASSIGNING <ls_tadir>.
CHECK <ls_tadir>-object <> 'DEVC'.
li_progress->show(
iv_current = sy-tabix
iv_text = |{ <ls_tadir>-object } { <ls_tadir>-obj_name }| ).
lt_where_used = get_where_used(
iv_obj_type = |{ <ls_tadir>-object }|
iv_obj_name = <ls_tadir>-obj_name
ir_package_scope = ir_package_scope ).
lt_objs_portion = convert_list(
iv_package = <ls_tadir>-devclass
iv_obj_type = <ls_tadir>-object
iv_obj_name = <ls_tadir>-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 <ls_dep> LIKE LINE OF rt_objs.
FIELD-SYMBOLS <ls_use> LIKE LINE OF it_where_used.
LOOP AT it_where_used ASSIGNING <ls_use>.
APPEND INITIAL LINE TO rt_objs ASSIGNING <ls_dep>.
<ls_dep>-dep_package = iv_package.
<ls_dep>-dep_obj_type = iv_obj_type.
<ls_dep>-dep_obj_name = iv_obj_name.
<ls_dep>-dep_used_obj = <ls_use>-used_obj.
<ls_dep>-dep_used_cls = <ls_use>-used_cls.
<ls_dep>-obj_cls = <ls_use>-object_cls.
<ls_dep>-obj_name = <ls_use>-encl_objec.
IF <ls_dep>-obj_name IS INITIAL.
<ls_dep>-obj_name = <ls_use>-object.
ENDIF.
IF <ls_use>-object_cls = 'FF'. " Function module
<ls_dep>-obj_type = 'FUNC'.
<ls_dep>-package = get_func_package( <ls_dep>-obj_name ).
ELSE.
<ls_dep>-obj_type = decode_obj_type( <ls_use>-object_cls ).
<ls_dep>-package = get_obj_package(
iv_obj_type = <ls_dep>-obj_type
iv_obj_name = <ls_dep>-obj_name ).
IF <ls_dep>-package IS INITIAL AND <ls_dep>-obj_type = 'CLAS'.
<ls_dep>-package = get_obj_package(
iv_obj_type = 'INTF'
iv_obj_name = <ls_dep>-obj_name ).
IF <ls_dep>-package IS NOT INITIAL.
<ls_dep>-obj_type = 'INTF'.
ENDIF.
ENDIF.
ENDIF.
IF <ls_dep>-package IS INITIAL.
IF <ls_dep>-obj_type = 'PROG'. " Maybe it is an include
<ls_dep>-package = get_incl_package( <ls_dep>-obj_name ).
IF <ls_dep>-package IS INITIAL.
SELECT SINGLE subc INTO <ls_dep>-obj_prog_type FROM trdir WHERE name = <ls_dep>-obj_name.
IF <ls_dep>-obj_prog_type IS NOT INITIAL AND <ls_dep>-obj_prog_type <> '1'. " Exec. prog
<ls_dep>-obj_type = 'INCL'.
ENDIF.
ENDIF.
ENDIF.
IF <ls_dep>-package IS INITIAL.
<ls_dep>-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 <ls_devobj> 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 <ls_devobj> WITH KEY type = iv_type.
IF sy-subrc = 0.
rv_type = <ls_devobj>-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.

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_ABAPGIT_WHERE_USED_TOOLS</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>abapGit where used utilities</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -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(

View File

@ -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,6 +514,9 @@ CLASS ZCL_ABAPGIT_HTML IMPLEMENTATION.
FIELD-SYMBOLS: <lv_line> LIKE LINE OF lt_temp,
<lv_line_c> LIKE LINE OF lt_temp.
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 <lv_line>.
@ -520,6 +525,7 @@ CLASS ZCL_ABAPGIT_HTML IMPLEMENTATION.
ENDLOOP.
CONCATENATE LINES OF lt_temp INTO rv_html SEPARATED BY cl_abap_char_utilities=>newline.
ENDIF.
ENDMETHOD.
@ -539,6 +545,7 @@ CLASS ZCL_ABAPGIT_HTML IMPLEMENTATION.
iv_id = iv_id
iv_class = iv_class
is_data_attr = is_data_attr
it_data_attrs = it_data_attrs
iv_hint = iv_hint ).
ri_self = me.
ENDMETHOD.
@ -553,6 +560,7 @@ CLASS ZCL_ABAPGIT_HTML IMPLEMENTATION.
iv_id = iv_id
iv_class = iv_class
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 = |</{ iv_tag }>|.

View File

@ -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.

View File

@ -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.

View File

@ -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 `<div class="form-field-help-tooltip">` TO lt_fragments.
APPEND li_html->icon(
iv_name = 'question-circle-solid'
iv_class = 'blue' ) TO lt_fragments.
APPEND `<div class="form-field-help-tooltip-text">` TO lt_fragments.
APPEND iv_text_to_wrap TO lt_fragments.
APPEND `</div>` TO lt_fragments.
APPEND `</div>` 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( |<div class="form-field-help-tooltip{ lv_add_class }">| ).
li_html->add_icon(
iv_name = 'question-circle-solid'
iv_class = 'blue' ).
li_html->add( `<div class="form-field-help-tooltip-text">` ).
li_html->add( iv_text_to_wrap ).
li_html->add( `</div>` ).
li_html->add( `</div>` ).
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( '<div class="dummydiv success">' ).
ri_html->add_icon( 'check' ).
ri_html->add( iv_message ).
ri_html->add( '</div>' ).
ENDMETHOD.
METHOD render_table_footer.
CREATE OBJECT ri_html TYPE zcl_abapgit_html.

View File

@ -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.
<ls_c>-from_field = to_upper( iv_from_field ).
<ls_c>-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 <lt_data> 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.
ASSIGN it_data TO <lt_data>.
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 <lt_data>.
<lt_data> = it_data.
apply_sorting( CHANGING ct_data = <lt_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( |<table{ lv_attrs }>| ).
render_thead( ).
render_tbody( it_data ).
render_tbody( <lt_data> ).
mi_html->add( '</table>' ).
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 <ls_col> LIKE LINE OF mt_columns.
FIELD-SYMBOLS <ls_grp> LIKE LINE OF mt_columns.
FIELD-SYMBOLS <lv_val> TYPE any.
LOOP AT mt_columns ASSIGNING <ls_col>.
IF <ls_col>-is_group = abap_true.
ASSIGN <ls_col> TO <ls_grp>.
CONTINUE.
ENDIF.
IF <ls_col>-from_field IS NOT INITIAL AND <ls_col>-from_field <> '-'.
ASSIGN COMPONENT <ls_col>-from_field OF STRUCTURE is_row TO <lv_val>.
IF sy-subrc <> 0.
@ -269,13 +395,17 @@ CLASS ZCL_ABAPGIT_HTML_TABLE IMPLEMENTATION.
iv_value = |{ <lv_val> }| ).
IF mv_with_cids = abap_true.
ls_cid = cid_attr( <ls_col>-column_id ).
CLEAR lt_attrs.
APPEND cid_attr( <ls_col>-column_id ) TO lt_attrs.
IF <ls_grp> IS ASSIGNED AND <ls_grp>-column_id IS NOT INITIAL.
APPEND gid_attr( <ls_grp>-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 <ls_col> LIKE LINE OF mt_columns.
DATA ls_cid TYPE zif_abapgit_html=>ty_data_attr.
FIELD-SYMBOLS <ls_grp> 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( '<thead>' ).
" Group headers
IF mr_last_grp IS NOT INITIAL. " Has groups
mi_html->add( '<tr>' ).
LOOP AT mt_columns ASSIGNING <ls_grp> WHERE is_group = abap_true.
IF mv_with_cids = abap_true AND <ls_grp>-column_id IS NOT INITIAL.
lv_grp_data = | data-gid="{ <ls_grp>-column_id }"|.
ELSE.
CLEAR lv_grp_data.
ENDIF.
IF <ls_grp>-group_span > 1.
ls_grp_span = | colspan="{ <ls_grp>-group_span }"|.
ELSE.
CLEAR ls_grp_span.
ENDIF.
mi_html->add( |<th{ ls_grp_span }{ lv_grp_data }>{ <ls_grp>-column_title }</th>| ).
ENDLOOP.
mi_html->add( '</tr>' ).
ENDIF.
" Regular headers
mi_html->add( '<tr>' ).
LOOP AT mt_columns ASSIGNING <ls_col>.
IF <ls_col>-is_group = abap_true.
ASSIGN <ls_col> TO <ls_grp>.
CONTINUE.
ENDIF.
IF mv_with_cids = abap_true.
ls_cid = cid_attr( <ls_col>-column_id ).
CLEAR lt_attrs.
APPEND cid_attr( <ls_col>-column_id ) TO lt_attrs.
IF <ls_grp> IS ASSIGNED AND <ls_grp>-column_id IS NOT INITIAL.
APPEND gid_attr( <ls_grp>-column_id ) TO lt_attrs.
ENDIF.
ENDIF.
mi_html->th(
iv_content = render_column_title( <ls_col> )
is_data_attr = ls_cid ).
it_data_attrs = lt_attrs ).
ENDLOOP.
mi_html->add( '</tr>' ).

View File

@ -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.
'<th>Col 2</th>' )->add(
'<th></th>' )->add(
'</tr>' )->add(
'</thead>' )->add(
'</thead>' ).
li_html_exp->add(
'<tbody>' )->add(
'<tr class="r1">' )->add(
'<td class="cell">Hello</td>' )->add(
@ -149,7 +151,8 @@ CLASS ltcl_test_simple_table IMPLEMENTATION.
'<th data-cid="col1">Col 1</th>' )->add(
'<th data-cid="col2">Col 2</th>' )->add(
'</tr>' )->add(
'</thead>' )->add(
'</thead>' ).
li_html_exp->add(
'<tbody>' )->add(
'<tr data-attr="1">' )->add(
'<td data-cid="col1">Hello</td>' )->add(
@ -200,12 +203,81 @@ CLASS ltcl_test_simple_table IMPLEMENTATION.
'<table id="with-sort">' )->add(
'<thead>' )->add(
'<tr>' )->add(
'<th><a href="sapevent:sort_by:col1:dsc">Col 1</a><span class="sort-arrow sort-active">&#x25BE;</span></th>'
)->add(
'<th><a href="sapevent:sort_by:col1:dsc">Col 1</a>' &&
'<span class="sort-arrow sort-active">&#x25BE;</span></th>' )->add(
'<th><a href="sapevent:sort_by:col2:asc">Col 2</a><span class="sort-arrow">&#x25BE;</span></th>' )->add(
'<th>Col 3</th>' )->add(
'</tr>' )->add(
'</thead>' )->add(
'</thead>' ).
li_html_exp->add(
'<tbody>' )->add(
'<tr>' )->add(
'<td>Hello</td>' )->add(
'<td>1</td>' )->add(
'<td>10</td>' )->add(
'</tr>' )->add(
'<tr>' )->add(
'<td>World</td>' )->add(
'<td>2</td>' )->add(
'<td>20</td>' )->add(
'</tr>' )->add(
'</tbody>' )->add(
'</table>' ).
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(
'<table id="with-sort">' )->add(
'<thead>' )->add(
'<tr>' )->add(
'<th></th>' )->add(
'<th colspan="2">Group</th>' )->add(
'</tr>' ).
li_html_exp->add(
'<tr>' )->add(
'<th><a href="sapevent:sort_by:col1:dsc">Col 1</a>' &&
'<span class="sort-arrow sort-active">&#x25BE;</span></th>' )->add(
'<th><a href="sapevent:sort_by:col2:asc">Col 2</a><span class="sort-arrow">&#x25BE;</span></th>' )->add(
'<th>Col 3</th>' )->add(
'</tr>' )->add(
'</thead>' ).
li_html_exp->add(
'<tbody>' )->add(
'<tr>' )->add(
'<td>Hello</td>' )->add(

View File

@ -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 <ls_i> LIKE LINE OF mt_items.
ls_hotkey_action-ui_component = iv_component_name.
LOOP AT mt_items ASSIGNING <ls_i> WHERE hotkey IS NOT INITIAL.
ls_hotkey_action-description = <ls_i>-txt.
ls_hotkey_action-action = <ls_i>-act.
ls_hotkey_action-hotkey = <ls_i>-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 <ls_item> LIKE LINE OF mt_items.
@ -212,9 +242,29 @@ CLASS zcl_abapgit_html_toolbar IMPLEMENTATION.
" Render items
LOOP AT mt_items ASSIGNING <ls_item>.
CLEAR: lv_class, lv_class_value, lv_icon.
lv_txt = <ls_item>-txt.
IF <ls_item>-hotkey IS NOT INITIAL.
ASSERT strlen( <ls_item>-hotkey ) = 1.
lv_hkidx = find(
val = lv_txt
sub = to_upper( <ls_item>-hotkey ) ).
IF lv_hkidx < 0.
lv_hkidx = find(
val = lv_txt
sub = <ls_item>-hotkey ).
ENDIF.
IF lv_hkidx >= 0.
lv_txt = replace(
val = lv_txt
off = lv_hkidx
len = 1
with = |<u>{ lv_txt+lv_hkidx(1) }</u>| ).
ENDIF.
ENDIF.
IF <ls_item>-typ = zif_abapgit_html=>c_action_type-separator.
ri_html->add( |<li class="separator">{ <ls_item>-txt }</li>| ).
ri_html->add( |<li class="separator">{ lv_txt }</li>| ).
CONTINUE.
ENDIF.
@ -250,7 +300,7 @@ CLASS zcl_abapgit_html_toolbar IMPLEMENTATION.
ri_html->add( |<li{ lv_class }{ lv_check }{ lv_aux }>| ).
IF <ls_item>-sub IS INITIAL.
ri_html->add_a( iv_txt = lv_icon && <ls_item>-txt
ri_html->add_a( iv_txt = lv_icon && lv_txt
iv_typ = <ls_item>-typ
iv_act = <ls_item>-act
iv_id = <ls_item>-id
@ -258,7 +308,7 @@ CLASS zcl_abapgit_html_toolbar IMPLEMENTATION.
iv_title = <ls_item>-title
iv_class = <ls_item>-class ).
ELSE.
ri_html->add_a( iv_txt = lv_icon && <ls_item>-txt
ri_html->add_a( iv_txt = lv_icon && lv_txt
iv_typ = zif_abapgit_html=>c_action_type-dummy
iv_act = ''
iv_id = <ls_item>-id

View File

@ -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( `<p>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.</p>`
)->add( `<p>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).</p>` ).
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 <ls_i> TYPE zcl_abapgit_where_used_tools=>ty_dependency.
ASSIGN is_row TO <ls_i>.
CASE iv_column_id.
WHEN 'dep_obj_name'.
rs_render-content = <ls_i>-dep_obj_name.
IF mv_show_used_obj = abap_true.
rs_render-content = rs_render-content && |<span class='used-obj'>{ <ls_i>-dep_used_obj }</span>|.
ENDIF.
WHEN 'obj_type'.
IF <ls_i>-obj_prog_type IS INITIAL.
rs_render-content = <ls_i>-obj_type.
ELSE.
rs_render-content = <ls_i>-obj_type && ':' && <ls_i>-obj_prog_type.
ENDIF.
WHEN 'obj_name'.
rs_render-content = zcl_abapgit_gui_chunk_lib=>get_item_link(
iv_obj_type = <ls_i>-obj_type
iv_obj_name = <ls_i>-obj_name ).
WHEN OTHERS.
rs_render-content = iv_value.
ENDCASE.
" TODO maybe add title for object cls ?
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_ABAPGIT_GUI_PAGE_WHEREUSED</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>abapGit where-used page</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -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 ).

View File

@ -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.

View File

@ -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%);
}

View File

@ -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',