Add NocoDB configuration tab to admin settings for persistent database connectivity
Build And Push Image / docker (push) Successful in 2m12s
Details
Build And Push Image / docker (push) Successful in 2m12s
Details
This commit is contained in:
parent
3b455a3989
commit
f84adeff21
|
|
@ -61,7 +61,11 @@
|
|||
"Read(/Z:\\Repos\\monacousa-portal\\assets\\scss/**)",
|
||||
"Read(/Z:\\Repos\\monacousa-portal\\pages\\admin/**)",
|
||||
"Read(/Z:\\Repos\\monacousa-portal\\pages\\admin/**)",
|
||||
"Read(/Z:\\Repos\\monacousa-portal\\pages\\admin/**)"
|
||||
"Read(/Z:\\Repos\\monacousa-portal\\pages\\admin/**)",
|
||||
"Read(/Z:\\Repos\\monacousa-portal\\pages\\admin\\dashboard/**)",
|
||||
"Read(/Z:\\Repos\\monacousa-portal\\components/**)",
|
||||
"Read(/Z:\\Repos\\monacousa-portal\\components/**)",
|
||||
"Read(/Z:\\Repos\\monacousa-portal\\pages\\admin\\settings/**)"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -118,14 +118,14 @@
|
|||
</v-card-text>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<v-card-actions class="pa-4 pt-0">
|
||||
<v-card-actions class="pa-4 pt-0 d-flex justify-center">
|
||||
<v-btn
|
||||
color="success"
|
||||
variant="elevated"
|
||||
size="small"
|
||||
height="44"
|
||||
:loading="loading"
|
||||
@click="showPaymentDateDialog = true"
|
||||
block
|
||||
class="px-4"
|
||||
>
|
||||
<v-icon start size="16">mdi-check-circle</v-icon>
|
||||
Mark as Paid
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@
|
|||
<v-icon start>mdi-email</v-icon>
|
||||
Email
|
||||
</v-tab>
|
||||
<v-tab value="nocodb">
|
||||
<v-icon start>mdi-database</v-icon>
|
||||
NocoDB
|
||||
</v-tab>
|
||||
</v-tabs>
|
||||
|
||||
<v-window v-model="activeTab">
|
||||
|
|
@ -327,6 +331,178 @@
|
|||
</v-row>
|
||||
</v-card-text>
|
||||
</v-window-item>
|
||||
|
||||
<!-- NocoDB Settings -->
|
||||
<v-window-item value="nocodb">
|
||||
<v-card-text>
|
||||
<!-- Edit Mode Toggle -->
|
||||
<v-row class="mb-4">
|
||||
<v-col>
|
||||
<v-alert
|
||||
v-if="!nocodbEditMode"
|
||||
type="info"
|
||||
variant="tonal"
|
||||
density="compact"
|
||||
>
|
||||
<template v-slot:text>
|
||||
Click "Edit NocoDB Configuration" to modify database settings
|
||||
</template>
|
||||
</v-alert>
|
||||
<v-alert
|
||||
v-if="nocodbEditMode"
|
||||
type="warning"
|
||||
variant="tonal"
|
||||
density="compact"
|
||||
>
|
||||
<template v-slot:text>
|
||||
NocoDB configuration is required for member management functionality
|
||||
</template>
|
||||
</v-alert>
|
||||
</v-col>
|
||||
<v-col cols="auto">
|
||||
<v-btn
|
||||
v-if="!nocodbEditMode"
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
@click="nocodbEditMode = true"
|
||||
>
|
||||
<v-icon start>mdi-pencil</v-icon>
|
||||
Edit NocoDB Configuration
|
||||
</v-btn>
|
||||
<v-btn-group v-else>
|
||||
<v-btn
|
||||
color="success"
|
||||
variant="flat"
|
||||
@click="saveNocodbSettings"
|
||||
>
|
||||
<v-icon start>mdi-check</v-icon>
|
||||
Save
|
||||
</v-btn>
|
||||
<v-btn
|
||||
color="warning"
|
||||
variant="outlined"
|
||||
@click="testNocodbConnection"
|
||||
:loading="testingNocodb"
|
||||
>
|
||||
<v-icon start>mdi-connection</v-icon>
|
||||
Test Connection
|
||||
</v-btn>
|
||||
<v-btn
|
||||
color="error"
|
||||
variant="outlined"
|
||||
@click="cancelNocodbEdit"
|
||||
>
|
||||
<v-icon start>mdi-close</v-icon>
|
||||
Cancel
|
||||
</v-btn>
|
||||
</v-btn-group>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<h3 class="text-h6 mb-4">NocoDB Database Configuration</h3>
|
||||
</v-col>
|
||||
<v-col cols="12">
|
||||
<v-text-field
|
||||
v-model="settings.nocodb.url"
|
||||
label="NocoDB URL"
|
||||
variant="outlined"
|
||||
placeholder="https://your-nocodb-instance.com"
|
||||
:readonly="!nocodbEditMode"
|
||||
:disabled="!nocodbEditMode"
|
||||
autocomplete="off"
|
||||
:class="{ 'readonly-field': !nocodbEditMode }"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12">
|
||||
<v-text-field
|
||||
v-model="settings.nocodb.apiKey"
|
||||
label="API Key"
|
||||
variant="outlined"
|
||||
:type="showNocodbApiKey ? 'text' : 'password'"
|
||||
placeholder="Enter your NocoDB API token"
|
||||
:readonly="!nocodbEditMode"
|
||||
:disabled="!nocodbEditMode"
|
||||
autocomplete="new-password"
|
||||
:class="{ 'readonly-field': !nocodbEditMode }"
|
||||
>
|
||||
<template v-slot:append-inner>
|
||||
<v-icon
|
||||
v-if="nocodbEditMode"
|
||||
@click="showNocodbApiKey = !showNocodbApiKey"
|
||||
:icon="showNocodbApiKey ? 'mdi-eye-off' : 'mdi-eye'"
|
||||
class="cursor-pointer"
|
||||
/>
|
||||
</template>
|
||||
</v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12">
|
||||
<v-text-field
|
||||
v-model="settings.nocodb.baseId"
|
||||
label="Base ID"
|
||||
variant="outlined"
|
||||
placeholder="Your NocoDB base ID"
|
||||
:readonly="!nocodbEditMode"
|
||||
:disabled="!nocodbEditMode"
|
||||
autocomplete="off"
|
||||
:class="{ 'readonly-field': !nocodbEditMode }"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12">
|
||||
<v-divider class="my-4" />
|
||||
</v-col>
|
||||
<v-col cols="12">
|
||||
<h3 class="text-h6 mb-4">Table Mappings</h3>
|
||||
</v-col>
|
||||
<v-col cols="12" md="4">
|
||||
<v-text-field
|
||||
v-model="settings.nocodb.tables.members"
|
||||
label="Members Table"
|
||||
variant="outlined"
|
||||
:readonly="!nocodbEditMode"
|
||||
:disabled="!nocodbEditMode"
|
||||
autocomplete="off"
|
||||
:class="{ 'readonly-field': !nocodbEditMode }"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" md="4">
|
||||
<v-text-field
|
||||
v-model="settings.nocodb.tables.events"
|
||||
label="Events Table"
|
||||
variant="outlined"
|
||||
:readonly="!nocodbEditMode"
|
||||
:disabled="!nocodbEditMode"
|
||||
autocomplete="off"
|
||||
:class="{ 'readonly-field': !nocodbEditMode }"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" md="4">
|
||||
<v-text-field
|
||||
v-model="settings.nocodb.tables.rsvps"
|
||||
label="RSVPs Table"
|
||||
variant="outlined"
|
||||
:readonly="!nocodbEditMode"
|
||||
:disabled="!nocodbEditMode"
|
||||
autocomplete="off"
|
||||
:class="{ 'readonly-field': !nocodbEditMode }"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<!-- Connection Status -->
|
||||
<v-row v-if="nocodbConnectionStatus" class="mt-4">
|
||||
<v-col>
|
||||
<v-alert
|
||||
:type="nocodbConnectionStatus.success ? 'success' : 'error'"
|
||||
variant="tonal"
|
||||
>
|
||||
{{ nocodbConnectionStatus.message }}
|
||||
</v-alert>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-window-item>
|
||||
</v-window>
|
||||
</v-card>
|
||||
|
||||
|
|
@ -359,8 +535,12 @@ definePageMeta({
|
|||
const activeTab = ref('general');
|
||||
const generalEditMode = ref(false);
|
||||
const emailEditMode = ref(false);
|
||||
const nocodbEditMode = ref(false);
|
||||
const showPassword = ref(false);
|
||||
const showNocodbApiKey = ref(false);
|
||||
const testingEmail = ref(false);
|
||||
const testingNocodb = ref(false);
|
||||
const nocodbConnectionStatus = ref<{ success: boolean; message: string } | null>(null);
|
||||
const snackbar = ref(false);
|
||||
const snackbarText = ref('');
|
||||
const snackbarColor = ref('success');
|
||||
|
|
@ -386,6 +566,16 @@ const settings = ref({
|
|||
useTLS: true,
|
||||
fromName: 'MonacoUSA',
|
||||
fromEmail: 'noreply@monacousa.org'
|
||||
},
|
||||
nocodb: {
|
||||
url: '',
|
||||
apiKey: '',
|
||||
baseId: '',
|
||||
tables: {
|
||||
members: 'Members',
|
||||
events: 'Events',
|
||||
rsvps: 'RSVPs'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -413,6 +603,7 @@ const currencies = [
|
|||
// Load settings on mount
|
||||
onMounted(async () => {
|
||||
await loadSettings();
|
||||
await loadNocodbSettings();
|
||||
});
|
||||
|
||||
// Methods
|
||||
|
|
@ -488,6 +679,84 @@ const showNotification = (text: string, color: string = 'success') => {
|
|||
snackbar.value = true;
|
||||
};
|
||||
|
||||
const loadNocodbSettings = async () => {
|
||||
try {
|
||||
const response = await $fetch<{ success: boolean; data?: any }>('/api/admin/nocodb-config');
|
||||
if (response.success && response.data) {
|
||||
settings.value.nocodb = {
|
||||
url: response.data.url || '',
|
||||
apiKey: response.data.apiKey || '',
|
||||
baseId: response.data.baseId || '',
|
||||
tables: response.data.tables || {
|
||||
members: 'Members',
|
||||
events: 'Events',
|
||||
rsvps: 'RSVPs'
|
||||
}
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading NocoDB settings:', error);
|
||||
showNotification('Failed to load NocoDB settings', 'error');
|
||||
}
|
||||
};
|
||||
|
||||
const saveNocodbSettings = async () => {
|
||||
try {
|
||||
const response = await $fetch('/api/admin/nocodb-config', {
|
||||
method: 'POST',
|
||||
body: settings.value.nocodb
|
||||
});
|
||||
nocodbEditMode.value = false;
|
||||
showNocodbApiKey.value = false;
|
||||
showNotification('NocoDB settings saved successfully', 'success');
|
||||
// Reload settings to ensure they're persistent
|
||||
await loadNocodbSettings();
|
||||
} catch (error) {
|
||||
console.error('Error saving NocoDB settings:', error);
|
||||
showNotification('Failed to save NocoDB settings', 'error');
|
||||
}
|
||||
};
|
||||
|
||||
const testNocodbConnection = async () => {
|
||||
testingNocodb.value = true;
|
||||
nocodbConnectionStatus.value = null;
|
||||
|
||||
try {
|
||||
const response = await $fetch<{ success: boolean; message: string }>('/api/admin/nocodb-test', {
|
||||
method: 'POST',
|
||||
body: settings.value.nocodb
|
||||
});
|
||||
|
||||
nocodbConnectionStatus.value = {
|
||||
success: response.success,
|
||||
message: response.message
|
||||
};
|
||||
|
||||
if (response.success) {
|
||||
showNotification('NocoDB connection successful', 'success');
|
||||
} else {
|
||||
showNotification(response.message, 'error');
|
||||
}
|
||||
} catch (error: any) {
|
||||
nocodbConnectionStatus.value = {
|
||||
success: false,
|
||||
message: error.data?.message || 'Failed to connect to NocoDB'
|
||||
};
|
||||
showNotification('Connection test failed', 'error');
|
||||
} finally {
|
||||
testingNocodb.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const cancelNocodbEdit = () => {
|
||||
if (originalSettings.value) {
|
||||
settings.value.nocodb = { ...originalSettings.value.nocodb };
|
||||
}
|
||||
nocodbEditMode.value = false;
|
||||
showNocodbApiKey.value = false;
|
||||
nocodbConnectionStatus.value = null;
|
||||
};
|
||||
|
||||
// Watch for edit mode changes to backup original settings
|
||||
watch(generalEditMode, (newVal) => {
|
||||
if (newVal) {
|
||||
|
|
@ -505,6 +774,14 @@ watch(emailEditMode, (newVal) => {
|
|||
}
|
||||
});
|
||||
|
||||
watch(nocodbEditMode, (newVal) => {
|
||||
if (newVal) {
|
||||
originalSettings.value = {
|
||||
nocodb: { ...settings.value.nocodb }
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// Prevent browser autofill on mount
|
||||
onMounted(() => {
|
||||
// Disable autofill for all inputs initially
|
||||
|
|
|
|||
Loading…
Reference in New Issue