134 lines
4.8 KiB
PHP
134 lines
4.8 KiB
PHP
<?php
|
|
if (!isset($vueViewName)) die("vueViewName is not set");
|
|
if (!isset($mfLayoutPackage)) die("mfLayoutPackage is not set");
|
|
|
|
$additionalCSS = $additionalCSS ?? [];
|
|
$additionalJS = $additionalJS ?? [];
|
|
$vueViewPath = BASEDIR . "/public/js/pages/$vueViewName";
|
|
|
|
// Load page-specific CSS and JS files
|
|
if (is_dir($vueViewPath)) {
|
|
foreach (scandir($vueViewPath) as $file) {
|
|
if ($file === '.' || $file === '..') continue;
|
|
|
|
$fileExtension = pathinfo($file, PATHINFO_EXTENSION);
|
|
if ($fileExtension === 'css') $additionalCSS[] = "js/pages/$vueViewName/$file";
|
|
else if ($fileExtension === 'js') $additionalJS[] = "js/pages/$vueViewName/$file";
|
|
}
|
|
}
|
|
|
|
// Add TT-Core CSS
|
|
$additionalCSS = [
|
|
"plugins/vue/tt-core/styles/tt-core.css",
|
|
...$additionalCSS,
|
|
];
|
|
|
|
/**
|
|
* Convert PascalCase to snake_case (e.g. PascalCase to pascal-case)
|
|
* @param string $str PascalCase string
|
|
* @return string snake-case string
|
|
*/
|
|
function pascalToSnakeCase(string $str): string {
|
|
return strtolower(preg_replace('/(?<!^)([A-Z])/', '-$1', $str));
|
|
}
|
|
|
|
$vueTagName = pascalToSnakeCase($vueViewName);
|
|
|
|
$vueHeaderPath = realpath(dirname(__FILE__) . "/../../$mfLayoutPackage") . "/vueHeader3.php";
|
|
if (!file_exists($vueHeaderPath))
|
|
$vueHeaderPath = realpath(dirname(__FILE__) . "/../../default") . "/vueHeader3.php";
|
|
|
|
include($vueHeaderPath); ?>
|
|
|
|
<div id="app">
|
|
<<?php echo $vueTagName; ?>>
|
|
</<?php echo $vueTagName; ?>>
|
|
</div>
|
|
|
|
<!-- TT-Core Library -->
|
|
<script src="<?php echo mfBaseController::getUrl(""); ?>plugins/vue/tt-core/index.js" type="module"></script>
|
|
|
|
<!-- Vue 3 Initialization -->
|
|
<script>
|
|
// TT-Core components to load
|
|
const ttCoreComponents = [
|
|
'plugins/vue/tt-core/components/data-display/TtDataTable.js',
|
|
'plugins/vue/tt-core/components/data-display/TtStatusChip.js',
|
|
'plugins/vue/tt-core/components/display/TtInfoCard.js',
|
|
'plugins/vue/tt-core/components/feedback/TtLoadingIndicator.js',
|
|
'plugins/vue/tt-core/components/feedback/TtSkeleton.js',
|
|
'plugins/vue/tt-core/components/forms/TtSmartAutocomplete.js',
|
|
'plugins/vue/tt-core/components/forms/TtFileDropzone.js',
|
|
'plugins/vue/tt-core/components/forms/TtCopyButton.js',
|
|
'plugins/vue/tt-core/components/overlays/TtDialog.js',
|
|
'plugins/vue/tt-core/components/navigation/TtViewSwitcher.js'
|
|
];
|
|
|
|
// All additional scripts
|
|
const allScripts = <?php echo json_encode($additionalJS); ?>;
|
|
|
|
// Separate Chart.js libraries (need to load first)
|
|
const chartLibs = allScripts.filter(s => s.includes('chart.js/chart.'));
|
|
const chartAdapters = allScripts.filter(s => s.includes('chartjs-adapter'));
|
|
const pageScripts = allScripts.filter(s => !s.includes('chart.js/') && !s.includes('chartjs-adapter'));
|
|
|
|
// Wait for TT_CORE to be loaded (since index.js is a module and loads async)
|
|
function initVueApp() {
|
|
if (typeof window.TT_CORE === 'undefined') {
|
|
// TT_CORE not loaded yet, wait a bit and try again
|
|
setTimeout(initVueApp, 50);
|
|
return;
|
|
}
|
|
|
|
const { createApp } = Vue;
|
|
|
|
const app = createApp({
|
|
data() {
|
|
return {
|
|
window: window
|
|
};
|
|
}
|
|
});
|
|
|
|
// CRITICAL: Register TT-Core components and set window.VueApp
|
|
window.TT_CORE.registerComponents(app);
|
|
|
|
// Load scripts in order:
|
|
// 1. TT-Core components
|
|
// 2. Chart.js library (if needed)
|
|
// 3. Chart.js adapters (after Chart.js)
|
|
// 4. Page-specific components
|
|
loadScripts(ttCoreComponents)
|
|
.then(() => chartLibs.length ? loadScripts(chartLibs) : Promise.resolve())
|
|
.then(() => chartAdapters.length ? loadScripts(chartAdapters) : Promise.resolve())
|
|
.then(() => loadScripts(pageScripts))
|
|
.then(() => {
|
|
// Mount the app after all components are loaded and registered
|
|
app.mount('#app');
|
|
})
|
|
.catch(err => {
|
|
console.error('Failed to load components:', err);
|
|
});
|
|
}
|
|
|
|
// Dynamically load scripts
|
|
function loadScripts(scriptPaths) {
|
|
const baseUrl = '<?php echo mfBaseController::getUrl(""); ?>';
|
|
const promises = scriptPaths.map(src => {
|
|
return new Promise((resolve, reject) => {
|
|
const script = document.createElement('script');
|
|
script.src = baseUrl + src;
|
|
script.onload = resolve;
|
|
script.onerror = () => reject(new Error(`Failed to load ${src}`));
|
|
document.body.appendChild(script);
|
|
});
|
|
});
|
|
return Promise.all(promises);
|
|
}
|
|
|
|
// Start initialization
|
|
initVueApp();
|
|
</script>
|
|
|
|
<?php include(realpath(dirname(__FILE__) . "/../../$mfLayoutPackage") . "/footer.php"); ?>
|