fix: DockerSecretsResolver - don't normalize absolute paths like /var/www/html/...
Some checks failed
Deploy Application / deploy (push) Has been cancelled

This commit is contained in:
2025-11-24 21:28:25 +01:00
parent 4eb7134853
commit 77abc65cd7
1327 changed files with 91915 additions and 9909 deletions

View File

@@ -0,0 +1,523 @@
# ActionHandler Guide
## Übersicht
Das `ActionHandler` Modul bietet ein wiederverwendbares Pattern für Event-Delegation-basiertes Action-Handling mit automatischem CSRF-Token-Handling, Loading States, Bestätigungen und Toast-Integration.
## Konzepte
### Event Delegation
Statt jedem Button einen eigenen Event Listener zuzuweisen, verwendet ActionHandler Event Delegation: Ein einziger Event Listener auf dem Container-Element behandelt alle Actions.
**Vorteile:**
- Bessere Performance (weniger Event Listener)
- Funktioniert mit dynamisch hinzugefügten Elementen
- Einfacheres Code-Management
### Handler-Registry
Handler sind vorkonfigurierte Action-Patterns, die wiederverwendet werden können. Sie definieren:
- URL-Templates
- Bestätigungs-Nachrichten
- Loading-Texte
- Success/Error-Messages
### URL-Templates
URL-Templates verwenden Platzhalter, die zur Laufzeit ersetzt werden:
- `{action}` - Der Action-Name
- `{id}` - ID aus `data-action-param-id`
- `{param:name}` - Parameter aus `data-action-param-{name}`
- `{data:name}` - Wert aus `data-{name}` Attribut
## Basis-Verwendung
### 1. ActionHandler initialisieren
```javascript
import { ActionHandler } from '/assets/js/modules/common/ActionHandler.js';
import { dockerContainerHandler } from '/assets/js/modules/common/ActionHandlers.js';
const handler = new ActionHandler('.my-container', {
csrfTokenSelector: '[data-live-component]',
toastHandler: showToast,
refreshHandler: refreshComponent,
autoRefresh: true
});
// Handler registrieren
handler.registerHandler('docker-container', dockerContainerHandler);
```
### 2. HTML mit data-* Attributen
```html
<div class="my-container">
<button
data-action="start"
data-action-handler="docker-container"
data-action-param-id="container-123"
>
Start Container
</button>
<button
data-action="stop"
data-action-handler="docker-container"
data-action-param-id="container-123"
>
Stop Container
</button>
</div>
```
## URL-Templates
### Einfaches Template
```javascript
// Handler-Konfiguration
const myHandler = {
urlTemplate: '/api/users/{id}/{action}',
method: 'POST'
};
// HTML
<button
data-action="delete"
data-action-handler="my-handler"
data-action-param-id="123"
>
Delete User
</button>
// Wird zu: /api/users/123/delete
```
### Template mit mehreren Parametern
```javascript
// Handler-Konfiguration
const myHandler = {
urlTemplate: '/api/{entity}/{id}/{action}',
method: 'POST'
};
// HTML
<button
data-action="update"
data-action-handler="my-handler"
data-action-param-entity="users"
data-action-param-id="123"
>
Update User
</button>
// Wird zu: /api/users/123/update
```
### Template mit {data:*} Platzhaltern
```javascript
// Handler-Konfiguration
const myHandler = {
urlTemplate: '/api/{data:entity}/{data:id}/{action}',
method: 'POST'
};
// HTML
<button
data-action="delete"
data-action-handler="my-handler"
data-entity="users"
data-id="123"
>
Delete
</button>
// Wird zu: /api/users/123/delete
```
## CSRF-Token Handling
ActionHandler extrahiert CSRF-Token automatisch aus verschiedenen Quellen (in Reihenfolge):
1. `data-csrf-token` Attribut des Action-Elements
2. `data-csrf-token` Attribut des nächstgelegenen `[data-live-component]` Elements
3. `data-csrf-token` Attribut des Containers
4. Meta-Tag `<meta name="csrf-token">`
5. Fallback: Leerer String
Das Token wird automatisch hinzugefügt:
- Header: `X-CSRF-Token`
- Body: `_token` und `_form_id`
## Bestätigungen
### Handler-basierte Bestätigungen
```javascript
const myHandler = {
urlTemplate: '/api/users/{id}/{action}',
confirmations: {
delete: 'Are you sure you want to delete this user?',
update: 'Are you sure you want to update this user?'
}
};
```
### Element-basierte Bestätigungen
```html
<button
data-action="delete"
data-action-confirm="Are you sure?"
data-action-handler="my-handler"
data-action-param-id="123"
>
Delete
</button>
```
## Loading States
### Handler-basierte Loading-Texte
```javascript
const myHandler = {
loadingTexts: {
start: 'Starting...',
stop: 'Stopping...',
delete: 'Deleting...'
}
};
```
### Element-basierte Loading-Texte
```html
<button
data-action="delete"
data-action-loading-text="Deleting user..."
data-action-handler="my-handler"
data-action-param-id="123"
>
Delete
</button>
```
## Toast-Integration
### Handler-basierte Toast-Messages
```javascript
const myHandler = {
successMessages: {
delete: 'User deleted successfully',
update: 'User updated successfully'
},
errorMessages: {
delete: 'Failed to delete user',
update: 'Failed to update user'
}
};
```
### Element-basierte Toast-Messages
```html
<button
data-action="delete"
data-action-success-toast="User deleted!"
data-action-error-toast="Failed to delete user"
data-action-handler="my-handler"
data-action-param-id="123"
>
Delete
</button>
```
## Custom Handler erstellen
### 1. Handler-Konfiguration erstellen
```javascript
// resources/js/modules/common/ActionHandlers.js
export const myCustomHandler = {
urlTemplate: '/api/{entity}/{id}/{action}',
method: 'POST',
confirmations: {
delete: 'Are you sure?'
},
loadingTexts: {
delete: 'Deleting...',
update: 'Updating...'
},
successMessages: {
delete: 'Deleted successfully',
update: 'Updated successfully'
},
errorMessages: {
delete: 'Failed to delete',
update: 'Failed to update'
}
};
```
### 2. Handler registrieren
```javascript
import { ActionHandler } from '/assets/js/modules/common/ActionHandler.js';
import { myCustomHandler } from '/assets/js/modules/common/ActionHandlers.js';
const handler = new ActionHandler('.my-container');
handler.registerHandler('my-handler', myCustomHandler);
```
### 3. Handler verwenden
```html
<button
data-action="delete"
data-action-handler="my-handler"
data-action-param-entity="users"
data-action-param-id="123"
>
Delete User
</button>
```
## Spezielle Action-Typen
### Window-Actions (öffnen in neuem Tab)
```html
<button
data-action="logs"
data-action-type="window"
data-action-url="/api/containers/{id}/logs"
data-action-param-id="123"
>
View Logs
</button>
```
## Best Practices
### 1. Container-Selektor verwenden
Verwende einen spezifischen Container-Selektor, um Konflikte zu vermeiden:
```javascript
// Gut
const handler = new ActionHandler('.docker-containers-component');
// Schlecht
const handler = new ActionHandler('body');
```
### 2. Handler wiederverwenden
Erstelle wiederverwendbare Handler für ähnliche Actions:
```javascript
// Gut: Wiederverwendbarer Handler
const userHandler = {
urlTemplate: '/api/users/{id}/{action}',
// ...
};
// Schlecht: Inline-Konfiguration für jede Action
```
### 3. Konsistente Namenskonventionen
Verwende konsistente Action-Namen:
```javascript
// Gut: RESTful Actions
start, stop, restart, delete, update, create
// Schlecht: Inkonsistente Namen
startContainer, stopContainer, deleteUser, updateUserData
```
### 4. Error Handling
ActionHandler behandelt Errors automatisch, aber du kannst Custom Error-Handling hinzufügen:
```javascript
const handler = new ActionHandler('.container', {
toastHandler: (message, type) => {
if (type === 'error') {
// Custom Error-Logging
console.error('[ActionHandler]', message);
}
// Standard Toast
showToast(message, type);
}
});
```
## Integration in bestehende Komponenten
### Docker Container Actions
```html
<button
data-action="start"
data-action-handler="docker-container"
data-action-param-id="{{containerId}}"
>
Start
</button>
```
### Bulk Operations
```html
<button
data-action="delete"
data-action-handler="bulk-operations"
data-action-param-entity="users"
>
Delete Selected
</button>
```
## API-Referenz
### ActionHandler Konstruktor
```javascript
new ActionHandler(containerSelector, options)
```
**Parameter:**
- `containerSelector` (string): CSS-Selektor für Container-Element
- `options` (object): Konfigurationsoptionen
- `csrfTokenSelector` (string): Selektor für CSRF-Token Element
- `toastHandler` (function): Funktion für Toast-Anzeige
- `confirmationHandler` (function): Funktion für Bestätigungen
- `loadingTexts` (object): Mapping von Action-Namen zu Loading-Texten
- `autoRefresh` (boolean): Automatisches Refresh nach erfolgreicher Action
- `refreshHandler` (function): Funktion für Refresh
### registerHandler
```javascript
handler.registerHandler(name, config)
```
**Parameter:**
- `name` (string): Handler-Name
- `config` (object): Handler-Konfiguration
- `urlTemplate` (string): URL-Template mit Platzhaltern
- `method` (string): HTTP-Methode (default: POST)
- `confirmations` (object): Bestätigungs-Nachrichten pro Action
- `loadingTexts` (object): Loading-Texte pro Action
- `successMessages` (object): Success-Messages pro Action
- `errorMessages` (object): Error-Messages pro Action
### HTML-Attribute
- `data-action`: Action-Name (erforderlich)
- `data-action-handler`: Handler-Name (optional)
- `data-action-url`: Direkte URL (optional, überschreibt Template)
- `data-action-method`: HTTP-Methode (optional, default: POST)
- `data-action-confirm`: Bestätigungs-Nachricht (optional)
- `data-action-loading-text`: Loading-Text (optional)
- `data-action-success-toast`: Success-Message (optional)
- `data-action-error-toast`: Error-Message (optional)
- `data-action-type`: Action-Typ (optional, z.B. "window")
- `data-action-param-*`: Parameter für URL-Template (optional)
## Beispiele
### Beispiel 1: Einfache Action
```html
<div class="user-actions">
<button
data-action="delete"
data-action-handler="user-handler"
data-action-param-id="123"
>
Delete User
</button>
</div>
```
```javascript
import { ActionHandler } from '/assets/js/modules/common/ActionHandler.js';
const handler = new ActionHandler('.user-actions');
handler.registerHandler('user-handler', {
urlTemplate: '/api/users/{id}/{action}',
confirmations: {
delete: 'Are you sure?'
}
});
```
### Beispiel 2: Action mit Custom URL
```html
<button
data-action="custom"
data-action-url="/api/custom-endpoint"
data-action-method="PUT"
>
Custom Action
</button>
```
### Beispiel 3: Action mit mehreren Parametern
```html
<button
data-action="transfer"
data-action-handler="transfer-handler"
data-action-param-from="account-1"
data-action-param-to="account-2"
data-action-param-amount="100"
>
Transfer
</button>
```
```javascript
handler.registerHandler('transfer-handler', {
urlTemplate: '/api/transfer/{param:from}/{param:to}/{param:amount}',
method: 'POST'
});
```
## Troubleshooting
### Actions werden nicht ausgeführt
1. Prüfe, ob Container-Selektor korrekt ist
2. Prüfe, ob `data-action` Attribut vorhanden ist
3. Prüfe Browser-Konsole für Warnungen
4. Prüfe, ob Handler registriert ist
### CSRF-Token-Fehler
1. Prüfe, ob CSRF-Token-Element vorhanden ist
2. Prüfe, ob `csrfTokenSelector` korrekt ist
3. Prüfe, ob Token im HTML vorhanden ist
### URL-Template wird nicht ersetzt
1. Prüfe, ob Platzhalter korrekt geschrieben sind (`{id}`, nicht `{ id }`)
2. Prüfe, ob Parameter-Attribute vorhanden sind (`data-action-param-id`)
3. Prüfe Browser-Konsole für Warnungen
### Toast wird nicht angezeigt
1. Prüfe, ob `toastHandler` konfiguriert ist
2. Prüfe, ob `LiveComponentUIHelper` verfügbar ist
3. Prüfe Browser-Konsole für Fehler