Building TotalGPT SaaS Website #13: Single Page Applications (SPA) - Admin Panel (Part 1)
Welcome back to our TotalGPT development series! After implementing our REST API for plan management in the previous post, we're now ready to take a significant step forward: creating a Single Page Application (SPA) for our admin panel using Total.js JComponent.
Understanding Single Page Applications in Total.js
Before diving into the code, let's understand what we're building. A Single Page Application (SPA) provides a fluid, desktop-like experience where page reloads are minimal. In Total.js, we can create SPAs efficiently using JComponent, particularly for admin panels.
The Basic Concept
The core idea is straightforward but powerful:
- All admin routes (starting with
/admin/
) are handled by two main scenarios:
- Authenticated users see the admin panel
- Unauthenticated users see the login page
Setting Up Basic Routes
Let's start with the basic routing structure:
//controllers/default.js
exports.install = function() {
ROUTE('+GET /admin/*', admin); // Protected route (requires auth)
ROUTE('-GET /admin/*', login); // Public route (no auth required)
}
function admin($) {
$.view('admin');
}
function login($) {
$.view('login');
}
The magic lies in the +
and -
prefixes:
+GET
: Route requires authentication
-GET
: Route is accessible without authentication
Enhanced Authentication for Admin Panel
For a more sophisticated application with different types of authentication (like user vs admin), we need a specialized approach. We'll create a dedicated admin module to handle this separation of concerns.
Creating the Admin Module
We'll move our admin-related functionality into a dedicated module (/modules/admin.js
):
// modules/admin.js
exports.install = function() {
ROUTE('+GET /admin/*', admin);
ROUTE('-GET /admin/*', login);
};
function admin($) {
// Prepare plugins for admin panel
var plugins = [];
var hostname = $.hostname();
// Update configuration URL if needed
if (CONF.url !== hostname)
CONF.url = hostname;
// Process available plugins
for (var key in F.plugins) {
var item = F.plugins[key];
if (!item.visible || item.visible($.user)) {
var obj = {
id: item.id,
position: item.position,
name: TRANSLATOR($.user.language || '', item.name),
icon: item.icon,
import: item.import,
routes: item.routes,
hidden: item.hidden
};
plugins.push(obj);
}
}
$.view('admin', plugins);
}
// Custom admin authentication handler
FUNC.authadmin = function($) {
// Rate limiting check
if (BLOCKED($, 10)) {
$.invalid();
return;
}
var user = Storage.user;
var token = $.cookie(user.cookie);
if (token) {
var session = DECRYPTREQ($, token, user.salt);
if (session && session.id === user.login && session.expire > NOW) {
BLOCKED($, null);
$.success({
id: user.id,
name: user.name,
sa: user.sa,
permissions: user.permissions
});
return;
}
}
$.invalid();
};
function login($) {
$.view('login');
}
Updating your AUTH() implementation
// /definitions/auth.js
const ADMIN = { id: 'admin', sa: true, name: 'Admin', permissions: [] };
const BOT = { id: 'bot', sa: true, name: 'Bot', permissions: [] };
AUTH(function($) {
var path = $.split[0];
if (path === 'admin') {
var token = $.headers['x-token'];
if (token) {
if (BLOCKED($, 10)) {
$.invalid();
return;
}
if (token === CONF.token) {
BLOCKED($, -1);
$.success(BOT);
}
} else if (CONF.op_reqtoken && CONF.op_restoken)
OpenPlatform.auth($);
else if (FUNC.authadmin)
FUNC.authadmin($);
else
$.success(ADMIN);
}
// previous code here
});
Why Create a Module?
Creating a separate module for admin functionality offers several benefits:
- Reusability: The module can be reused in other Total.js projects
- Organization: Keeps admin-related code separate from main application logic
- Maintainability: Easier to update and modify admin features
- Scalability: Simple to extend with new admin features
Plugin System Integration
Notice how we're preparing for plugin support in our admin function. This sets us up for a flexible, extensible admin panel where new features can be added as plugins. We'll dive deeper into this in the next blog post.
What's Next?
In Part 2 of this series, we'll:
- Create the
admin.html
and login.html
views
- Set up the basic structure of our admin panel
- Implement the authentication flow
- Create a responsive layout for our admin interface
Stay tuned to learn how to build a professional, plugin-based admin panel using Total.js JComponent! 🚀