From d4cbf7059e267c59dd094d2d27b419b314568d81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frederik=20Hud=C3=A1k?= Date: Mon, 14 Jun 2021 14:44:38 +0200 Subject: [PATCH] Repo overview - rework action buttons + cosmetic changes (#4771) * Repo overview - cosmetic changes * extract logic to method * Update src/ui/zcl_abapgit_gui_page_repo_over.clas.abap Co-authored-by: abaplint[bot] <24845621+abaplint[bot]@users.noreply.github.com> * fix if in if * unshorten remote, move package, improve wrapping * Add max width for columns * Mostly working now * add prefixes * Remove checkbox, move package where it was * Keyboard navigation < > to navigate in list (arrow keys don't seem to trigger), enter to open selected * Ellipsis for repo url, use css variable * Fix css, js persistence * Fix invalid function name * add back !important to override hover color * abaplint * Don't use const in js * more eslint * Remove unused field symbol * eslint * Bring back repo lock icon, styling improvements Co-authored-by: Marc Bernard <59966492+mbtools@users.noreply.github.com> --- src/ui/core/zcl_abapgit_html.clas.abap | 20 +- src/ui/zabapgit_css_common.w3mi.data.css | 24 +- src/ui/zabapgit_css_theme_dark.w3mi.data.css | 4 + .../zabapgit_css_theme_default.w3mi.data.css | 13 +- src/ui/zabapgit_js_common.w3mi.data.js | 184 ++++++- .../zcl_abapgit_gui_page_repo_over.clas.abap | 451 +++++++++++------- 6 files changed, 477 insertions(+), 219 deletions(-) diff --git a/src/ui/core/zcl_abapgit_html.clas.abap b/src/ui/core/zcl_abapgit_html.clas.abap index f102c4fef..8e32381ea 100644 --- a/src/ui/core/zcl_abapgit_html.clas.abap +++ b/src/ui/core/zcl_abapgit_html.clas.abap @@ -17,6 +17,12 @@ CLASS zcl_abapgit_html DEFINITION !iv_onclick TYPE string OPTIONAL RETURNING VALUE(rv_str) TYPE string . + CLASS-METHODS checkbox + IMPORTING + iv_id TYPE string OPTIONAL + iv_checked TYPE abap_bool OPTIONAL + RETURNING + VALUE(rv_html) TYPE string . PROTECTED SECTION. PRIVATE SECTION. @@ -58,17 +64,11 @@ CLASS zcl_abapgit_html DEFINITION !is_context TYPE ty_indent_context RETURNING VALUE(rs_result) TYPE ty_study_result . - METHODS checkbox - IMPORTING - !iv_id TYPE string - !iv_checked TYPE abap_bool OPTIONAL - RETURNING - VALUE(rv_html) TYPE string . ENDCLASS. -CLASS ZCL_ABAPGIT_HTML IMPLEMENTATION. +CLASS zcl_abapgit_html IMPLEMENTATION. METHOD checkbox. @@ -79,8 +79,12 @@ CLASS ZCL_ABAPGIT_HTML IMPLEMENTATION. lv_checked = |checked|. ENDIF. - rv_html = ||. + rv_html = |`. ENDMETHOD. diff --git a/src/ui/zabapgit_css_common.w3mi.data.css b/src/ui/zabapgit_css_common.w3mi.data.css index 6ed872138..536ab6511 100644 --- a/src/ui/zabapgit_css_common.w3mi.data.css +++ b/src/ui/zabapgit_css_common.w3mi.data.css @@ -297,7 +297,7 @@ table.repo_tab { .repo_tab tr:first-child td { border-top: 0px; } .repo_tab tr:hover { - background-color: rgb(245, 245, 245) !important; + background-color: var(--theme-greyscale-dark) !important; } @@ -560,6 +560,9 @@ div.db_list { overflow-x: auto; } +table.db_tab{ + table-layout: fixed; +} table.db_tab pre { display: inline-block; overflow: hidden; @@ -578,11 +581,29 @@ table.db_tab th { table.db_tab td { padding: 4px 8px; vertical-align: middle; + word-break: break-all; + max-width: 250px; } + +table.db_tab th.package { + width: 45ch; +} + table.db_tab td.data { font-style: italic; } +span.action_link.enabled{ + visibility: visible; + position: relative; +} + +span.action_link:not(enabled){ + visibility: hidden; + position: fixed; /* so it does not take up space when hidden */ +} + + /* DB ENTRY DISPLAY */ div.db_entry { padding: 0.5em; @@ -933,7 +954,6 @@ table.commit tr .title { .repo-overview { font-size: smaller; } .repo-overview tbody td { height: 2em; } .ro-detail { display: none; } -.ro-action { width: 260px; } .ro-go { font-size: 150%; } /* Branch Overview Page */ diff --git a/src/ui/zabapgit_css_theme_dark.w3mi.data.css b/src/ui/zabapgit_css_theme_dark.w3mi.data.css index fb30d074d..cb5cdd08e 100644 --- a/src/ui/zabapgit_css_theme_dark.w3mi.data.css +++ b/src/ui/zabapgit_css_theme_dark.w3mi.data.css @@ -168,6 +168,10 @@ table.db_tab th { border-bottom-color: #333; } +table.db_tab tr.selected { + background: rgba(92, 92, 92, 1) !important; +} + /* ERROR LOGS */ div.log { color: var(--theme-greyscale-dark); } .close-btn, .message-panel, .message-panel-commands a { color: var(--theme-greyscale-dark); } diff --git a/src/ui/zabapgit_css_theme_default.w3mi.data.css b/src/ui/zabapgit_css_theme_default.w3mi.data.css index 8fae68936..ac1233363 100644 --- a/src/ui/zabapgit_css_theme_default.w3mi.data.css +++ b/src/ui/zabapgit_css_theme_default.w3mi.data.css @@ -28,6 +28,11 @@ body { font-size: var(--theme-font-size); } a, a:visited { color: var(--theme-link-color); } +.link { + color: var(--theme-link-color); + cursor: pointer; +} + input, textarea, select { border-color: #ddd; } input:focus, textarea:focus { border-color: #8cadd9; } @@ -341,8 +346,8 @@ table.diff_tab td.patch, th.patch { .syntax-hl span.variables { color:purple; } /* DEBUG INFO STYLES */ -div.debug_container { - color: #444; +div.debug_container { + color: #444; background-color: var(--theme-container-background-color); } @@ -356,6 +361,10 @@ table.db_tab th { border-bottom-color: #ddd; } +table.db_tab tr.selected { + background-color: rgba(191, 191, 191, 1) !important; +} + /* DB ENTRY DISPLAY */ div.db_entry { background-color: var(--theme-container-background-color); diff --git a/src/ui/zabapgit_js_common.w3mi.data.js b/src/ui/zabapgit_js_common.w3mi.data.js index cfc3a42bb..b4d6a6f2d 100644 --- a/src/ui/zabapgit_js_common.w3mi.data.js +++ b/src/ui/zabapgit_js_common.w3mi.data.js @@ -86,6 +86,12 @@ if (!String.prototype.startsWith) { }); } +// forEach polyfill, taken from https://developer.mozilla.org +// used for querySelectorAll results +if (window.NodeList && !NodeList.prototype.forEach) { + NodeList.prototype.forEach = Array.prototype.forEach; +} + /********************************************************** * Common functions **********************************************************/ @@ -250,16 +256,161 @@ function RepoOverViewHelper() { this.toggleFilterIcon(icon, this.isDetailsDisplayed); icon = document.getElementById("icon-filter-favorite"); this.toggleFilterIcon(icon, this.isOnlyFavoritesDisplayed); + this.registerRowSelection(); + this.registerKeyboardShortcuts(); } +RepoOverViewHelper.prototype.setHooks = function () { + window.onload = this.onPageLoad.bind(this); +}; + +RepoOverViewHelper.prototype.onPageLoad = function () { + var data = window.localStorage && JSON.parse(window.localStorage.getItem(this.pageId)); + if (data) { + if (data.isDetailsDisplayed) { + this.toggleItemsDetail(true); + } + if (data.isOnlyFavoritesDisplayed) { + this.toggleItemsFavorites(true); + } + if (data.selectedRepoKey) { + this.selectRowByRepoKey(data.selectedRepoKey); + } else { + this.selectRowByIndex(0); + } + } +}; + +RepoOverViewHelper.prototype.registerKeyboardShortcuts = function () { + var self = this; + document.addEventListener("keypress", function (event) { + if (document.activeElement.id === "filter") { + return; + } + var keycode = event.keyCode; + var rows = Array.prototype.slice.call(self.getVisibleRows()); + var selected = document.querySelector(".repo.selected"); + var indexOfSelected = rows.indexOf(selected); + + if (keycode == 13) { + // "enter" to open + self.openSelectedRepo(); + } + else if (keycode == 44 && indexOfSelected > 0) { + // "<" for previous + self.selectRowByIndex(indexOfSelected - 1); + } else if (keycode == 46 && indexOfSelected < rows.length - 1) { + // ">" for next + self.selectRowByIndex(indexOfSelected + 1); + } + }); +}; + +RepoOverViewHelper.prototype.openSelectedRepo = function () { + this.selectedRepoKey = document.querySelector(".repo.selected").dataset.key; + this.saveLocalStorage(); + document.querySelector(".repo.selected td.ro-go a").click(); +}; + +RepoOverViewHelper.prototype.selectRowByIndex = function (index) { + var rows = this.getVisibleRows(); + if (rows.length >= index) { + var selectedRow = rows[index]; + if (selectedRow.classList.contains("selected")) { + return; + } + + this.deselectAllRows(); + rows[index].classList.add("selected"); + this.selectedRepoKey = selectedRow.dataset.key; + this.updateActionLinks(selectedRow); + this.saveLocalStorage(); + } +}; + +RepoOverViewHelper.prototype.selectRowByRepoKey = function (key) { + var attributeQuery = "[data-key='" + key + "']"; + var row = document.querySelector(".repo" + attributeQuery); + // navigation to already selected repo + if (row.dataset.key === key && row.classList.contains("selected")) { + return; + } + + this.deselectAllRows(); + row.classList.add("selected"); + this.selectedRepoKey = key; + this.updateActionLinks(row); + this.saveLocalStorage(); +}; + +RepoOverViewHelper.prototype.updateActionLinks = function (selectedRow) { + // now we have a repo selected, determine which action buttons are relevant + var selectedRepoKey = selectedRow.dataset.key; + var selectedRepoIsOffline = selectedRow.dataset.offline === "X"; + + var actionLinks = document.querySelectorAll("a.action_link"); + actionLinks.forEach(function (link) { + // adjust repo key in urls + link.href = link.href.replace(/\?key=(#|\d+)/, "?key=" + selectedRepoKey); + + // toggle button visibility + if (link.classList.contains("action_offline_repo")) { + if (selectedRepoIsOffline) { + link.parentElement.classList.add("enabled"); + } else { + link.parentElement.classList.remove("enabled"); + } + } + else if (link.classList.contains("action_online_repo")) { + if (!selectedRepoIsOffline) { + link.parentElement.classList.add("enabled"); + } else { + link.parentElement.classList.remove("enabled"); + } + } + else { + // if the action is for both repository types, it will only have the .action_link class + // it still needs to be toggled as we want to hide everything if no repo is selected + link.parentElement.classList.add("enabled"); + } + }); +}; + +RepoOverViewHelper.prototype.deselectAllRows = function () { + document.querySelectorAll(".repo").forEach(function (x) { + x.classList.remove("selected"); + }); +}; + +RepoOverViewHelper.prototype.getVisibleRows = function () { + return document.querySelectorAll(".repo:not(.nodisplay)"); +}; + +RepoOverViewHelper.prototype.registerRowSelection = function () { + var self = this; + document.querySelectorAll(".repo td:not(.ro-go)").forEach(function (repoListRowCell) { + repoListRowCell.addEventListener("click", function () { + self.selectRowByRepoKey(this.parentElement.dataset.key); + }); + }); + + document.querySelectorAll(".repo td.ro-go").forEach(function (openRepoIcon) { + openRepoIcon.addEventListener("click", function () { + var selectedRow = this.parentElement; + self.selectRowByRepoKey(selectedRow.dataset.key); + self.openSelectedRepo(); + }); + }); +}; + RepoOverViewHelper.prototype.toggleRepoListDetail = function (forceDisplay) { if (this.detailCssClass) { this.toggleItemsDetail(forceDisplay); - this.saveFilter(); + this.saveLocalStorage(); } }; -RepoOverViewHelper.prototype.toggleItemsDetail = function(forceDisplay){ +RepoOverViewHelper.prototype.toggleItemsDetail = function (forceDisplay) { if (this.detailCssClass) { this.isDetailsDisplayed = forceDisplay || !this.isDetailsDisplayed; @@ -273,7 +424,6 @@ RepoOverViewHelper.prototype.toggleItemsDetail = function(forceDisplay){ } this.detailCssClass.style.display = this.isDetailsDisplayed ? "" : "none"; - this.actionCssClass.style.display = this.isDetailsDisplayed ? "none" : ""; var icon = document.getElementById("icon-filter-detail"); this.toggleFilterIcon(icon, this.isDetailsDisplayed); } @@ -291,10 +441,10 @@ RepoOverViewHelper.prototype.toggleFilterIcon = function (icon, isEnabled) { RepoOverViewHelper.prototype.toggleRepoListFavorites = function (forceDisplay) { this.toggleItemsFavorites(forceDisplay); - this.saveFilter(); + this.saveLocalStorage(); }; -RepoOverViewHelper.prototype.toggleItemsFavorites = function(forceDisplay){ +RepoOverViewHelper.prototype.toggleItemsFavorites = function (forceDisplay) { this.isOnlyFavoritesDisplayed = forceDisplay || !this.isOnlyFavoritesDisplayed; var repositories = document.getElementsByClassName("repo"); var icon = document.getElementById("icon-filter-favorite"); @@ -303,38 +453,24 @@ RepoOverViewHelper.prototype.toggleItemsFavorites = function(forceDisplay){ var repo = repositories[i]; if (this.isOnlyFavoritesDisplayed) { if (!repo.classList.contains("favorite")) { - repo.style.display = "none"; + repo.classList.add("nodisplay"); } } else { - repo.style.display = ""; + repo.classList.remove("nodisplay"); } } }; -RepoOverViewHelper.prototype.setHooks = function () { - window.onload = this.onPageLoad.bind(this); -}; - -RepoOverViewHelper.prototype.saveFilter = function () { +RepoOverViewHelper.prototype.saveLocalStorage = function () { if (!window.localStorage) return; var data = { isDetailsDisplayed: this.isDetailsDisplayed, - isOnlyFavoritesDisplayed: this.isOnlyFavoritesDisplayed + isOnlyFavoritesDisplayed: this.isOnlyFavoritesDisplayed, + selectedRepoKey: this.selectedRepoKey, }; window.localStorage.setItem(this.pageId, JSON.stringify(data)); }; -RepoOverViewHelper.prototype.onPageLoad = function () { - var data = window.localStorage && JSON.parse(window.localStorage.getItem(this.pageId)); - if (data) { - if (data.isDetailsDisplayed) { - this.toggleItemsDetail(true); - } - if (data.isOnlyFavoritesDisplayed) { - this.toggleItemsFavorites(true); - } - } -}; /********************************************************** * STAGE PAGE Logic diff --git a/src/ui/zcl_abapgit_gui_page_repo_over.clas.abap b/src/ui/zcl_abapgit_gui_page_repo_over.clas.abap index 27a587d4c..174bcb033 100644 --- a/src/ui/zcl_abapgit_gui_page_repo_over.clas.abap +++ b/src/ui/zcl_abapgit_gui_page_repo_over.clas.abap @@ -26,7 +26,6 @@ CLASS zcl_abapgit_gui_page_repo_over DEFINITION PRIVATE SECTION. - TYPES: BEGIN OF ty_overview, favorite TYPE string, @@ -42,73 +41,95 @@ CLASS zcl_abapgit_gui_page_repo_over DEFINITION deserialized_by TYPE xubname, deserialized_at TYPE string, write_protected TYPE abap_bool, - END OF ty_overview . - TYPES: + END OF ty_overview, ty_overviews TYPE STANDARD TABLE OF ty_overview - WITH NON-UNIQUE DEFAULT KEY . - + WITH NON-UNIQUE DEFAULT KEY. CONSTANTS: BEGIN OF c_action, select TYPE string VALUE 'select', apply_filter TYPE string VALUE 'apply_filter', END OF c_action . - DATA mv_order_descending TYPE abap_bool . - DATA mv_filter TYPE string . - DATA mv_time_zone TYPE timezone . - DATA mt_col_spec TYPE zif_abapgit_definitions=>ty_col_spec_tt . - DATA mt_overview TYPE ty_overviews . - METHODS render_text_input - IMPORTING - !iv_name TYPE string - !iv_label TYPE string - !iv_value TYPE string OPTIONAL - !iv_max_length TYPE string OPTIONAL - !iv_autofocus TYPE abap_bool DEFAULT abap_false - RETURNING - VALUE(ri_html) TYPE REF TO zif_abapgit_html . - METHODS apply_filter - CHANGING - !ct_overview TYPE ty_overviews . - METHODS map_repo_list_to_overview - RETURNING - VALUE(rt_overview) TYPE ty_overviews - RAISING - zcx_abapgit_exception . - METHODS render_table_header - IMPORTING - !ii_html TYPE REF TO zif_abapgit_html . - METHODS render_table - IMPORTING - !ii_html TYPE REF TO zif_abapgit_html - !it_overview TYPE ty_overviews - RAISING - zcx_abapgit_exception . - METHODS render_table_body - IMPORTING - !ii_html TYPE REF TO zif_abapgit_html - !it_overview TYPE ty_overviews - RAISING - zcx_abapgit_exception . - METHODS render_header_bar - IMPORTING - !ii_html TYPE REF TO zif_abapgit_html . - METHODS apply_order_by - CHANGING - !ct_overview TYPE ty_overviews . - METHODS _add_column - IMPORTING - !iv_tech_name TYPE string OPTIONAL - !iv_display_name TYPE string OPTIONAL - !iv_css_class TYPE string OPTIONAL - !iv_add_tz TYPE abap_bool OPTIONAL - !iv_title TYPE string OPTIONAL - !iv_allow_order_by TYPE any OPTIONAL . + DATA: mv_order_descending TYPE abap_bool, + mv_filter TYPE string, + mv_time_zone TYPE timezone, + mt_col_spec TYPE zif_abapgit_definitions=>ty_col_spec_tt, + mt_overview TYPE ty_overviews. + + METHODS: render_text_input + IMPORTING iv_name TYPE string + iv_label TYPE string + iv_value TYPE string OPTIONAL + iv_max_length TYPE string OPTIONAL + !iv_autofocus TYPE abap_bool DEFAULT abap_false + RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html, + + apply_filter + CHANGING + ct_overview TYPE ty_overviews, + + map_repo_list_to_overview + RETURNING + VALUE(rt_overview) TYPE ty_overviews + RAISING + zcx_abapgit_exception, + + render_table_header + IMPORTING + ii_html TYPE REF TO zif_abapgit_html, + + render_table + IMPORTING + ii_html TYPE REF TO zif_abapgit_html + it_overview TYPE ty_overviews + RAISING + zcx_abapgit_exception, + + render_table_body + IMPORTING + ii_html TYPE REF TO zif_abapgit_html + it_repo_list TYPE ty_overviews + RAISING + zcx_abapgit_exception, + + render_header_bar + IMPORTING + ii_html TYPE REF TO zif_abapgit_html, + + apply_order_by + CHANGING ct_overview TYPE ty_overviews, + + _add_column + IMPORTING + iv_tech_name TYPE string OPTIONAL + iv_display_name TYPE string OPTIONAL + iv_css_class TYPE string OPTIONAL + iv_add_tz TYPE abap_bool OPTIONAL + iv_title TYPE string OPTIONAL + iv_allow_order_by TYPE any OPTIONAL. + METHODS render_scripts RETURNING VALUE(ri_html) TYPE REF TO zif_abapgit_html RAISING - zcx_abapgit_exception . + zcx_abapgit_exception. + + METHODS shorten_repo_url + IMPORTING iv_full_url TYPE string + iv_max_length TYPE i DEFAULT 60 + RETURNING VALUE(rv_shortened) TYPE string. + + METHODS render_actions + IMPORTING ii_html TYPE REF TO zif_abapgit_html. + + METHODS column + IMPORTING iv_content TYPE string OPTIONAL + iv_css_class TYPE string OPTIONAL + RETURNING VALUE(rv_html) TYPE string. + + METHODS action_link + IMPORTING iv_content TYPE string + RETURNING VALUE(rv_html) TYPE string. ENDCLASS. @@ -178,9 +199,9 @@ CLASS zcl_abapgit_gui_page_repo_over IMPLEMENTATION. METHOD map_repo_list_to_overview. - DATA: ls_overview LIKE LINE OF rt_overview, - lv_date TYPE d, - lv_time TYPE t, + DATA: ls_overview LIKE LINE OF rt_overview, + lv_date TYPE d, + lv_time TYPE t, lt_repo_obj_list TYPE zif_abapgit_repo_srv=>ty_repo_list. FIELD-SYMBOLS LIKE LINE OF lt_repo_obj_list. @@ -255,6 +276,8 @@ CLASS zcl_abapgit_gui_page_repo_over IMPLEMENTATION. iv_act = |gHelper.toggleRepoListDetail()| iv_typ = zif_abapgit_html=>c_action_type-onclick ) ). + render_actions( ii_html = ii_html ). + ii_html->add( || ). ENDMETHOD. @@ -274,11 +297,11 @@ CLASS zcl_abapgit_gui_page_repo_over IMPLEMENTATION. METHOD render_table. ii_html->add( |
| ). - ii_html->add( || ). + ii_html->add( |
| ). render_table_header( ii_html ). render_table_body( ii_html = ii_html - it_overview = it_overview ). + it_repo_list = it_overview ). ii_html->add( |
| ). ii_html->add( |
| ). @@ -288,35 +311,33 @@ CLASS zcl_abapgit_gui_page_repo_over IMPLEMENTATION. METHOD render_table_body. - CONSTANTS: lc_separator TYPE string VALUE `|`. - DATA: - lv_type_icon TYPE string, - lv_favorite_icon TYPE string, - lv_favorite_class TYPE string, - lv_stage_link TYPE string, - lv_patch_link TYPE string, - lv_zip_import_link TYPE string, - lv_zip_export_link TYPE string, - lv_check_link TYPE string, - lv_text TYPE string, - lv_lock TYPE string, - lv_settings_link TYPE string. - DATA lv_new_length TYPE i. + lv_type_icon TYPE string, + lv_favorite_icon TYPE string, + lv_favorite_class TYPE string, + lv_stage_link TYPE string, + lv_patch_link TYPE string, + lv_zip_import_link TYPE string, + lv_zip_export_link TYPE string, + lv_check_link TYPE string, + lv_text TYPE string, + lv_lock TYPE string, + lv_toggle_favorite_link TYPE string, + lv_repo_go_link TYPE string. - FIELD-SYMBOLS: LIKE LINE OF it_overview. + FIELD-SYMBOLS: LIKE LINE OF it_repo_list. ii_html->add( '' ). - LOOP AT it_overview ASSIGNING . + LOOP AT it_repo_list ASSIGNING . - IF -type = abap_true. + IF -type = abap_true. lv_type_icon = 'plug/darkgrey'. ELSE. lv_type_icon = 'cloud-upload-alt/darkgrey'. ENDIF. - IF -favorite = abap_true. + IF -favorite = abap_true. lv_favorite_icon = 'star/blue'. lv_favorite_class = 'favorite'. ELSE. @@ -324,119 +345,91 @@ CLASS zcl_abapgit_gui_page_repo_over IMPLEMENTATION. lv_favorite_class = ''. ENDIF. - ii_html->add( || ). - ii_html->add( || ). - ii_html->add_a( iv_act = |{ zif_abapgit_definitions=>c_action-repo_toggle_fav }?key={ -key }| - iv_txt = ii_html->icon( iv_name = lv_favorite_icon - iv_class = 'pad-sides' - iv_hint = 'Click to toggle favorite' ) ). - ii_html->add( || ). + ii_html->add( + || ). + + lv_toggle_favorite_link = ii_html->a( + iv_act = |{ zif_abapgit_definitions=>c_action-repo_toggle_fav }?key={ -key }| + iv_txt = ii_html->icon( iv_name = lv_favorite_icon + iv_class = 'pad-sides' + iv_hint = 'Click to toggle favorite' ) ). + + ii_html->add( + column( iv_content = lv_toggle_favorite_link + iv_css_class = 'wmin' ) ). + CLEAR lv_lock. - IF -write_protected = abap_true. + IF -write_protected = abap_true. lv_lock = ii_html->icon( iv_name = 'lock/grey70' iv_class = 'm-em5-sides' iv_hint = 'Locked from pulls' ). ENDIF. - ii_html->add( |{ ii_html->icon( lv_type_icon ) }| ). + ii_html->add( + column( iv_content = ii_html->icon( lv_type_icon ) + iv_css_class = 'wmin' ) ). - ii_html->add( |{ ii_html->a( iv_txt = -name - iv_act = |{ c_action-select }?key={ -key }| ) }{ lv_lock }| ). + ii_html->add( + column( iv_content = ii_html->a( iv_txt = -name + iv_act = |{ c_action-select }?key={ -key }| ) && lv_lock ) ). - IF -type = abap_false. - lv_text = -url. - REPLACE FIRST OCCURRENCE OF 'https://' IN lv_text WITH ''. - REPLACE FIRST OCCURRENCE OF 'http://' IN lv_text WITH ''. - IF lv_text CP '*.git'. - lv_new_length = strlen( lv_text ) - 4. - lv_text = lv_text(lv_new_length). - ENDIF. - ii_html->add( |{ ii_html->a( + ii_html->add( + column( iv_content = zcl_abapgit_gui_chunk_lib=>render_package_name( + iv_package = -package + iv_suppress_title = abap_true )->render( ) ) ). + + IF -type = abap_false. + lv_text = shorten_repo_url( -url ). + ii_html->add( column( iv_content = |{ ii_html->a( iv_txt = lv_text - iv_title = -url - iv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ -url }| ) }| ). + iv_title = -url + iv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ -url }| ) }| ) ). ELSE. - ii_html->add( || ). + ii_html->add( column( ) ). ENDIF. - ii_html->add( || ). - ii_html->add( zcl_abapgit_gui_chunk_lib=>render_package_name( - iv_package = -package - iv_suppress_title = abap_true ) ). - ii_html->add( || ). - - IF -branch IS INITIAL. - ii_html->add( | | ). + IF -branch IS INITIAL. + ii_html->add( column( iv_content = | | ) ). ELSE. - ii_html->add( || ). - ii_html->add( zcl_abapgit_gui_chunk_lib=>render_branch_name( - iv_branch = -branch - iv_repo_key = -key ) ). - ii_html->add( || ). + ii_html->add( + column( iv_content = zcl_abapgit_gui_chunk_lib=>render_branch_name( + iv_branch = -branch + iv_repo_key = -key )->render( ) ) ). ENDIF. - ii_html->add( || ). - ii_html->add( zcl_abapgit_gui_chunk_lib=>render_user_name( - iv_username = -deserialized_by - iv_suppress_title = abap_true ) ). - ii_html->add( || ). - ii_html->add( |{ -deserialized_at }| ). - ii_html->add( || ). - ii_html->add( zcl_abapgit_gui_chunk_lib=>render_user_name( - iv_username = -created_by - iv_suppress_title = abap_true ) ). - ii_html->add( || ). - ii_html->add( |{ -created_at }| ). - ii_html->add( |{ -key }| ). + ii_html->add( + column( iv_content = zcl_abapgit_gui_chunk_lib=>render_user_name( + iv_username = -deserialized_by + iv_suppress_title = abap_true )->render( ) + iv_css_class = 'ro-detail' ) ). - ii_html->add( | | ). + ii_html->add( + column( iv_content = -deserialized_at + iv_css_class = 'ro-detail' ) ). - lv_check_link = ii_html->a( - iv_txt = |Check| - iv_act = |{ zif_abapgit_definitions=>c_action-repo_code_inspector }?key={ -key } | ). + ii_html->add( + column( iv_content = zcl_abapgit_gui_chunk_lib=>render_user_name( + iv_username = -created_by + iv_suppress_title = abap_true )->render( ) + iv_css_class = 'ro-detail' ) ). - ii_html->add( lv_check_link && lc_separator ). + ii_html->add( + column( iv_content = -created_at + iv_css_class = 'ro-detail' ) ). - IF -type = abap_false. " online repo - lv_stage_link = ii_html->a( - iv_txt = |Stage| - iv_act = |{ zif_abapgit_definitions=>c_action-go_stage }?key={ -key } | ). + ii_html->add( + column( iv_content = |{ -key }| + iv_css_class = 'ro-detail' ) ). - ii_html->add( lv_stage_link && lc_separator ). + " the link is clicked in javascript + lv_repo_go_link = ii_html->a( + iv_txt = `` + iv_act = |{ c_action-select }?key={ -key }| + iv_class = 'hidden' ). - lv_patch_link = ii_html->a( - iv_txt = |Patch| - iv_act = |{ zif_abapgit_definitions=>c_action-go_patch }?key={ -key } | ). - - ii_html->add( lv_patch_link && lc_separator ). - ELSE. " offline repo - lv_zip_import_link = ii_html->a( - iv_txt = |Import| - iv_act = |{ zif_abapgit_definitions=>c_action-zip_import }?key={ -key } | ). - - ii_html->add( lv_zip_import_link && lc_separator ). - - lv_zip_export_link = ii_html->a( - iv_txt = |Export| - iv_act = |{ zif_abapgit_definitions=>c_action-zip_export }?key={ -key } | ). - - ii_html->add( lv_zip_export_link && lc_separator ). - ENDIF. - - lv_settings_link = ii_html->a( - iv_txt = |Settings| - iv_act = |{ zif_abapgit_definitions=>c_action-repo_settings }?key={ -key } | ). - - ii_html->add( lv_settings_link ). - - ii_html->add( || ). - - ii_html->add( |{ - ii_html->a( - iv_txt = `›` - iv_act = |{ c_action-select }?key={ -key }| ) }| ). - - ii_html->add( || ). + ii_html->add( column( + iv_content = |›{ lv_repo_go_link }| + iv_css_class = 'ro-go' ) ). ENDLOOP. @@ -444,6 +437,91 @@ CLASS zcl_abapgit_gui_page_repo_over IMPLEMENTATION. ENDMETHOD. + METHOD render_actions. + + CONSTANTS: + lc_separator TYPE string VALUE `|`, + lc_dummy_key TYPE string VALUE `?key=#`, + lc_offline_class TYPE string VALUE `action_offline_repo`, + lc_online_class TYPE string VALUE `action_online_repo`, + lc_action_class TYPE string VALUE `action_link`. + + DATA: + lv_settings_link TYPE string, + lv_check_link TYPE string, + lv_stage_link TYPE string, + lv_patch_link TYPE string. + + DATA: + lv_zip_import_link TYPE string, + lv_zip_export_link TYPE string. + + ii_html->add( |
| ). + + lv_check_link = ii_html->a( + iv_txt = |Check| + iv_act = |{ zif_abapgit_definitions=>c_action-repo_code_inspector }{ lc_dummy_key }| + iv_class = |{ lc_action_class }| ). + + ii_html->add( action_link( lv_check_link && lc_separator ) ). + + lv_stage_link = ii_html->a( + iv_txt = |Stage| + iv_act = |{ zif_abapgit_definitions=>c_action-go_stage }{ lc_dummy_key }| + iv_class = |{ lc_action_class } { lc_online_class } | ). + + ii_html->add( action_link( lv_stage_link && lc_separator ) ). + + lv_patch_link = ii_html->a( + iv_txt = |Patch| + iv_act = |{ zif_abapgit_definitions=>c_action-go_patch }{ lc_dummy_key }| + iv_class = |{ lc_action_class } { lc_online_class } | ). + + ii_html->add( action_link( lv_patch_link && lc_separator ) ). + + lv_zip_import_link = ii_html->a( + iv_txt = |Import| + iv_act = |{ zif_abapgit_definitions=>c_action-zip_import }{ lc_dummy_key }| + iv_class = |{ lc_action_class } { lc_offline_class }| ). + + ii_html->add( action_link( lv_zip_import_link && lc_separator ) ). + + lv_zip_export_link = ii_html->a( + iv_txt = |Export| + iv_act = |{ zif_abapgit_definitions=>c_action-zip_export }{ lc_dummy_key }| + iv_class = |{ lc_action_class } { lc_offline_class }| ). + + ii_html->add( action_link( lv_zip_export_link && lc_separator ) ). + + lv_settings_link = ii_html->a( + iv_txt = |Settings| + iv_act = |{ zif_abapgit_definitions=>c_action-repo_settings }{ lc_dummy_key }| + iv_class = |{ lc_action_class }| ). + + ii_html->add( action_link( lv_settings_link ) ). + + ii_html->add( |
| ). + ENDMETHOD. + + METHOD shorten_repo_url. + DATA lt_results TYPE match_result_tab. + DATA lv_new_length TYPE i. + DATA: lv_length_to_truncate_to TYPE i. + + rv_shortened = iv_full_url. + + REPLACE FIRST OCCURRENCE OF 'https://' IN rv_shortened WITH ''. + REPLACE FIRST OCCURRENCE OF 'http://' IN rv_shortened WITH ''. + IF rv_shortened CP '*.git'. + lv_new_length = strlen( rv_shortened ) - 4. + rv_shortened = rv_shortened(lv_new_length). + ENDIF. + + IF strlen( rv_shortened ) > iv_max_length. + lv_length_to_truncate_to = iv_max_length - 3. + rv_shortened = rv_shortened(lv_length_to_truncate_to) && `...`. + ENDIF. + ENDMETHOD. METHOD render_table_header. @@ -465,13 +543,14 @@ CLASS zcl_abapgit_gui_page_repo_over IMPLEMENTATION. iv_allow_order_by = abap_true ). _add_column( - iv_tech_name = 'URL' - iv_display_name = 'Url' + iv_tech_name = 'PACKAGE' + iv_display_name = 'Package' + iv_css_class = 'package' iv_allow_order_by = abap_true ). _add_column( - iv_tech_name = 'PACKAGE' - iv_display_name = 'Package' + iv_tech_name = 'URL' + iv_display_name = 'Remote' iv_allow_order_by = abap_true ). _add_column( @@ -497,7 +576,6 @@ CLASS zcl_abapgit_gui_page_repo_over IMPLEMENTATION. iv_css_class = 'ro-detail' iv_allow_order_by = abap_true ). - _add_column( iv_tech_name = 'CREATED_AT' iv_display_name = 'Created at' @@ -511,12 +589,6 @@ CLASS zcl_abapgit_gui_page_repo_over IMPLEMENTATION. iv_css_class = 'ro-detail' iv_allow_order_by = abap_true ). - _add_column( - iv_tech_name = 'ACTION' - iv_display_name = 'Action' - iv_css_class = 'ro-action' - iv_allow_order_by = abap_false ). - _add_column( iv_tech_name = 'GO' iv_css_class = 'ro-go' @@ -618,4 +690,17 @@ CLASS zcl_abapgit_gui_page_repo_over IMPLEMENTATION. -add_tz = iv_add_tz. -allow_order_by = iv_allow_order_by. ENDMETHOD. + + METHOD column. + IF iv_css_class IS NOT INITIAL. + rv_html = || && iv_content && ||. + ELSE. + rv_html = || && iv_content && ||. + ENDIF. + ENDMETHOD. + + METHOD action_link. + rv_html = || && iv_content && ||. + ENDMETHOD. + ENDCLASS.