Changes for eveai_chat_client:
- Modal display of privacy statement & Terms & Conditions - Consent-flag ==> check of privacy and Terms & Conditions - customisation option added to show or hide DynamicForm titles
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
// eveai_chat_client/static/assets/js/composables/useContentModal.js
|
||||
|
||||
import { ref, reactive, provide, inject } from 'vue';
|
||||
|
||||
// Injection key for the composable
|
||||
export const CONTENT_MODAL_KEY = Symbol('contentModal');
|
||||
|
||||
// Create the composable
|
||||
export function useContentModal() {
|
||||
// Reactive state for modal
|
||||
const modalState = reactive({
|
||||
show: false,
|
||||
title: '',
|
||||
content: '',
|
||||
version: '',
|
||||
loading: false,
|
||||
error: false,
|
||||
errorMessage: '',
|
||||
lastContentUrl: '' // Add this for retry functionality
|
||||
});
|
||||
|
||||
// Content cache to avoid repeated API calls
|
||||
const contentCache = ref({});
|
||||
|
||||
// Show modal with content
|
||||
const showModal = async (options = {}) => {
|
||||
const {
|
||||
title = 'Content',
|
||||
contentUrl = null,
|
||||
content = null,
|
||||
version = ''
|
||||
} = options;
|
||||
|
||||
// Set initial state
|
||||
modalState.show = true;
|
||||
modalState.title = title;
|
||||
modalState.content = content || '';
|
||||
modalState.version = version;
|
||||
modalState.loading = !!contentUrl; // Only show loading if we need to fetch content
|
||||
modalState.error = false;
|
||||
modalState.errorMessage = '';
|
||||
modalState.lastContentUrl = contentUrl || ''; // Store for retry functionality
|
||||
|
||||
// If content is provided directly, no need to fetch
|
||||
if (content) {
|
||||
modalState.loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// If contentUrl is provided, fetch the content
|
||||
if (contentUrl) {
|
||||
await loadContent(contentUrl);
|
||||
}
|
||||
};
|
||||
|
||||
// Hide modal
|
||||
const hideModal = () => {
|
||||
console.log('Hiding content modal');
|
||||
modalState.show = false;
|
||||
modalState.title = '';
|
||||
modalState.content = '';
|
||||
modalState.version = '';
|
||||
modalState.loading = false;
|
||||
modalState.error = false;
|
||||
modalState.errorMessage = '';
|
||||
modalState.lastContentUrl = ''; // Clear for next use
|
||||
};
|
||||
|
||||
// Load content from API
|
||||
const loadContent = async (contentUrl) => {
|
||||
try {
|
||||
console.log('Loading content from:', contentUrl);
|
||||
modalState.loading = true;
|
||||
modalState.error = false;
|
||||
modalState.errorMessage = '';
|
||||
|
||||
// Check cache first
|
||||
if (contentCache.value[contentUrl]) {
|
||||
console.log('Content found in cache for:', contentUrl);
|
||||
const cached = contentCache.value[contentUrl];
|
||||
modalState.content = cached.content;
|
||||
modalState.version = cached.version;
|
||||
modalState.loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch from API
|
||||
console.log('Fetching content from API:', contentUrl);
|
||||
const response = await fetch(contentUrl);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
console.log('API response received:', {
|
||||
hasSuccess: data.success !== undefined,
|
||||
hasContent: data.content !== undefined,
|
||||
hasError: data.error !== undefined,
|
||||
contentLength: data.content ? data.content.length : 0
|
||||
});
|
||||
|
||||
// Support both response formats
|
||||
if (data.success !== undefined) {
|
||||
// New format with success property
|
||||
if (data.success) {
|
||||
modalState.content = data.content || '';
|
||||
modalState.version = data.version || '';
|
||||
} else {
|
||||
throw new Error(data.error || 'Onbekende fout bij het laden van content');
|
||||
}
|
||||
} else if (data.content !== undefined) {
|
||||
// Legacy format without success property (current privacy/terms endpoints)
|
||||
modalState.content = data.content || '';
|
||||
modalState.version = data.version || '';
|
||||
} else if (data.error) {
|
||||
// Error response format
|
||||
throw new Error(data.message || data.error || 'Er is een fout opgetreden');
|
||||
} else {
|
||||
throw new Error('Invalid response format: no content or success property found');
|
||||
}
|
||||
|
||||
// Cache the result
|
||||
contentCache.value[contentUrl] = {
|
||||
content: modalState.content,
|
||||
version: modalState.version,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error loading content:', error);
|
||||
modalState.error = true;
|
||||
modalState.errorMessage = error.message || 'Er is een fout opgetreden bij het laden van de content.';
|
||||
} finally {
|
||||
modalState.loading = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Retry loading content
|
||||
const retryLoad = async () => {
|
||||
if (modalState.lastContentUrl) {
|
||||
console.log('Retrying content load for:', modalState.lastContentUrl);
|
||||
await loadContent(modalState.lastContentUrl);
|
||||
} else {
|
||||
console.warn('No content URL available for retry');
|
||||
modalState.error = true;
|
||||
modalState.errorMessage = 'Geen content URL beschikbaar voor opnieuw proberen.';
|
||||
}
|
||||
};
|
||||
|
||||
// Clear cache (useful for development or when content updates)
|
||||
const clearCache = () => {
|
||||
contentCache.value = {};
|
||||
};
|
||||
|
||||
// Get cache size for debugging
|
||||
const getCacheInfo = () => {
|
||||
return {
|
||||
size: Object.keys(contentCache.value).length,
|
||||
entries: Object.keys(contentCache.value)
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
// State
|
||||
modalState,
|
||||
|
||||
// Methods
|
||||
showModal,
|
||||
hideModal,
|
||||
loadContent,
|
||||
retryLoad,
|
||||
clearCache,
|
||||
getCacheInfo
|
||||
};
|
||||
}
|
||||
|
||||
// Provider function to be used in the root component
|
||||
export function provideContentModal() {
|
||||
const contentModal = useContentModal();
|
||||
provide(CONTENT_MODAL_KEY, contentModal);
|
||||
return contentModal;
|
||||
}
|
||||
|
||||
// Injector function to be used in child components
|
||||
export function injectContentModal() {
|
||||
const contentModal = inject(CONTENT_MODAL_KEY);
|
||||
if (!contentModal) {
|
||||
throw new Error('useContentModal must be provided before it can be injected');
|
||||
}
|
||||
return contentModal;
|
||||
}
|
||||
@@ -211,7 +211,7 @@ export function useComponentTranslations(componentName, originalTexts) {
|
||||
const translations = provider.registerComponent(componentName, originalTexts);
|
||||
|
||||
return {
|
||||
translations: computed(() => translations.translated),
|
||||
texts: computed(() => translations.translated),
|
||||
isLoading: computed(() => translations.isLoading),
|
||||
error: computed(() => translations.error),
|
||||
currentLanguage: provider.currentLanguage
|
||||
|
||||
Reference in New Issue
Block a user