Radius/add network structure
This commit is contained in:
133
Layout/default/VueViews/Vue3.php
Normal file
133
Layout/default/VueViews/Vue3.php
Normal file
@@ -0,0 +1,133 @@
|
||||
<?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"); ?>
|
||||
83
Layout/default/vueHeader3.php
Normal file
83
Layout/default/vueHeader3.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title><?= MFAPPNAME_FULL ?></title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="shortcut icon" href="<?= self::getResourcePath() ?>assets/images/favicon.ico">
|
||||
|
||||
<link href="<?= self::getResourcePath() ?>cssbundler.php?<?= $git_merge_ts ?>" rel="stylesheet">
|
||||
<link href="<?= self::getResourcePath() ?>fontawesome/css/fontawesome.min.css?<?= $git_merge_ts ?>"
|
||||
rel="stylesheet">
|
||||
<link href="<?= self::getResourcePath() ?>fontawesome/css/solid.min.css?<?= $git_merge_ts ?>" rel="stylesheet">
|
||||
<link href="<?= self::getResourcePath() ?>fontawesome/css/regular.min.css?<?= $git_merge_ts ?>" rel="stylesheet">
|
||||
<link href="<?=self::getResourcePath()?>fontawesome/css/duotone.min.css?<?=$git_merge_ts?>" rel="stylesheet" type="text/css" />
|
||||
<link href="<?=self::getResourcePath()?>fontawesome/css/duotone-regular.min.css?<?=$git_merge_ts?>" rel="stylesheet" type="text/css" />
|
||||
<link href="<?= self::getResourcePath() ?>fontawesome/css/sharp-light.min.css?<?= $git_merge_ts ?>"
|
||||
rel="stylesheet">
|
||||
|
||||
<?php if (!empty($additionalCSS)):
|
||||
foreach ($additionalCSS as $css): ?>
|
||||
<link rel="stylesheet" href="<?= self::getResourcePath() ?><?= $css ?>?<?= $git_merge_ts ?>">
|
||||
<?php endforeach;
|
||||
endif;
|
||||
|
||||
if (!empty($additionalHead)):
|
||||
foreach ($additionalHead as $head):
|
||||
echo $head;
|
||||
endforeach;
|
||||
endif; ?>
|
||||
|
||||
<script>
|
||||
const baseurl = '<?=self::getResourcePath()?>';
|
||||
window.mfNotify = <?=json_encode($mfNotify ?? null)?>;
|
||||
window.TT_CONFIG = {};
|
||||
<?php
|
||||
if(isset($JSGlobals) && is_array($JSGlobals) && count($JSGlobals)):
|
||||
foreach($JSGlobals as $key => $value): ?>
|
||||
window.TT_CONFIG.<?=$key?> = <?=is_array($value) ? json_encode($value) : "'$value'"; ?>;
|
||||
<?php endforeach; endif;?>
|
||||
</script>
|
||||
<script type="text/javascript" src="<?=self::getResourcePath()?>js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="<?=self::getResourcePath()?>js/popper.min.js"></script>
|
||||
<script type="text/javascript" src="<?=self::getResourcePath()?>js/bootstrap.min.js"></script>
|
||||
|
||||
<!-- Vue 3 CDN -->
|
||||
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
|
||||
|
||||
<!-- Axios for HTTP requests -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
||||
|
||||
<!-- Moment.js for date handling -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/moment@2.29.4/moment.min.js"></script>
|
||||
|
||||
<script src="<?= self::getResourcePath() ?>plugins/notification/notify.js" defer></script>
|
||||
<script src="<?= self::getResourcePath() ?>plugins/bookstack/bookstackIntegration.js" defer></script>
|
||||
|
||||
<style>
|
||||
body {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
<?php if (MFAPPNAME === "devthetool"): ?>
|
||||
body {
|
||||
border-left: 8px dashed #f672a7;
|
||||
}
|
||||
|
||||
<?php endif; ?>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header id="topnav">
|
||||
<?php
|
||||
include(__DIR__ . "/topbar.php");
|
||||
include(__DIR__ . "/menu.php");
|
||||
?>
|
||||
</header>
|
||||
|
||||
<div class="wrapper pl-0 pl-lg-1 pr-0 pr-lg-1">
|
||||
<div class="container-fluid">
|
||||
Reference in New Issue
Block a user