mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-07-26 07:05:22 +00:00
Merge branch 'main' into session_2025_03_22
This commit is contained in:
commit
f33d8b0f23
@ -139,7 +139,7 @@ Stirling-PDF currently supports 39 languages!
|
|||||||
| Korean (한국어) (ko_KR) |  |
|
| Korean (한국어) (ko_KR) |  |
|
||||||
| Norwegian (Norsk) (no_NB) |  |
|
| Norwegian (Norsk) (no_NB) |  |
|
||||||
| Persian (فارسی) (fa_IR) |  |
|
| Persian (فارسی) (fa_IR) |  |
|
||||||
| Polish (Polski) (pl_PL) |  |
|
| Polish (Polski) (pl_PL) |  |
|
||||||
| Portuguese (Português) (pt_PT) |  |
|
| Portuguese (Português) (pt_PT) |  |
|
||||||
| Portuguese Brazilian (Português) (pt_BR) |  |
|
| Portuguese Brazilian (Português) (pt_BR) |  |
|
||||||
| Romanian (Română) (ro_RO) |  |
|
| Romanian (Română) (ro_RO) |  |
|
||||||
|
@ -204,6 +204,7 @@ public class UserService implements UserServiceInterface {
|
|||||||
user.setPassword(passwordEncoder.encode(password));
|
user.setPassword(passwordEncoder.encode(password));
|
||||||
user.setEnabled(true);
|
user.setEnabled(true);
|
||||||
user.setAuthenticationType(AuthenticationType.WEB);
|
user.setAuthenticationType(AuthenticationType.WEB);
|
||||||
|
user.addAuthority(new Authority(Role.USER.getRoleId(), user));
|
||||||
userRepository.save(user);
|
userRepository.save(user);
|
||||||
databaseService.exportDatabase();
|
databaseService.exportDatabase();
|
||||||
}
|
}
|
||||||
@ -229,6 +230,22 @@ public class UserService implements UserServiceInterface {
|
|||||||
saveUser(username, password, role, false);
|
saveUser(username, password, role, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void saveUser(String username, String password, boolean firstLogin, boolean enabled)
|
||||||
|
throws IllegalArgumentException, SQLException, UnsupportedProviderException {
|
||||||
|
if (!isUsernameValid(username)) {
|
||||||
|
throw new IllegalArgumentException(getInvalidUsernameMessage());
|
||||||
|
}
|
||||||
|
User user = new User();
|
||||||
|
user.setUsername(username);
|
||||||
|
user.setPassword(passwordEncoder.encode(password));
|
||||||
|
user.addAuthority(new Authority(Role.USER.getRoleId(), user));
|
||||||
|
user.setEnabled(enabled);
|
||||||
|
user.setAuthenticationType(AuthenticationType.WEB);
|
||||||
|
user.setFirstLogin(firstLogin);
|
||||||
|
userRepository.save(user);
|
||||||
|
databaseService.exportDatabase();
|
||||||
|
}
|
||||||
|
|
||||||
public void deleteUser(String username) {
|
public void deleteUser(String username) {
|
||||||
Optional<User> userOpt = findByUsernameIgnoreCase(username);
|
Optional<User> userOpt = findByUsernameIgnoreCase(username);
|
||||||
if (userOpt.isPresent()) {
|
if (userOpt.isPresent()) {
|
||||||
@ -351,6 +368,7 @@ public class UserService implements UserServiceInterface {
|
|||||||
|
|
||||||
List<String> notAllowedUserList = new ArrayList<>();
|
List<String> notAllowedUserList = new ArrayList<>();
|
||||||
notAllowedUserList.add("ALL_USERS".toLowerCase());
|
notAllowedUserList.add("ALL_USERS".toLowerCase());
|
||||||
|
notAllowedUserList.add("anonymoususer");
|
||||||
boolean notAllowedUser = notAllowedUserList.contains(username.toLowerCase());
|
boolean notAllowedUser = notAllowedUserList.contains(username.toLowerCase());
|
||||||
return (isValidSimpleUsername || isValidEmail) && !notAllowedUser;
|
return (isValidSimpleUsername || isValidEmail) && !notAllowedUser;
|
||||||
}
|
}
|
||||||
|
@ -1036,10 +1036,10 @@ decrypt.unexpectedError=Wystąpił błąd podczas przetwarzania pliku. Spróbuj
|
|||||||
decrypt.serverError=Błąd serwera podczas odszyfrowywania: {0}
|
decrypt.serverError=Błąd serwera podczas odszyfrowywania: {0}
|
||||||
decrypt.success=Plik został pomyślnie odszyfrowany.
|
decrypt.success=Plik został pomyślnie odszyfrowany.
|
||||||
|
|
||||||
#multiTool-advert
|
#multiTool-advert
|
||||||
multiTool-advert.message=Ta funkcja jest również dostępna na naszej <a href="{0}">stronie narzędzia wielofunkcyjnego</a>. Sprawdź ją, aby uzyskać lepszy interfejs zarządzania stronami i dodatkowe funkcje!
|
multiTool-advert.message=Ta funkcja jest również dostępna na naszej <a href="{0}">stronie narzędzia wielofunkcyjnego</a>. Sprawdź ją, aby uzyskać lepszy interfejs zarządzania stronami i dodatkowe funkcje!
|
||||||
|
|
||||||
#view pdf
|
#view pdf
|
||||||
viewPdf.title=Przeglądaj/Edytuj PDF
|
viewPdf.title=Przeglądaj/Edytuj PDF
|
||||||
viewPdf.header=Podejrzyj PDF
|
viewPdf.header=Podejrzyj PDF
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ function getChartColors() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch for theme changes and update chart if needed
|
// Watch for theme changes and update chart if needed
|
||||||
function setupThemeChangeListener() {
|
function setupThemeChangeListener() {
|
||||||
|
|
||||||
// Start observing theme changes
|
// Start observing theme changes
|
||||||
document.addEventListener("modeChanged", (event) => {
|
document.addEventListener("modeChanged", (event) => {
|
||||||
@ -41,7 +41,7 @@ function setupThemeChangeListener() {
|
|||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Also watch for system preference changes
|
// Also watch for system preference changes
|
||||||
window
|
window
|
||||||
.matchMedia('(prefers-color-scheme: dark)')
|
.matchMedia('(prefers-color-scheme: dark)')
|
||||||
@ -60,22 +60,22 @@ function setupThemeChangeListener() {
|
|||||||
function filterData() {
|
function filterData() {
|
||||||
const includeHome = document.getElementById('hideHomeCheckbox').checked;
|
const includeHome = document.getElementById('hideHomeCheckbox').checked;
|
||||||
const includeLogin = document.getElementById('hideLoginCheckbox').checked;
|
const includeLogin = document.getElementById('hideLoginCheckbox').checked;
|
||||||
|
|
||||||
filteredData = allEndpointData.filter(item => {
|
filteredData = allEndpointData.filter(item => {
|
||||||
if (!includeHome && item.endpoint === '/') return false;
|
if (!includeHome && item.endpoint === '/') return false;
|
||||||
if (!includeLogin && item.endpoint === '/login') return false;
|
if (!includeLogin && item.endpoint === '/login') return false;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Sort and calculate
|
// Sort and calculate
|
||||||
sortedData = [...filteredData].sort((a, b) => b.count - a.count);
|
sortedData = [...filteredData].sort((a, b) => b.count - a.count);
|
||||||
totalEndpoints = filteredData.length;
|
totalEndpoints = filteredData.length;
|
||||||
totalVisits = filteredData.reduce((sum, item) => sum + item.count, 0);
|
totalVisits = filteredData.reduce((sum, item) => sum + item.count, 0);
|
||||||
|
|
||||||
// Update stats
|
// Update stats
|
||||||
document.getElementById('totalEndpoints').textContent = totalEndpoints.toLocaleString();
|
document.getElementById('totalEndpoints').textContent = totalEndpoints.toLocaleString();
|
||||||
document.getElementById('totalVisits').textContent = totalVisits.toLocaleString();
|
document.getElementById('totalVisits').textContent = totalVisits.toLocaleString();
|
||||||
|
|
||||||
// Update the chart with current limit
|
// Update the chart with current limit
|
||||||
const currentLimit = document.getElementById('currentlyShowing').textContent;
|
const currentLimit = document.getElementById('currentlyShowing').textContent;
|
||||||
const limit = (currentLimit === endpointStatsTranslations.all)
|
const limit = (currentLimit === endpointStatsTranslations.all)
|
||||||
@ -96,33 +96,33 @@ async function fetchEndpointData() {
|
|||||||
<span class="visually-hidden">${endpointStatsTranslations.loading}</span>
|
<span class="visually-hidden">${endpointStatsTranslations.loading}</span>
|
||||||
</div>`;
|
</div>`;
|
||||||
chartContainer.appendChild(loadingDiv);
|
chartContainer.appendChild(loadingDiv);
|
||||||
|
|
||||||
// Also add animation to refresh button
|
// Also add animation to refresh button
|
||||||
const refreshBtn = document.getElementById('refreshBtn');
|
const refreshBtn = document.getElementById('refreshBtn');
|
||||||
refreshBtn.classList.add('refreshing');
|
refreshBtn.classList.add('refreshing');
|
||||||
refreshBtn.disabled = true;
|
refreshBtn.disabled = true;
|
||||||
|
|
||||||
const response = await fetch('/api/v1/info/load/all');
|
const response = await fetch('/api/v1/info/load/all');
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('Network response was not ok');
|
throw new Error('Network response was not ok');
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
allEndpointData = data;
|
allEndpointData = data;
|
||||||
|
|
||||||
// Apply filters
|
// Apply filters
|
||||||
filterData();
|
filterData();
|
||||||
|
|
||||||
// Remove loading state
|
// Remove loading state
|
||||||
chartContainer.removeChild(loadingDiv);
|
chartContainer.removeChild(loadingDiv);
|
||||||
refreshBtn.classList.remove('refreshing');
|
refreshBtn.classList.remove('refreshing');
|
||||||
refreshBtn.disabled = false;
|
refreshBtn.disabled = false;
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching endpoint data:', error);
|
console.error('Error fetching endpoint data:', error);
|
||||||
// Show error message to user
|
// Show error message to user
|
||||||
showError(endpointStatsTranslations.failedToLoad);
|
showError(endpointStatsTranslations.failedToLoad);
|
||||||
|
|
||||||
// Reset refresh button
|
// Reset refresh button
|
||||||
const refreshBtn = document.getElementById('refreshBtn');
|
const refreshBtn = document.getElementById('refreshBtn');
|
||||||
refreshBtn.classList.remove('refreshing');
|
refreshBtn.classList.remove('refreshing');
|
||||||
@ -141,24 +141,24 @@ function formatEndpointName(endpoint) {
|
|||||||
function updateTable(data) {
|
function updateTable(data) {
|
||||||
const tableBody = document.getElementById('endpointTableBody');
|
const tableBody = document.getElementById('endpointTableBody');
|
||||||
tableBody.innerHTML = '';
|
tableBody.innerHTML = '';
|
||||||
|
|
||||||
data.forEach((item, index) => {
|
data.forEach((item, index) => {
|
||||||
const percentage = ((item.count / totalVisits) * 100).toFixed(2);
|
const percentage = ((item.count / totalVisits) * 100).toFixed(2);
|
||||||
const row = document.createElement('tr');
|
const row = document.createElement('tr');
|
||||||
|
|
||||||
// Format endpoint for better readability
|
// Format endpoint for better readability
|
||||||
let displayEndpoint = item.endpoint;
|
let displayEndpoint = item.endpoint;
|
||||||
if (displayEndpoint.length > 40) {
|
if (displayEndpoint.length > 40) {
|
||||||
displayEndpoint = displayEndpoint.substring(0, 37) + '...';
|
displayEndpoint = displayEndpoint.substring(0, 37) + '...';
|
||||||
}
|
}
|
||||||
|
|
||||||
row.innerHTML = `
|
row.innerHTML = `
|
||||||
<td>${index + 1}</td>
|
<td>${index + 1}</td>
|
||||||
<td title="${item.endpoint}">${displayEndpoint}</td>
|
<td title="${item.endpoint}">${displayEndpoint}</td>
|
||||||
<td>${item.count.toLocaleString()}</td>
|
<td>${item.count.toLocaleString()}</td>
|
||||||
<td>${percentage}%</td>
|
<td>${percentage}%</td>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
tableBody.appendChild(row);
|
tableBody.appendChild(row);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -172,10 +172,10 @@ function updateChart(dataLimit) {
|
|||||||
const displayedPercentage = totalVisits > 0
|
const displayedPercentage = totalVisits > 0
|
||||||
? ((displayedVisits / totalVisits) * 100).toFixed(2)
|
? ((displayedVisits / totalVisits) * 100).toFixed(2)
|
||||||
: '0';
|
: '0';
|
||||||
|
|
||||||
document.getElementById('displayedVisits').textContent = displayedVisits.toLocaleString();
|
document.getElementById('displayedVisits').textContent = displayedVisits.toLocaleString();
|
||||||
document.getElementById('displayedPercentage').textContent = displayedPercentage;
|
document.getElementById('displayedPercentage').textContent = displayedPercentage;
|
||||||
|
|
||||||
// If the limit equals the total filtered items, show "All"; otherwise "Top X"
|
// If the limit equals the total filtered items, show "All"; otherwise "Top X"
|
||||||
document.getElementById('currentlyShowing').textContent =
|
document.getElementById('currentlyShowing').textContent =
|
||||||
(dataLimit === filteredData.length)
|
(dataLimit === filteredData.length)
|
||||||
@ -303,30 +303,30 @@ function updateChart(dataLimit) {
|
|||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
// Set up theme change listener
|
// Set up theme change listener
|
||||||
setupThemeChangeListener();
|
setupThemeChangeListener();
|
||||||
|
|
||||||
// Initial data fetch
|
// Initial data fetch
|
||||||
fetchEndpointData();
|
fetchEndpointData();
|
||||||
|
|
||||||
// Set up button event listeners
|
// Set up button event listeners
|
||||||
document.getElementById('top10Btn').addEventListener('click', function() {
|
document.getElementById('top10Btn').addEventListener('click', function() {
|
||||||
updateChart(10);
|
updateChart(10);
|
||||||
setActiveButton(this);
|
setActiveButton(this);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('top20Btn').addEventListener('click', function() {
|
document.getElementById('top20Btn').addEventListener('click', function() {
|
||||||
updateChart(20);
|
updateChart(20);
|
||||||
setActiveButton(this);
|
setActiveButton(this);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('allBtn').addEventListener('click', function() {
|
document.getElementById('allBtn').addEventListener('click', function() {
|
||||||
updateChart(filteredData.length);
|
updateChart(filteredData.length);
|
||||||
setActiveButton(this);
|
setActiveButton(this);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('refreshBtn').addEventListener('click', function() {
|
document.getElementById('refreshBtn').addEventListener('click', function() {
|
||||||
fetchEndpointData();
|
fetchEndpointData();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set up filter checkbox listeners
|
// Set up filter checkbox listeners
|
||||||
document.getElementById('hideHomeCheckbox').addEventListener('change', filterData);
|
document.getElementById('hideHomeCheckbox').addEventListener('change', filterData);
|
||||||
document.getElementById('hideLoginCheckbox').addEventListener('change', filterData);
|
document.getElementById('hideLoginCheckbox').addEventListener('change', filterData);
|
||||||
@ -350,14 +350,14 @@ function showError(message) {
|
|||||||
<span class="material-symbols-rounded" style="vertical-align: bottom; margin-right: 5px;">error</span>
|
<span class="material-symbols-rounded" style="vertical-align: bottom; margin-right: 5px;">error</span>
|
||||||
${message}
|
${message}
|
||||||
<button id="errorRetryBtn" class="btn btn-outline-danger btn-sm" style="margin-left: 10px;">
|
<button id="errorRetryBtn" class="btn btn-outline-danger btn-sm" style="margin-left: 10px;">
|
||||||
<span class="material-symbols-rounded" style="font-size: 1rem; vertical-align: bottom;">refresh</span>
|
<span class="material-symbols-rounded" style="font-size: 1rem; vertical-align: bottom;">refresh</span>
|
||||||
${endpointStatsTranslations.retry}
|
${endpointStatsTranslations.retry}
|
||||||
</button>
|
</button>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
chartContainer.innerHTML = '';
|
chartContainer.innerHTML = '';
|
||||||
chartContainer.appendChild(errorDiv);
|
chartContainer.appendChild(errorDiv);
|
||||||
|
|
||||||
// Add retry button functionality
|
// Add retry button functionality
|
||||||
document.getElementById('errorRetryBtn').addEventListener('click', fetchEndpointData);
|
document.getElementById('errorRetryBtn').addEventListener('click', fetchEndpointData);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user