Refactor MemberTransferDialog to improve configuration handling and UI
Updated the MemberTransferDialog component to enhance user experience by displaying configuration summaries and handling missing configurations more effectively. Removed redundant form sections and added conditional rendering for login credentials. Improved validation logic for transfer settings and introduced new styles for better visual clarity.
This commit is contained in:
@@ -12,160 +12,81 @@
|
||||
</div>
|
||||
|
||||
<div v-else class="transfer-form">
|
||||
<div class="form-section">
|
||||
<h4>Server-Konfiguration</h4>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="server">Server-Basis-URL:</label>
|
||||
<input
|
||||
type="text"
|
||||
id="server"
|
||||
v-model="config.server"
|
||||
placeholder="https://example.com"
|
||||
class="form-input"
|
||||
readonly
|
||||
/>
|
||||
<span class="hint">Aus Einstellungen geladen (nur lesend)</span>
|
||||
</div>
|
||||
<div v-if="!hasConfig" class="config-missing">
|
||||
<p><strong>Keine Konfiguration gefunden</strong></p>
|
||||
<p>Bitte konfigurieren Sie zuerst die Mitgliederübertragung in den Einstellungen.</p>
|
||||
<router-link to="/member-transfer-settings" class="btn-link" @click="handleClose">
|
||||
Zu den Einstellungen
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<div class="form-section">
|
||||
<h4>Login-Konfiguration</h4>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="loginEndpoint">Login-Endpoint Pfad:</label>
|
||||
<input
|
||||
type="text"
|
||||
id="loginEndpoint"
|
||||
v-model="config.loginEndpoint"
|
||||
placeholder="/api/auth/login"
|
||||
class="form-input"
|
||||
/>
|
||||
<span class="hint">Optional: Relativer Pfad zum Login-Endpoint</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="loginFormat">Login-Format:</label>
|
||||
<select id="loginFormat" v-model="config.loginFormat" class="form-select">
|
||||
<option value="json">JSON</option>
|
||||
<option value="form-data">Form Data</option>
|
||||
<option value="x-www-form-urlencoded">URL Encoded</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Login-Daten:</label>
|
||||
<div class="credentials-group">
|
||||
<div class="credential-row">
|
||||
<input
|
||||
type="text"
|
||||
v-model="loginCredentials.username"
|
||||
placeholder="Benutzername / Email"
|
||||
class="form-input"
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
v-model="loginCredentials.password"
|
||||
placeholder="Passwort"
|
||||
class="form-input"
|
||||
/>
|
||||
<div v-else>
|
||||
<div class="config-summary">
|
||||
<h4>Übertragungskonfiguration</h4>
|
||||
<div class="summary-info">
|
||||
<div class="summary-row">
|
||||
<span class="summary-label">Server:</span>
|
||||
<span class="summary-value">{{ config.server }}</span>
|
||||
</div>
|
||||
<div class="credential-row">
|
||||
<input
|
||||
type="text"
|
||||
v-model="loginCredentials.additionalField1"
|
||||
:placeholder="additionalField1Placeholder"
|
||||
class="form-input"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
v-model="loginCredentials.additionalField2"
|
||||
:placeholder="additionalField2Placeholder"
|
||||
class="form-input"
|
||||
/>
|
||||
<div class="summary-row">
|
||||
<span class="summary-label">Endpoint:</span>
|
||||
<span class="summary-value">{{ config.transferEndpoint }}</span>
|
||||
</div>
|
||||
<div class="summary-row">
|
||||
<span class="summary-label">Methode:</span>
|
||||
<span class="summary-value">{{ config.transferMethod }}</span>
|
||||
</div>
|
||||
<div class="summary-row">
|
||||
<span class="summary-label">Format:</span>
|
||||
<span class="summary-value">{{ config.transferFormat }}</span>
|
||||
</div>
|
||||
<div class="summary-row">
|
||||
<span class="summary-label">Modus:</span>
|
||||
<span class="summary-value">{{ config.useBulkMode ? 'Bulk-Import' : 'Einzeln' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="hint">Zusätzliche Felder werden nur verwendet, wenn sie ausgefüllt sind</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-section">
|
||||
<h4>Übertragungs-Konfiguration</h4>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="transferEndpoint">Übertragungs-Endpoint Pfad: <span class="required">*</span></label>
|
||||
<input
|
||||
type="text"
|
||||
id="transferEndpoint"
|
||||
v-model="config.transferEndpoint"
|
||||
placeholder="/api/members/bulk"
|
||||
class="form-input"
|
||||
required
|
||||
/>
|
||||
<span class="hint">Relativer Pfad zum Übertragungs-Endpoint</span>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="transferMethod">HTTP-Methode:</label>
|
||||
<select id="transferMethod" v-model="config.transferMethod" class="form-select">
|
||||
<option value="POST">POST</option>
|
||||
<option value="PUT">PUT</option>
|
||||
<option value="GET">GET</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="transferFormat">Übertragungs-Format:</label>
|
||||
<select id="transferFormat" v-model="config.transferFormat" class="form-select">
|
||||
<option value="json">JSON</option>
|
||||
<option value="xml">XML</option>
|
||||
<option value="form-data">Form Data</option>
|
||||
<option value="x-www-form-urlencoded">URL Encoded</option>
|
||||
</select>
|
||||
</div>
|
||||
<router-link to="/member-transfer-settings" class="btn-link-small" @click="handleClose">
|
||||
Konfiguration bearbeiten
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="checkbox-item">
|
||||
<input type="checkbox" v-model="config.useBulkMode" />
|
||||
<span>Bulk-Import-Modus (alle Mitglieder auf einmal übertragen)</span>
|
||||
</label>
|
||||
<span class="hint">Wenn aktiviert, werden alle Mitglieder in einem Request als Array übertragen. Das Template definiert das Format für ein einzelnes Mitglied.</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="transferTemplate">Übertragungs-Template: <span class="required">*</span></label>
|
||||
<textarea
|
||||
id="transferTemplate"
|
||||
v-model="config.transferTemplate"
|
||||
rows="8"
|
||||
class="form-textarea"
|
||||
placeholder='{"name": "{{firstName}} {{lastName}}", "email": "{{email}}", "phone": "{{phone}}"}'
|
||||
required
|
||||
></textarea>
|
||||
<div class="template-help">
|
||||
<strong>Verfügbare Platzhalter:</strong>
|
||||
<ul>
|
||||
<li><code>{{firstName}}</code> - Vorname</li>
|
||||
<li><code>{{lastName}}</code> - Nachname</li>
|
||||
<li><code>{{fullName}}</code> - Vollständiger Name</li>
|
||||
<li><code>{{email}}</code> - E-Mail-Adresse</li>
|
||||
<li><code>{{phone}}</code> - Telefonnummer</li>
|
||||
<li><code>{{street}}</code> - Straße</li>
|
||||
<li><code>{{city}}</code> - Ort</li>
|
||||
<li><code>{{birthDate}}</code> - Geburtsdatum (YYYY-MM-DD)</li>
|
||||
<li><code>{{geburtsdatum}}</code> - Geburtsdatum (YYYY-MM-DD, alternativ)</li>
|
||||
<li><code>{{address}}</code> - Kombinierte Adresse (Straße, Ort)</li>
|
||||
<li><code>{{ttr}}</code> - TTR-Wert</li>
|
||||
<li><code>{{qttr}}</code> - QTTR-Wert</li>
|
||||
<li><code>{{gender}}</code> - Geschlecht</li>
|
||||
</ul>
|
||||
<p><strong>Beispiel JSON (für einzelnes Mitglied):</strong></p>
|
||||
<pre>{{ jsonExample }}</pre>
|
||||
<p v-if="config.useBulkMode" class="bulk-hint">
|
||||
<strong>Bulk-Modus aktiv:</strong> Das Template wird für jedes Mitglied angewendet und automatisch in <code>{"members": [...]}</code> gewrappt.
|
||||
</p>
|
||||
<div v-if="config.loginEndpoint" class="form-section">
|
||||
<h4>Login-Daten (optional überschreiben)</h4>
|
||||
<p class="section-hint">Die Login-Daten werden aus den Einstellungen verwendet. Sie können sie hier überschreiben, falls nötig.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Login-Daten:</label>
|
||||
<div class="credentials-group">
|
||||
<div class="credential-row">
|
||||
<input
|
||||
type="text"
|
||||
v-model="loginCredentials.username"
|
||||
placeholder="Benutzername / Email"
|
||||
class="form-input"
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
v-model="loginCredentials.password"
|
||||
placeholder="Passwort (leer lassen für gespeichertes)"
|
||||
class="form-input"
|
||||
/>
|
||||
</div>
|
||||
<div class="credential-row">
|
||||
<input
|
||||
type="text"
|
||||
v-model="loginCredentials.additionalField1"
|
||||
:placeholder="additionalField1Placeholder"
|
||||
class="form-input"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
v-model="loginCredentials.additionalField2"
|
||||
:placeholder="additionalField2Placeholder"
|
||||
class="form-input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span class="hint">Nur ausfüllen, wenn Sie die gespeicherten Login-Daten überschreiben möchten. Leere Felder verwenden die gespeicherten Werte.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -204,6 +125,10 @@ export default {
|
||||
...mapGetters(['currentClub']),
|
||||
|
||||
isValid() {
|
||||
return this.hasConfig && !!(this.config.server && this.config.transferEndpoint && this.config.transferTemplate);
|
||||
},
|
||||
|
||||
hasConfig() {
|
||||
return !!(this.config.server && this.config.transferEndpoint && this.config.transferTemplate);
|
||||
},
|
||||
|
||||
@@ -219,17 +144,6 @@ export default {
|
||||
return 'Feldname: Wert (z.B. client_secret: xyz789)';
|
||||
}
|
||||
return 'Zusätzliches Feld (z.B. client_secret)';
|
||||
},
|
||||
|
||||
jsonExample() {
|
||||
return JSON.stringify({
|
||||
firstName: "{{firstName}}",
|
||||
lastName: "{{lastName}}",
|
||||
geburtsdatum: "{{geburtsdatum}}",
|
||||
email: "{{email}}",
|
||||
phone: "{{phone}}",
|
||||
address: "{{address}}"
|
||||
}, null, 2);
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -242,7 +156,8 @@ export default {
|
||||
transferMethod: 'POST',
|
||||
transferFormat: 'json',
|
||||
transferTemplate: '',
|
||||
useBulkMode: false
|
||||
useBulkMode: false,
|
||||
bulkWrapperTemplate: ''
|
||||
},
|
||||
loginCredentials: {
|
||||
username: '',
|
||||
@@ -283,14 +198,15 @@ export default {
|
||||
this.config.transferFormat = savedConfig.transferFormat || 'json';
|
||||
this.config.transferTemplate = savedConfig.transferTemplate || '';
|
||||
this.config.useBulkMode = savedConfig.useBulkMode || false;
|
||||
this.config.bulkWrapperTemplate = savedConfig.bulkWrapperTemplate || '';
|
||||
|
||||
// Login-Credentials (Passwort wird nicht zurückgegeben, nur wenn vorhanden)
|
||||
if (savedConfig.loginCredentials) {
|
||||
this.loginCredentials.username = savedConfig.loginCredentials.username || '';
|
||||
this.loginCredentials.password = ''; // Passwort wird nicht zurückgegeben
|
||||
// Zusätzliche Felder können nicht direkt zugewiesen werden, da sie verschlüsselt sind
|
||||
// Benutzer muss diese neu eingeben
|
||||
}
|
||||
// Login-Credentials zurücksetzen (werden nur verwendet, wenn im Dialog eingegeben)
|
||||
this.loginCredentials = {
|
||||
username: '',
|
||||
password: '',
|
||||
additionalField1: '',
|
||||
additionalField2: ''
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
// Keine Konfiguration vorhanden - das ist OK, Dialog bleibt leer
|
||||
@@ -315,7 +231,8 @@ export default {
|
||||
transferMethod: 'POST',
|
||||
transferFormat: 'json',
|
||||
transferTemplate: '',
|
||||
useBulkMode: false
|
||||
useBulkMode: false,
|
||||
bulkWrapperTemplate: ''
|
||||
};
|
||||
this.loginCredentials = {
|
||||
username: '',
|
||||
@@ -367,7 +284,8 @@ export default {
|
||||
transferMethod: this.config.transferMethod,
|
||||
transferFormat: this.config.transferFormat,
|
||||
transferTemplate: this.config.transferTemplate,
|
||||
useBulkMode: this.config.useBulkMode
|
||||
useBulkMode: this.config.useBulkMode,
|
||||
bulkWrapperTemplate: this.config.bulkWrapperTemplate || null
|
||||
};
|
||||
|
||||
// Login-Konfiguration nur hinzufügen, wenn Endpoint vorhanden
|
||||
@@ -578,6 +496,92 @@ export default {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.config-missing {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
background-color: #fff3cd;
|
||||
border: 1px solid #ffc107;
|
||||
border-radius: 6px;
|
||||
color: #856404;
|
||||
}
|
||||
|
||||
.config-missing p {
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
.btn-link {
|
||||
display: inline-block;
|
||||
margin-top: 1rem;
|
||||
padding: 0.75rem 1.5rem;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
font-weight: 500;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.btn-link:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.config-summary {
|
||||
background-color: #f8f9fa;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 6px;
|
||||
padding: 1.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.config-summary h4 {
|
||||
margin: 0 0 1rem 0;
|
||||
color: #333;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.summary-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.summary-row {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.summary-label {
|
||||
font-weight: 600;
|
||||
color: #555;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.summary-value {
|
||||
color: #333;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.btn-link-small {
|
||||
display: inline-block;
|
||||
color: #007bff;
|
||||
text-decoration: none;
|
||||
font-size: 0.9em;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.btn-link-small:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.section-hint {
|
||||
margin: 0 0 1rem 0;
|
||||
font-size: 0.9em;
|
||||
color: #666;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
|
||||
Reference in New Issue
Block a user