mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2026-03-13 02:18:16 +01:00
Add audit system, invite links, and usage analytics (#4749)
# Description of Changes New Features Audit System: Complete audit logging with dashboard, event tracking, and export capabilities Invite Links: Secure invite system with email notifications and expiration Usage Analytics: Endpoint usage statistics and visualization License Management: User counting with grandfathering and license enforcement ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: James Brunton <jbrunton96@gmail.com>
This commit is contained in:
53
frontend/src/core/utils/settingsNavigation.ts
Normal file
53
frontend/src/core/utils/settingsNavigation.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { NavKey } from '@app/components/shared/config/types';
|
||||
|
||||
/**
|
||||
* Navigate to a specific settings section
|
||||
*
|
||||
* @param section - The settings section key to navigate to
|
||||
*
|
||||
* @example
|
||||
* // Navigate to People section
|
||||
* navigateToSettings('people');
|
||||
*
|
||||
* // Navigate to Admin Premium section
|
||||
* navigateToSettings('adminPremium');
|
||||
*/
|
||||
export function navigateToSettings(section: NavKey) {
|
||||
const basePath = window.location.pathname.split('/settings')[0] || '';
|
||||
const newPath = `${basePath}/settings/${section}`;
|
||||
window.history.pushState({}, '', newPath);
|
||||
|
||||
// Trigger a popstate event to notify components
|
||||
window.dispatchEvent(new PopStateEvent('popstate'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL path for a settings section
|
||||
* Useful for creating links
|
||||
*
|
||||
* @param section - The settings section key
|
||||
* @returns The URL path for the settings section
|
||||
*
|
||||
* @example
|
||||
* <a href={getSettingsUrl('people')}>Go to People Settings</a>
|
||||
* // Returns: "/settings/people"
|
||||
*/
|
||||
export function getSettingsUrl(section: NavKey): string {
|
||||
return `/settings/${section}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if currently viewing a settings section
|
||||
*
|
||||
* @param section - Optional section key to check for specific section
|
||||
* @returns True if in settings (and matching specific section if provided)
|
||||
*/
|
||||
export function isInSettings(section?: NavKey): boolean {
|
||||
const pathname = window.location.pathname;
|
||||
|
||||
if (!section) {
|
||||
return pathname.startsWith('/settings');
|
||||
}
|
||||
|
||||
return pathname === `/settings/${section}`;
|
||||
}
|
||||
@@ -50,12 +50,19 @@ export function isFieldPending<T extends SettingsWithPending>(
|
||||
fieldPath: string
|
||||
): boolean {
|
||||
if (!settings?._pending) {
|
||||
console.log(`[isFieldPending] No _pending block found for field: ${fieldPath}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Navigate the pending object using dot notation
|
||||
const value = getNestedValue(settings._pending, fieldPath);
|
||||
return value !== undefined;
|
||||
const isPending = value !== undefined;
|
||||
|
||||
if (isPending) {
|
||||
console.log(`[isFieldPending] Field ${fieldPath} IS pending with value:`, value);
|
||||
}
|
||||
|
||||
return isPending;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user