Initial commit

This commit is contained in:
root
2025-12-21 09:55:58 -05:00
committed by Sebastian Krupinski
commit 169b7b4c91
57 changed files with 10105 additions and 0 deletions

View File

@@ -0,0 +1,124 @@
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { useIntegrationStore } from '@KTXC/stores/integrationStore'
import type { ServiceLocation } from '@MailManager/types/service'
const props = defineProps<{
providerId: string
discoveredLocation?: ServiceLocation
modelValue?: ServiceLocation | null
}>()
const emit = defineEmits<{
'update:modelValue': [value: ServiceLocation]
'valid': [value: boolean]
}>()
const integrationStore = useIntegrationStore()
const loadedPanels = new Map<string, any>()
const currentProviderPanel = ref<any>(null)
const loadingPanel = ref(false)
const localLocation = ref<ServiceLocation | undefined>(props.modelValue || props.discoveredLocation)
// The full integration ID (e.g., "provider_jmapc.jmap")
const effectiveIntegrationId = computed(() => {
return props.providerId
})
// Load provider panel dynamically using the integration ID
async function loadProviderPanel(integrationId: string) {
if (loadedPanels.has(integrationId)) {
currentProviderPanel.value = loadedPanels.get(integrationId)
return
}
loadingPanel.value = true
// Try to find panel - integration IDs are prefixed with module handle
// so we need to search for panels that match the provider ID
const panels = integrationStore.getItems('mail_account_config_panels')
const panelConfig = panels.find((panel: any) => {
// Check if the ID ends with the provider ID (e.g., "provider_jmapc.jmap" contains "jmap")
return panel.id === integrationId || panel.id.endsWith(`.${integrationId}`)
})
if (!panelConfig?.component) {
console.warn(`No config panel found for provider ID: ${integrationId}`)
console.warn(`Available panels:`, panels.map((p: any) => p.id))
currentProviderPanel.value = null
loadingPanel.value = false
return
}
try {
const module = await panelConfig.component()
const component = module.default || module
loadedPanels.set(integrationId, component)
currentProviderPanel.value = component
} catch (error) {
console.error(`Failed to load panel for ${integrationId}:`, error)
currentProviderPanel.value = null
} finally {
loadingPanel.value = false
}
}
watch(effectiveIntegrationId, (newIntegrationId, oldIntegrationId) => {
if (newIntegrationId && newIntegrationId !== oldIntegrationId) {
loadProviderPanel(newIntegrationId)
}
}, { immediate: true })
function handleLocationUpdate(location: ServiceLocation) {
localLocation.value = location
emit('update:modelValue', location)
// Emit valid when location is provided
emit('valid', !!location)
}
// Watch for prop changes
watch(() => props.modelValue, (newValue) => {
if (newValue) {
localLocation.value = newValue
}
})
watch(() => props.discoveredLocation, (newValue) => {
if (newValue && !props.modelValue) {
localLocation.value = newValue
emit('update:modelValue', newValue)
emit('valid', true)
}
})
</script>
<template>
<div class="provider-config-step">
<h3 class="text-h6 mb-2">Protocol Configuration</h3>
<p class="text-body-2 text-medium-emphasis mb-6">
Configure the connection settings for your mail service
</p>
<!-- Dynamic Provider Panel -->
<component
v-if="currentProviderPanel"
:is="currentProviderPanel"
v-model="localLocation"
:discovered-location="discoveredLocation"
@update:model-value="handleLocationUpdate"
/>
<!-- Loading state for panel -->
<div v-else-if="loadingPanel" class="text-center py-8">
<v-progress-circular indeterminate color="primary" />
<p class="text-caption text-medium-emphasis mt-2">Loading configuration panel...</p>
</div>
<!-- No panel available -->
<v-alert v-else type="info" variant="tonal">
<v-icon start>mdi-information</v-icon>
No configuration panel available for this provider
</v-alert>
</div>
</template>