Skip to content

Commit

Permalink
Merge branch 'develop' into ELI-47-Transfer_LinkInspector_settings-to…
Browse files Browse the repository at this point in the history
…-granite-console

# Conflicts:
#	core/src/main/java/com/exadel/etoolbox/linkinspector/core/services/resolvers/ExternalLinkResolverImpl.java
#	core/src/main/java/com/exadel/etoolbox/linkinspector/core/services/resolvers/InternalLinkResolverImpl.java
  • Loading branch information
Saldatsenka, Siarhei committed Aug 30, 2024
2 parents 52bb47e + 533b54f commit 9c0374b
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
/**
* Validates external links via sending HEAD requests concurrently using {@link PoolingHttpClientConnectionManager}
*/
@Component(service = {LinkResolver.class, ExternalLinkResolverImpl.class})
@Component(service = {LinkResolver.class, ExternalLinkResolverImpl.class}, immediate = true)
@Designate(ocd = ExternalLinkResolverImpl.Configuration.class)
public class ExternalLinkResolverImpl implements LinkResolver {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
/**
* Validates external links via sending HEAD requests concurrently using {@link PoolingHttpClientConnectionManager}
*/
@Component(service = LinkResolver.class)
@Component(service = LinkResolver.class )
@Designate(ocd = InternalLinkResolverImpl.Config.class)
public class InternalLinkResolverImpl implements LinkResolver {

Expand All @@ -69,7 +69,7 @@ public class InternalLinkResolverImpl implements LinkResolver {
private String internalLinksHost;

@Reference
private ExternalLinkResolverImpl externalLinkResolver;
private LinkResolver externalLinkResolver;

@Activate
@Modified
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,11 @@ public class ReplaceByPatternServlet extends SlingAllMethodsServlet {
private static final String DRY_RUN_PARAM = "isDryRun";
private static final String BACKUP_PARAM = "isBackup";
private static final String OUTPUT_AS_CSV_PARAM = "isOutputAsCsv";
private static final String ADVANCED_MODE_PARAM = "advancedMode";
private static final String ITEMS_COUNT_RESP_PARAM = "updatedItemsCount";
private static final String BACKUP_PACKAGE_GROUP = "EToolbox_Link_Inspector";
private static final String BACKUP_PACKAGE_NAME = "replace_by_pattern_backup_%s";
private static final String BACKUP_PACKAGE_VERSION = "1.0";
private static final String PAGE_PARAM = "page";
private static final String SELECTED_PARAM = "selected";

private static final String[] CSV_COLUMNS = {
Expand Down Expand Up @@ -136,18 +136,24 @@ void activate(Configuration configuration) {
protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) {
String linkPattern = ServletUtil.getRequestParamString(request, LINK_PATTERN_PARAM);
String replacement = ServletUtil.getRequestParamString(request, REPLACEMENT_PARAM);
boolean isAdvancedMode = ServletUtil.getRequestParamBoolean(request, ADVANCED_MODE_PARAM);
boolean isDryRun = ServletUtil.getRequestParamBoolean(request, DRY_RUN_PARAM);
boolean isBackup = ServletUtil.getRequestParamBoolean(request, BACKUP_PARAM);
boolean isOutputAsCsv = ServletUtil.getRequestParamBoolean(request, OUTPUT_AS_CSV_PARAM);
List<String> selectedItems = ServletUtil.getRequestParamStringList(request, SELECTED_PARAM);

if (StringUtils.isAnyBlank(linkPattern, replacement)) {
if (StringUtils.isBlank(replacement)) {
response.setStatus(HttpStatus.SC_BAD_REQUEST);
LOG.warn("Any (or all) request params are empty: linkPattern - {}, replacement - {}",
linkPattern, replacement);
LOG.warn("Request params is empty: replacement - {}", replacement);
return;
}
if (linkPattern.equals(replacement)) {

if (isAdvancedMode && StringUtils.isBlank(linkPattern)) {
response.setStatus(HttpStatus.SC_BAD_REQUEST);
LOG.warn("Request params is empty: linkPattern - {}", linkPattern);
return;
}
if (isAdvancedMode && linkPattern.equals(replacement)) {
response.setStatus(HttpStatus.SC_ACCEPTED);
LOG.debug("linkPattern and replacement are equal, no processing is required");
return;
Expand All @@ -162,7 +168,7 @@ protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse
.format("%s@%s", gridResource.getResourcePath(), gridResource.getPropertyName())))
.collect(Collectors.toList());
List<UpdatedItem> updatedItems =
processResources(filteredGridResources, isDryRun, isBackup, linkPattern, replacement, resourceResolver);
processResources(filteredGridResources, isDryRun, isBackup, isAdvancedMode, linkPattern, replacement, resourceResolver);
if (CollectionUtils.isEmpty(updatedItems)) {
LOG.info("No links were updated, linkPattern: {}, replacement: {}", linkPattern, replacement);
response.setStatus(HttpStatus.SC_NO_CONTENT);
Expand All @@ -184,6 +190,7 @@ protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse
private List<UpdatedItem> processResources(Collection<GridResource> gridResources,
boolean isDryRun,
boolean isBackup,
boolean isAdvancedMode,
String linkPattern,
String replacement,
ResourceResolver resourceResolver)
Expand All @@ -197,7 +204,7 @@ private List<UpdatedItem> processResources(Collection<GridResource> gridResource
if (isBackup && !isDeactivated) {
createBackupPackage(filteredGridResources, session.get());
}
return replaceByPattern(filteredGridResources, isDryRun, linkPattern, replacement, resourceResolver);
return replaceByPattern(filteredGridResources, isDryRun, isAdvancedMode, linkPattern, replacement, resourceResolver);
}

private List<GridResource> filterGridResources(Collection<GridResource> gridResources,
Expand All @@ -216,6 +223,7 @@ private List<GridResource> filterGridResources(Collection<GridResource> gridReso

private List<UpdatedItem> replaceByPattern(Collection<GridResource> gridResources,
boolean isDryRun,
boolean isAdvancedMode,
String linkPattern,
String replacement,
ResourceResolver resourceResolver) throws PersistenceException {
Expand All @@ -227,7 +235,7 @@ private List<UpdatedItem> replaceByPattern(Collection<GridResource> gridResource
String currentLink = gridResource.getHref();
String path = gridResource.getResourcePath();
String propertyName = gridResource.getPropertyName();
Optional<String> updated = Optional.of(currentLink.replaceAll(linkPattern, replacement))
Optional<String> updated = Optional.of(isAdvancedMode ? currentLink.replaceAll(linkPattern, replacement) : replacement)
.filter(updatedLink -> !updatedLink.equals(currentLink))
.filter(updatedLink ->
linkHelper.replaceLink(resourceResolver, path, propertyName, currentLink, updatedLink)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class FixBrokenLinkServletTest {
private static final String TEST_CURRENT_LINK = "/content/link-for-replacement";
private static final String TEST_NEW_LINK = "/content/replacement-link";
private static final String TEST_EXCEPTION_MSG = "Test exception message";
private static final String ADVANCED_MODE = "advancedMode";

private final AemContext context = new AemContext(ResourceResolverType.JCR_MOCK);

Expand Down Expand Up @@ -100,6 +101,7 @@ void testCurrentLinkEqualToReplacement() {
request.addRequestParameter(PROPERTY_NAME_PARAM, TEST_PROPERTY_NAME);
request.addRequestParameter(CURRENT_LINK_PARAM, TEST_CURRENT_LINK);
request.addRequestParameter(NEW_LINK_PARAM, TEST_CURRENT_LINK);
request.addRequestParameter(ADVANCED_MODE, Boolean.TRUE.toString());
fixture.doPost(request, response);

assertEquals(HttpStatus.SC_ACCEPTED, response.getStatus());
Expand All @@ -119,6 +121,7 @@ void testValidateNewLink_notValid() {
request.addRequestParameter(CURRENT_LINK_PARAM, TEST_CURRENT_LINK);
request.addRequestParameter(NEW_LINK_PARAM, TEST_NEW_LINK);
request.addRequestParameter(IS_SKIP_VALIDATION_PARAM, Boolean.FALSE.toString());
request.addRequestParameter(ADVANCED_MODE, Boolean.TRUE.toString());
fixture.doPost(request, response);

assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatus());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class ReplaceByPatternServletTest {
private static final String TEST_RESOURCES_TREE_PATH = "/com/exadel/etoolbox/linkinspector/core/servlets/resources.json";
private static final String TEST_FOLDER_PATH = "/content/test-folder";
private static final String TEST_EXCEPTION_MSG = "Test exception message";
private static final String ADVANCED_MODE = "advancedMode";

private final AemContext context = new AemContext(ResourceResolverType.JCR_MOCK);

Expand Down Expand Up @@ -153,6 +154,7 @@ void testEmptyParams() {
void testCurrentLinkEqualToReplacement() {
request.addRequestParameter(LINK_PATTERN_PARAM, TEST_LINK_PATTERN);
request.addRequestParameter(REPLACEMENT_PARAM, TEST_LINK_PATTERN);
request.addRequestParameter(ADVANCED_MODE, Boolean.TRUE.toString());
linkHelper = mock(LinkHelper.class);
repositoryHelper = mock(RepositoryHelper.class);
packageHelper = mock(PackageHelper.class);
Expand Down Expand Up @@ -433,6 +435,7 @@ private void setUpRequestParamsWithBackup() throws IOException {
private void setUpRequestParamsLinks() throws IOException {
request.addRequestParameter(LINK_PATTERN_PARAM, TEST_LINK_PATTERN);
request.addRequestParameter(REPLACEMENT_PARAM, TEST_REPLACEMENT);
request.addRequestParameter(ADVANCED_MODE, Boolean.TRUE.toString());
Arrays.stream(loadSelectedValues()).forEach(value ->
request.addRequestParameter(SELECTED_PARAM, value)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,15 @@ tr.elc-card {
width:30%
}

#elc-filter-options.elc-filter-active, #elc-filter-options.elc-filter-active:hover {
background-color: #d3d3d3;
}

.filter-dialog-button-group {
display: flex;
justify-content: space-between;
}

#filter-dialog{
.coral3-Dialog-wrapper{
min-width: 50rem;
Expand All @@ -149,3 +158,4 @@ tr.elc-card {
font-size: 12px;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
const DIALOG_TITLE_LABEL = Granite.I18n.get('Filter Links');
const CANCEL_LABEL = Granite.I18n.get('Cancel');
const SUBMIT_FILTER_LABEL = Granite.I18n.get('Apply');
const RESET_FILTER_LABEL = Granite.I18n.get('Reset');

function onFilterAction(name, el, config, collection, selections) {
const dialog = document.querySelector('#filter--dialog');
Expand Down Expand Up @@ -82,12 +83,21 @@
$('<p>').html('By text').appendTo(dialog.content);
$linkSubstringField.appendTo(dialog.content);


const $dialogActionsButtons = $('<div class="filter-dialog-action-buttons">');
const $resetBtn = $('<button data-dialog-reset is="coral-button" variant="default">').text(RESET_FILTER_LABEL);
const $cancelBtn = $('<button is="coral-button" variant="default" coral-close>').text(CANCEL_LABEL);
const $updateBtn =
$('<button data-dialog-action is="coral-button" variant="primary" coral-close>').text(SUBMIT_FILTER_LABEL);

$cancelBtn.appendTo(dialog.footer);
$updateBtn.appendTo(dialog.footer);
$cancelBtn.appendTo($dialogActionsButtons);
$updateBtn.appendTo($dialogActionsButtons);

const $buttonGroup = $('<div class="filter-dialog-button-group">');
$resetBtn.appendTo($buttonGroup);
$dialogActionsButtons.appendTo($buttonGroup);

$buttonGroup.appendTo(dialog.footer);

function onSubmit(){
searchParams.delete('type');
Expand All @@ -102,6 +112,12 @@
document.location.search = searchParams;
}

function onReset(){
$linkSubstringField.val('');
linksTypeSelect.value = '';
}

dialog.on('click', '[data-dialog-reset]', onReset);
dialog.on('click', '[data-dialog-action]', onSubmit);
dialog.on('change', function(event) {
linksTypeSelect.value
Expand All @@ -121,9 +137,7 @@

$(document).ready(function () {
let searchParams = new URL(document.location).searchParams;
if (searchParams != null && searchParams.get('type') != null || searchParams.get('substring') != null) {
$('#elc-filter-options').attr('variant', 'primary');
}
$('#elc-filter-options').toggleClass('elc-filter-active', searchParams && searchParams.get('type') != null || searchParams.get('substring') != null)
initFiltersDialog(searchParams);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
'use strict';

var CANCEL_LABEL = Granite.I18n.get('Cancel');
var REPLACE_LABEL = Granite.I18n.get('Replace By Pattern');
var REPLACE_BUTTON_LABEL = Granite.I18n.get('Replace');
var REPLACE_AND_MODIFY_LABEL = Granite.I18n.get('Replace and Modify by Pattern');
var REPLACE_LABEL = Granite.I18n.get('Replace');
var MODIFY_LABEL = Granite.I18n.get('Modify');
var PATTERN_LABEL = Granite.I18n.get('Please enter the regex pattern to be replaced');
var REPLACEMENT_LINK_LABEL = Granite.I18n.get('Please enter the replacement');
var DRY_RUN_CHECKBOX_LABEL = Granite.I18n.get('Dry run');
Expand Down Expand Up @@ -59,6 +60,7 @@
isDryRun: data.isDryRun,
isBackup: data.isBackup,
isOutputAsCsv: data.isOutputAsCsv,
advancedMode: data.advancedMode,
selected: data.selected
}].filter(function (item) {
return item.pattern && item.replacement && item.pattern !== item.replacement;
Expand Down Expand Up @@ -136,22 +138,37 @@

var el = ELC.getSharableDlg();
el.variant = 'notice';
el.header.textContent = REPLACE_LABEL;
el.header.textContent = REPLACE_AND_MODIFY_LABEL;
el.footer.innerHTML = ''; // Clean content
el.content.innerHTML = ''; // Clean content

var $cancelBtn = $('<button is="coral-button" variant="default" coral-close>').text(CANCEL_LABEL);
var $updateBtn = $('<button data-dialog-action is="coral-button" variant="primary" coral-close>').text(REPLACE_BUTTON_LABEL);
var $updateBtn = $('<button name="update-button" is="coral-button" variant="primary" coral-close>').text(REPLACE_LABEL);
$cancelBtn.appendTo(el.footer);
$updateBtn.appendTo(el.footer);

buildConfirmationMessage(selection).appendTo(el.content);
buildConfirmationMessage(confirmationMessageSelectionItems(selection)).appendTo(el.content);

// Pattern input group
let $replaceRadio = new Coral.Radio();
$replaceRadio.label.textContent = REPLACE_LABEL;
$replaceRadio.name = 'replace-modify';
$replaceRadio.checked = true;
$replaceRadio.value = 'replace';

let $modifyRadio = new Coral.Radio();
$modifyRadio.label.textContent = MODIFY_LABEL;
$modifyRadio.name = 'replace-modify';
$modifyRadio.value = 'modify';

el.content.appendChild($replaceRadio);
el.content.appendChild($modifyRadio);

let $patternFieldGroup = $('<div class="elc-pattern-field-group" hidden>');
var $patternTextField =
$('<input is="coral-textfield" class="elc-pattern-input" name="pattern" value="" required>');
$('<p>').text(PATTERN_LABEL).appendTo(el.content);
$patternTextField.appendTo(el.content);
$('<input is="coral-textfield" class="elc-pattern-input" name="pattern" value="" placeholder=".+" required>');
$('<p>').text(PATTERN_LABEL).appendTo($patternFieldGroup);
$patternTextField.appendTo($patternFieldGroup);
$patternFieldGroup.appendTo(el.content);

// Replacement input group
var $replacementTextField =
Expand All @@ -161,11 +178,11 @@

// Dry run checkbox group
var $isDryRunCheckbox =
$('<coral-checkbox name="$isDryRun" title="' + DRY_RUN_TOOLTIP + '" checked>').text(DRY_RUN_CHECKBOX_LABEL);
$('<coral-checkbox name="dry-run-checkbox" title="' + DRY_RUN_TOOLTIP + '" checked>').text(DRY_RUN_CHECKBOX_LABEL);
$isDryRunCheckbox.appendTo(el.content);

// Backup checkbox group
var $isBackupCheckbox = $('<coral-checkbox name="isBackup">').text(BACKUP_CHECKBOX_LABEL);
var $isBackupCheckbox = $('<coral-checkbox name="isBackup" disabled>').text(BACKUP_CHECKBOX_LABEL);
$isBackupCheckbox.appendTo(el.content);

// CSV output checkbox group
Expand All @@ -178,15 +195,18 @@
function onValidate() {
var replVal = $replacementTextField.val();
var patternVal = $patternTextField.val();
var advanced = $modifyRadio.checked;
$replacementTextField.each(function () {
this.setCustomValidity(replVal === patternVal ? VALIDATION_MSG : '');
});
$updateBtn.attr('disabled', !replVal || !patternVal || replVal === patternVal);
$updateBtn.attr('disabled', !replVal || (advanced && !patternVal || replVal === patternVal));
}

/** @param {Event} e */
function onResolve(e) {
var data = {
pattern: $patternTextField.val(),
advancedMode: $modifyRadio.checked,
replacement: $replacementTextField.val(),
isDryRun: $isDryRunCheckbox.prop("checked"),
isBackup: $isBackupCheckbox.prop("checked"),
Expand All @@ -198,23 +218,37 @@
deferred.resolve(data);
}

/** @param {Event} e */
function onDryRunChange(e) {
$isBackupCheckbox.attr('disabled', $isDryRunCheckbox.prop('checked'));
}

el.on('input', 'input', onValidate);
el.on('click', '[data-dialog-action]', onResolve);
el.on('click', '[name="update-button"]', onResolve);
el.on('change', '[name="dry-run-checkbox"]', onDryRunChange);
el.on('coral-overlay:close', function () {
el.off('input', 'input', onValidate);
el.off('click', '[data-dialog-action]', onResolve);
el.off('click', '[name="update-button"]', onResolve);
el.off('change', '[name="dry-run-checkbox"]', onDryRunChange);
deferred.reject();
});

el.show();
onValidate();

el.content.addEventListener('change', function(event) {
if (event.target.name == 'replace-modify') {
$patternFieldGroup.attr('hidden', event.target.value != 'modify');
onValidate();
}
});

return deferred.promise();
}

function buildConfirmationMessage(selections) {
let list = selections.slice(0, 12).map(function (row) {
return '<li>' + row.currentLink + '</li>';
return '<li>' + row.currentLink + ' (' + row.count + ')' + '</li>';
});
if (selections.length > 12) {
list.push('<li>&#8230;</li>'); // &#8230; is ellipsis
Expand All @@ -226,6 +260,21 @@
return $msg;
}

function confirmationMessageSelectionItems(selections) {
let valuesMap = {};
selections.map(function (row) {
return row.currentLink;
}).forEach(function (item) {
valuesMap[item] = (valuesMap[item]||0) + 1;
});

let items = [];
for (const [key, value] of Object.entries(valuesMap)) {
items.push({currentLink: key, count: value});
}
return items;
}

function buildSelectionItems(selections) {
return selections.map(function (v) {
let row = $(v);
Expand Down
Loading

0 comments on commit 9c0374b

Please sign in to comment.