-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
--------- Co-authored-by: Arkadiusz Wójcik <[email protected]> Co-authored-by: Mike Alhayek <[email protected]>
- Loading branch information
1 parent
9252778
commit 1fb3287
Showing
91 changed files
with
3,394 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
src/OrchardCore.Modules/OrchardCore.UrlRewriting/AdminMenu.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
using Microsoft.Extensions.Localization; | ||
using OrchardCore.Navigation; | ||
|
||
namespace OrchardCore.UrlRewriting; | ||
|
||
public sealed class AdminMenu : AdminNavigationProvider | ||
{ | ||
internal readonly IStringLocalizer S; | ||
|
||
public AdminMenu(IStringLocalizer<AdminMenu> stringLocalizer) | ||
{ | ||
S = stringLocalizer; | ||
} | ||
|
||
protected override ValueTask BuildAsync(NavigationBuilder builder) | ||
{ | ||
builder | ||
.Add(S["Configuration"], configuration => configuration | ||
.Add(S["URL Rewriting"], S["URL Rewriting"].PrefixPosition(), rewriting => rewriting | ||
.AddClass("url-rewriting") | ||
.Id("urlRewriting") | ||
.Permission(UrlRewritingPermissions.ManageUrlRewritingRules) | ||
.Action("Index", "Admin", "OrchardCore.UrlRewriting") | ||
.LocalNav() | ||
) | ||
); | ||
|
||
return ValueTask.CompletedTask; | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
src/OrchardCore.Modules/OrchardCore.UrlRewriting/Assets.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[ | ||
{ | ||
"inputs": [ | ||
"Assets/js/sortable-rules.js" | ||
], | ||
"output": "wwwroot/Scripts/sortable-rules.js" | ||
}, | ||
{ | ||
"inputs": [ | ||
"Assets/js/admin-ui.js" | ||
], | ||
"output": "wwwroot/Scripts/admin-ui.js" | ||
} | ||
] |
169 changes: 169 additions & 0 deletions
169
src/OrchardCore.Modules/OrchardCore.UrlRewriting/Assets/js/admin-ui.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
urlRewritingAdmin = function () { | ||
|
||
const initialize = (url, errorLabel, selectedLabel) => { | ||
|
||
// Create the sortable UI. | ||
sortingListManager.create('#rewrite-rules-sortable-list', url, errorLabel); | ||
|
||
let searchBox = document.getElementById('search-box'); | ||
let searchAlert = document.getElementById('list-alert'); | ||
|
||
const filterElements = document.querySelectorAll('[data-filter-value]'); | ||
|
||
// If the user press Enter, don't submit. | ||
searchBox.addEventListener('keydown', function (e) { | ||
if (e.key === 'Enter') { | ||
e.preventDefault(); | ||
} | ||
}); | ||
|
||
searchBox.addEventListener('keyup', e => { | ||
|
||
var search = e.target.value.toLowerCase(); | ||
// On ESC, clear the search box and display all rules. | ||
if (e.key == 'Escape' || search == '') { | ||
searchAlert.classList.add('d-none'); | ||
searchBox.value = ''; | ||
for (let i = 0; i < filterElements.length; i++) { | ||
filterElements[i].classList.remove("d-none"); | ||
filterElements[i].classList.remove("first-child-visible"); | ||
filterElements[i].classList.remove("last-child-visible"); | ||
} | ||
|
||
if (filterElements.length > 0) { | ||
filterElements[0].classList.add('first-child-visible'); | ||
filterElements[filterElements.length - 1].classList.add('last-child-visible'); | ||
} | ||
} else { | ||
let visibleElements = []; | ||
for (let i = 0; i < filterElements.length; i++) { | ||
let filter = filterElements[i]; | ||
|
||
var text = filter.getAttribute('data-filter-value'); | ||
|
||
if (!text) { | ||
filter.classList.add("d-none"); | ||
continue; | ||
} | ||
|
||
var found = text.indexOf(search) > -1; | ||
|
||
if (found) { | ||
filter.classList.remove("d-none"); | ||
filter.classList.remove("first-child-visible"); | ||
filter.classList.remove("last-child-visible"); | ||
visibleElements.push(filter); | ||
} else { | ||
filter.classList.add("d-none"); | ||
} | ||
} | ||
|
||
if (visibleElements.length > 0) { | ||
visibleElements[0].classList.add('first-child-visible'); | ||
visibleElements[visibleElements.length - 1].classList.add('last-child-visible'); | ||
searchAlert.classList.add('d-none'); | ||
} else { | ||
searchAlert.classList.remove('d-none'); | ||
} | ||
} | ||
}); | ||
|
||
var actions = document.getElementById('actions'); | ||
var items = document.getElementById('items'); | ||
var filters = document.querySelectorAll('.filter'); | ||
var selectAllCtrl = document.getElementById('select-all'); | ||
var selectedItems = document.getElementById('selected-items'); | ||
var itemsCheckboxes = document.querySelectorAll("input[type='checkbox'][name='ruleIds']"); | ||
|
||
function displayActionsOrFilters() { | ||
// Select all checked checkboxes with name 'ruleIds' | ||
var checkedCheckboxes = document.querySelectorAll("input[type='checkbox'][name='ruleIds']:checked"); | ||
|
||
if (checkedCheckboxes.length > 1) { | ||
actions.classList.remove('d-none'); | ||
for (let i = 0; i < filters.length; i++) { | ||
filters[i].classList.add('d-none'); | ||
} | ||
selectedItems.classList.remove('d-none'); | ||
items.classList.add('d-none'); | ||
} else { | ||
actions.classList.add('d-none'); | ||
|
||
for (let i = 0; i < filters.length; i++) { | ||
filters[i].classList.remove('d-none'); | ||
} | ||
selectedItems.classList.add('d-none'); | ||
items.classList.remove('d-none'); | ||
} | ||
} | ||
|
||
var dropdownItems = document.querySelectorAll(".dropdown-menu .dropdown-item"); | ||
|
||
// Add click event listeners to each dropdown item | ||
dropdownItems.forEach(function (item) { | ||
// Check if the item has a data-action attribute | ||
if (item.dataset.action) { | ||
item.addEventListener("click", function () { | ||
// Get all checked checkboxes | ||
var checkedCheckboxes = document.querySelectorAll("input[type='checkbox'][name='ruleIds']:checked"); | ||
|
||
// Check if more than one checkbox is checked | ||
if (checkedCheckboxes.length > 1) { | ||
// Get data attributes from the clicked item | ||
var actionData = Object.assign({}, item.dataset); | ||
|
||
confirmDialog({ | ||
...actionData, | ||
callback: function (r) { | ||
if (r) { | ||
// Set the value of the BulkAction option | ||
document.querySelector("[name='Options.BulkAction']").value = actionData.action; | ||
// Trigger the submit action | ||
document.querySelector("[name='submit.BulkAction']").click(); | ||
} | ||
} | ||
}); | ||
} | ||
}); | ||
} | ||
}); | ||
|
||
selectAllCtrl.addEventListener("click", function () { | ||
itemsCheckboxes.forEach(function (checkbox) { | ||
if (checkbox !== selectAllCtrl) { | ||
checkbox.checked = selectAllCtrl.checked; // Set the checked state of all checkboxes | ||
} | ||
}); | ||
|
||
// Update the selected items text | ||
updateSelectedItemsText(); | ||
displayActionsOrFilters(); | ||
}); | ||
|
||
// Event listener for individual checkboxes | ||
itemsCheckboxes.forEach(function (checkbox) { | ||
checkbox.addEventListener("click", function () { | ||
var itemsCount = itemsCheckboxes.length; | ||
var selectedItemsCount = document.querySelectorAll("input[type='checkbox'][name='ruleIds']:checked").length; | ||
|
||
// Update selectAllCtrl state | ||
selectAllCtrl.checked = selectedItemsCount === itemsCount; | ||
selectAllCtrl.indeterminate = selectedItemsCount > 0 && selectedItemsCount < itemsCount; | ||
|
||
// Update the selected items text | ||
updateSelectedItemsText(); | ||
displayActionsOrFilters(); | ||
}); | ||
}); | ||
|
||
// Function to update selected items text | ||
function updateSelectedItemsText() { | ||
var selectedCount = document.querySelectorAll("input[type='checkbox'][name='ruleIds']:checked").length; | ||
selectedItems.textContent = selectedCount + ' ' + selectedLabel; | ||
} | ||
} | ||
|
||
return { | ||
initialize: initialize | ||
} | ||
}(); |
57 changes: 57 additions & 0 deletions
57
src/OrchardCore.Modules/OrchardCore.UrlRewriting/Assets/js/sortable-rules.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
sortingListManager = function () { | ||
|
||
const saveOrders = (evt, url, errorMessage) => { | ||
|
||
var data = { | ||
oldIndex: evt.oldIndex, | ||
newIndex: evt.newIndex | ||
}; | ||
fetch(url, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json' | ||
}, | ||
body: JSON.stringify(data) | ||
}).catch(error => { | ||
console.log(error); | ||
alert(errorMessage || 'Unable to sort the list'); | ||
}); | ||
} | ||
|
||
const create = (selector, sortUrl, errorMessage) => { | ||
|
||
var sortable = document.querySelector(selector); | ||
|
||
if (!sortable) { | ||
console.log('Unable to find the sortable element. The given selector is: ' + selector); | ||
|
||
return; | ||
} | ||
|
||
if (sortUrl) { | ||
orderUrl = sortUrl; | ||
} else { | ||
orderUrl = sortable.getAttribute('data-sort-uri'); | ||
} | ||
|
||
if (!orderUrl) { | ||
console.log('Unable to determine the sort post URI. Either pass it to the create function or set it as data-sort-uri to the sorting element.'); | ||
|
||
return; | ||
} | ||
|
||
var sortable = Sortable.create(sortable, { | ||
handle: ".ui-sortable-handle", | ||
animation: 150, | ||
filter: ".ignore-elements", | ||
draggable: ".item", | ||
onUpdate: function (evt) { | ||
saveOrders(evt, orderUrl, errorMessage); | ||
} | ||
}); | ||
}; | ||
|
||
return { | ||
create: create | ||
} | ||
}(); |
Oops, something went wrong.