Improve Team-indeling dashboard UI and cache invalidation
- Replace 'TEAM' label with Type attribute (Business/Enabling/Staf) in team blocks - Make Type labels larger (text-sm) and brighter colors - Make SUBTEAM label less bright (indigo-300) and smaller (text-[10px]) - Add 'FTE' suffix to bandbreedte values in header and application blocks - Add Platform and Connected Device labels to application blocks - Show Platform FTE and Workloads FTE separately in Platform blocks - Add spacing between Regiemodel letter and count value - Add cache invalidation for Team Dashboard when applications are updated - Enrich team references with Type attribute in getSubteamToTeamMapping
This commit is contained in:
@@ -6,13 +6,18 @@ import cookieParser from 'cookie-parser';
|
||||
import { config, validateConfig } from './config/env.js';
|
||||
import { logger } from './services/logger.js';
|
||||
import { dataService } from './services/dataService.js';
|
||||
import { syncEngine } from './services/syncEngine.js';
|
||||
import { cmdbService } from './services/cmdbService.js';
|
||||
import applicationsRouter from './routes/applications.js';
|
||||
import classificationsRouter from './routes/classifications.js';
|
||||
import referenceDataRouter from './routes/referenceData.js';
|
||||
import dashboardRouter from './routes/dashboard.js';
|
||||
import configurationRouter from './routes/configuration.js';
|
||||
import authRouter, { authMiddleware } from './routes/auth.js';
|
||||
import { jiraAssetsService } from './services/jiraAssets.js';
|
||||
import searchRouter from './routes/search.js';
|
||||
import cacheRouter from './routes/cache.js';
|
||||
import objectsRouter from './routes/objects.js';
|
||||
import schemaRouter from './routes/schema.js';
|
||||
|
||||
// Validate configuration
|
||||
validateConfig();
|
||||
@@ -50,16 +55,16 @@ app.use((req, res, next) => {
|
||||
// Auth middleware - extract session info for all requests
|
||||
app.use(authMiddleware);
|
||||
|
||||
// Set user token on JiraAssets service for each request
|
||||
// Set user token on CMDBService for each request (for user-specific OAuth)
|
||||
app.use((req, res, next) => {
|
||||
// Set user's OAuth token if available
|
||||
if (req.accessToken) {
|
||||
jiraAssetsService.setRequestToken(req.accessToken);
|
||||
cmdbService.setUserToken(req.accessToken);
|
||||
}
|
||||
|
||||
// Clear token after response is sent
|
||||
res.on('finish', () => {
|
||||
jiraAssetsService.clearRequestToken();
|
||||
cmdbService.clearUserToken();
|
||||
});
|
||||
|
||||
next();
|
||||
@@ -68,12 +73,19 @@ app.use((req, res, next) => {
|
||||
// Health check
|
||||
app.get('/health', async (req, res) => {
|
||||
const jiraConnected = await dataService.testConnection();
|
||||
const cacheStatus = dataService.getCacheStatus();
|
||||
|
||||
res.json({
|
||||
status: 'ok',
|
||||
timestamp: new Date().toISOString(),
|
||||
dataSource: dataService.isUsingJiraAssets() ? 'jira-assets' : 'mock-data',
|
||||
dataSource: dataService.isUsingJiraAssets() ? 'jira-assets-cached' : 'mock-data',
|
||||
jiraConnected: dataService.isUsingJiraAssets() ? jiraConnected : null,
|
||||
aiConfigured: !!config.anthropicApiKey,
|
||||
cache: {
|
||||
isWarm: cacheStatus.isWarm,
|
||||
objectCount: cacheStatus.totalObjects,
|
||||
lastSync: cacheStatus.lastIncrementalSync,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -91,6 +103,10 @@ app.use('/api/classifications', classificationsRouter);
|
||||
app.use('/api/reference-data', referenceDataRouter);
|
||||
app.use('/api/dashboard', dashboardRouter);
|
||||
app.use('/api/configuration', configurationRouter);
|
||||
app.use('/api/search', searchRouter);
|
||||
app.use('/api/cache', cacheRouter);
|
||||
app.use('/api/objects', objectsRouter);
|
||||
app.use('/api/schema', schemaRouter);
|
||||
|
||||
// Error handling
|
||||
app.use((err: Error, req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
@@ -108,20 +124,33 @@ app.use((req, res) => {
|
||||
|
||||
// Start server
|
||||
const PORT = config.port;
|
||||
app.listen(PORT, () => {
|
||||
app.listen(PORT, async () => {
|
||||
logger.info(`Server running on http://localhost:${PORT}`);
|
||||
logger.info(`Environment: ${config.nodeEnv}`);
|
||||
logger.info(`AI Classification: ${config.anthropicApiKey ? 'Configured' : 'Not configured'}`);
|
||||
logger.info(`Jira Assets: ${config.jiraPat ? 'Configured' : 'Using mock data'}`);
|
||||
logger.info(`Jira Assets: ${config.jiraPat ? 'Configured with caching' : 'Using mock data'}`);
|
||||
|
||||
// Initialize sync engine if using Jira Assets
|
||||
if (config.jiraPat && config.jiraSchemaId) {
|
||||
try {
|
||||
await syncEngine.initialize();
|
||||
logger.info('Sync Engine: Initialized and running');
|
||||
} catch (error) {
|
||||
logger.error('Failed to initialize sync engine', error);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Graceful shutdown
|
||||
process.on('SIGTERM', () => {
|
||||
logger.info('SIGTERM signal received: closing HTTP server');
|
||||
const shutdown = () => {
|
||||
logger.info('Shutdown signal received: stopping services...');
|
||||
|
||||
// Stop sync engine
|
||||
syncEngine.stop();
|
||||
|
||||
logger.info('Services stopped, exiting');
|
||||
process.exit(0);
|
||||
});
|
||||
};
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
logger.info('SIGINT signal received: closing HTTP server');
|
||||
process.exit(0);
|
||||
});
|
||||
process.on('SIGTERM', shutdown);
|
||||
process.on('SIGINT', shutdown);
|
||||
|
||||
Reference in New Issue
Block a user