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>
This commit is contained in:
Frederik Hudák 2021-06-14 14:44:38 +02:00 committed by GitHub
parent 6f8e3f45fa
commit d4cbf7059e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 477 additions and 219 deletions

View File

@ -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 = |<input type="checkbox" id="{ iv_id }" { lv_checked }>|.
rv_html = |<input type="checkbox" { lv_checked } |.
IF iv_id IS NOT INITIAL.
rv_html = rv_html && |id="{ iv_id }"|.
ENDIF.
rv_html = rv_html && `/>`.
ENDMETHOD.

View File

@ -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 */

View File

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

View File

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

View File

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

View File

@ -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 <ls_repo> 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( |</div>| ).
ENDMETHOD.
@ -274,11 +297,11 @@ CLASS zcl_abapgit_gui_page_repo_over IMPLEMENTATION.
METHOD render_table.
ii_html->add( |<div class="db_list repo-overview">| ).
ii_html->add( |<table class="db_tab w100">| ).
ii_html->add( |<table class="db_tab">| ).
render_table_header( ii_html ).
render_table_body( ii_html = ii_html
it_overview = it_overview ).
it_repo_list = it_overview ).
ii_html->add( |</table>| ).
ii_html->add( |</div>| ).
@ -288,35 +311,33 @@ CLASS zcl_abapgit_gui_page_repo_over IMPLEMENTATION.
METHOD render_table_body.
CONSTANTS: lc_separator TYPE string VALUE `<span class="separator">|</span>`.
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: <ls_overview> LIKE LINE OF it_overview.
FIELD-SYMBOLS: <ls_repo> LIKE LINE OF it_repo_list.
ii_html->add( '<tbody>' ).
LOOP AT it_overview ASSIGNING <ls_overview>.
LOOP AT it_repo_list ASSIGNING <ls_repo>.
IF <ls_overview>-type = abap_true.
IF <ls_repo>-type = abap_true.
lv_type_icon = 'plug/darkgrey'.
ELSE.
lv_type_icon = 'cloud-upload-alt/darkgrey'.
ENDIF.
IF <ls_overview>-favorite = abap_true.
IF <ls_repo>-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( |<tr class="repo { lv_favorite_class }">| ).
ii_html->add( |<td class="wmin">| ).
ii_html->add_a( iv_act = |{ zif_abapgit_definitions=>c_action-repo_toggle_fav }?key={ <ls_overview>-key }|
iv_txt = ii_html->icon( iv_name = lv_favorite_icon
iv_class = 'pad-sides'
iv_hint = 'Click to toggle favorite' ) ).
ii_html->add( |</td>| ).
ii_html->add(
|<tr class="repo { lv_favorite_class }" data-key="{ <ls_repo>-key }" data-offline="{ <ls_repo>-type }">| ).
lv_toggle_favorite_link = ii_html->a(
iv_act = |{ zif_abapgit_definitions=>c_action-repo_toggle_fav }?key={ <ls_repo>-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 <ls_overview>-write_protected = abap_true.
IF <ls_repo>-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( |<td class="wmin">{ ii_html->icon( lv_type_icon ) }</td>| ).
ii_html->add(
column( iv_content = ii_html->icon( lv_type_icon )
iv_css_class = 'wmin' ) ).
ii_html->add( |<td>{ ii_html->a( iv_txt = <ls_overview>-name
iv_act = |{ c_action-select }?key={ <ls_overview>-key }| ) }{ lv_lock }</td>| ).
ii_html->add(
column( iv_content = ii_html->a( iv_txt = <ls_repo>-name
iv_act = |{ c_action-select }?key={ <ls_repo>-key }| ) && lv_lock ) ).
IF <ls_overview>-type = abap_false.
lv_text = <ls_overview>-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( |<td>{ ii_html->a(
ii_html->add(
column( iv_content = zcl_abapgit_gui_chunk_lib=>render_package_name(
iv_package = <ls_repo>-package
iv_suppress_title = abap_true )->render( ) ) ).
IF <ls_repo>-type = abap_false.
lv_text = shorten_repo_url( <ls_repo>-url ).
ii_html->add( column( iv_content = |{ ii_html->a(
iv_txt = lv_text
iv_title = <ls_overview>-url
iv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ <ls_overview>-url }| ) }</td>| ).
iv_title = <ls_repo>-url
iv_act = |{ zif_abapgit_definitions=>c_action-url }?url={ <ls_repo>-url }| ) }| ) ).
ELSE.
ii_html->add( |<td></td>| ).
ii_html->add( column( ) ).
ENDIF.
ii_html->add( |<td>| ).
ii_html->add( zcl_abapgit_gui_chunk_lib=>render_package_name(
iv_package = <ls_overview>-package
iv_suppress_title = abap_true ) ).
ii_html->add( |</td>| ).
IF <ls_overview>-branch IS INITIAL.
ii_html->add( |<td>&nbsp;</td>| ).
IF <ls_repo>-branch IS INITIAL.
ii_html->add( column( iv_content = |&nbsp;| ) ).
ELSE.
ii_html->add( |<td>| ).
ii_html->add( zcl_abapgit_gui_chunk_lib=>render_branch_name(
iv_branch = <ls_overview>-branch
iv_repo_key = <ls_overview>-key ) ).
ii_html->add( |</td>| ).
ii_html->add(
column( iv_content = zcl_abapgit_gui_chunk_lib=>render_branch_name(
iv_branch = <ls_repo>-branch
iv_repo_key = <ls_repo>-key )->render( ) ) ).
ENDIF.
ii_html->add( |<td class="ro-detail">| ).
ii_html->add( zcl_abapgit_gui_chunk_lib=>render_user_name(
iv_username = <ls_overview>-deserialized_by
iv_suppress_title = abap_true ) ).
ii_html->add( |</td>| ).
ii_html->add( |<td class="ro-detail">{ <ls_overview>-deserialized_at }</td>| ).
ii_html->add( |<td class="ro-detail">| ).
ii_html->add( zcl_abapgit_gui_chunk_lib=>render_user_name(
iv_username = <ls_overview>-created_by
iv_suppress_title = abap_true ) ).
ii_html->add( |</td>| ).
ii_html->add( |<td class="ro-detail">{ <ls_overview>-created_at }</td>| ).
ii_html->add( |<td class="ro-detail">{ <ls_overview>-key }</td>| ).
ii_html->add(
column( iv_content = zcl_abapgit_gui_chunk_lib=>render_user_name(
iv_username = <ls_repo>-deserialized_by
iv_suppress_title = abap_true )->render( )
iv_css_class = 'ro-detail' ) ).
ii_html->add( |<td class='ro-action'> | ).
ii_html->add(
column( iv_content = <ls_repo>-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={ <ls_overview>-key } | ).
ii_html->add(
column( iv_content = zcl_abapgit_gui_chunk_lib=>render_user_name(
iv_username = <ls_repo>-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 = <ls_repo>-created_at
iv_css_class = 'ro-detail' ) ).
IF <ls_overview>-type = abap_false. " online repo
lv_stage_link = ii_html->a(
iv_txt = |Stage|
iv_act = |{ zif_abapgit_definitions=>c_action-go_stage }?key={ <ls_overview>-key } | ).
ii_html->add(
column( iv_content = |{ <ls_repo>-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={ <ls_repo>-key }|
iv_class = 'hidden' ).
lv_patch_link = ii_html->a(
iv_txt = |Patch|
iv_act = |{ zif_abapgit_definitions=>c_action-go_patch }?key={ <ls_overview>-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={ <ls_overview>-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={ <ls_overview>-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={ <ls_overview>-key } | ).
ii_html->add( lv_settings_link ).
ii_html->add( |</td>| ).
ii_html->add( |<td class='ro-go'><span>{
ii_html->a(
iv_txt = `&rsaquo;`
iv_act = |{ c_action-select }?key={ <ls_overview>-key }| ) }</span></td>| ).
ii_html->add( |</tr>| ).
ii_html->add( column(
iv_content = |<span class="link" title="Open">&rsaquo;{ lv_repo_go_link }</span>|
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 `<span class="separator">|</span>`,
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( |<div class="float-right">| ).
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( |</div>| ).
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.
<ls_col>-add_tz = iv_add_tz.
<ls_col>-allow_order_by = iv_allow_order_by.
ENDMETHOD.
METHOD column.
IF iv_css_class IS NOT INITIAL.
rv_html = |<td class="{ iv_css_class }">| && iv_content && |</td>|.
ELSE.
rv_html = |<td>| && iv_content && |</td>|.
ENDIF.
ENDMETHOD.
METHOD action_link.
rv_html = |<span class="action_link">| && iv_content && |</span>|.
ENDMETHOD.
ENDCLASS.