110 lines
3.6 KiB
JavaScript
110 lines
3.6 KiB
JavaScript
/* ===== Radius.js (Vue 3 + TT-Core) ===== */
|
|
|
|
/* ---------- Root View: <radius> ---------- */
|
|
const Radius = {
|
|
name: 'Radius',
|
|
template: `
|
|
<div class="tt-scope radius-container">
|
|
<section class="card card-in">
|
|
<div class="pane-header">
|
|
<div class="title">
|
|
<span class="logo-dot"></span>
|
|
<span>Radius</span>
|
|
</div>
|
|
<nav class="view-tabs">
|
|
<button
|
|
v-for="i in viewOptions"
|
|
:key="i.id"
|
|
class="tab-btn"
|
|
:class="{active: view === i.id}"
|
|
@click="switchView(i.id)"
|
|
>
|
|
<i :class="i.icon"></i> {{ i.name }}
|
|
</button>
|
|
</nav>
|
|
<div class="view-select-wrap select">
|
|
<select v-model="view" @change="switchView($event.target.value)">
|
|
<option v-for="i in viewOptions" :value="i.id">{{ i.name }}</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<hr class="content-divider" />
|
|
<section v-show="view === 'users'" class="card-in">
|
|
<radius-users />
|
|
</section>
|
|
<section v-show="view === 'free'" class="card-in">
|
|
<radius-free-users ref="freeView" />
|
|
</section>
|
|
<section v-show="view === 'unused'" class="card-in">
|
|
<radius-unused-users ref="unusedView" />
|
|
</section>
|
|
<section v-show="view === 'ont'" class="card-in">
|
|
<radius-ont-parser />
|
|
</section>
|
|
<section v-show="view === 'ontReverse'" class="card-in">
|
|
<radius-ont-finder />
|
|
</section>
|
|
<section v-show="view === 'avmscanner'" class="card-in">
|
|
<radius-avm-scanner ref="avmScannerView" />
|
|
</section>
|
|
</section>
|
|
</div>
|
|
`,
|
|
data() {
|
|
return {
|
|
view: 'users',
|
|
window: window,
|
|
_initFlags: {}
|
|
};
|
|
},
|
|
computed: {
|
|
viewOptions() {
|
|
const options = [
|
|
{ id: 'users', name: 'Benutzer', icon: 'fa-duotone fa-users' },
|
|
{ id: 'free', name: 'Freie Benutzer', icon: 'fa-duotone fa-user-plus' },
|
|
{ id: 'unused', name: 'Ungenutzte Benutzer', icon: 'fa-duotone fa-user-clock' },
|
|
{ id: 'avmscanner', name: 'AVM Scanner', icon: 'fa-duotone fa-router' }
|
|
];
|
|
|
|
if (window.TT_CONFIG.CAN_BILLING === '1') {
|
|
options.push(
|
|
{ id: 'ont', name: 'ONT Parser', icon: 'fa-duotone fa-diagram-project' },
|
|
{ id: 'ontReverse', name: 'ONT Reverse', icon: 'fa-duotone fa-arrows-rotate' }
|
|
);
|
|
}
|
|
|
|
return options;
|
|
}
|
|
},
|
|
mounted() {
|
|
this.switchView(this.view);
|
|
},
|
|
methods: {
|
|
switchView(v) {
|
|
this.view = v;
|
|
|
|
if (!this._initFlags || this._initFlags[v]) return;
|
|
|
|
let refName = '';
|
|
if (v === 'free') refName = 'freeView';
|
|
else if (v === 'unused') refName = 'unusedView';
|
|
else if (v === 'avmscanner') refName = 'avmScannerView';
|
|
|
|
if (refName) {
|
|
this.$nextTick(() => {
|
|
const childComponent = this.$refs[refName];
|
|
if (childComponent && typeof childComponent.initIfNeeded === 'function') {
|
|
childComponent.initIfNeeded();
|
|
this._initFlags[v] = true;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// Register component with Vue 3 app
|
|
if (window.VueApp) {
|
|
window.VueApp.component('radius', Radius);
|
|
}
|