autocomit
This commit is contained in:
@@ -0,0 +1,18 @@
|
|||||||
|
# Feature 1
|
||||||
|
Dans l'écran applications, je veux pouvoir ajouter des contacts à l'application.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Feature 2
|
||||||
|
J'aimerais un écran me permettant de gérer les utilisateurs de l'application.
|
||||||
|
(ou de permettre d'utiliser un LDAP pour identifier les users)
|
||||||
|
A ce moment il faudra pouvoir assigner les users aux business units pour qu'ils puissent gérer les entités relatives à cette business unit la.
|
||||||
|
admin peut tout faire.
|
||||||
|
|
||||||
|
|
||||||
|
# Feature 3
|
||||||
|
J'aimerais que les badges "quick access" soient toujours disponible dans une bannière à gauche sur chaque écran.
|
||||||
|
Aujourd'hui les écrans de gestion (business units, applications, environments, personnes ...) sont des pages uniques et ce n'est pas pratique.
|
||||||
|
Je préfèrerais un dashboard cohérent qui me permette d'accéder à tous les éléments de l'application en gardant ce menu à gauche.
|
||||||
|
est-ce clair ? (n'implémente pas encore)
|
||||||
|
|
||||||
|
|||||||
@@ -12,13 +12,16 @@ export const routes: Routes = [
|
|||||||
loadComponent: () => import('./core/auth/login/login.component').then(m => m.LoginComponent)
|
loadComponent: () => import('./core/auth/login/login.component').then(m => m.LoginComponent)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'dashboard',
|
path: '',
|
||||||
canActivate: [authGuard],
|
canActivate: [authGuard],
|
||||||
|
loadComponent: () => import('./core/layout/main-layout/main-layout.component').then(m => m.MainLayoutComponent),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'dashboard',
|
||||||
loadComponent: () => import('./features/dashboard/dashboard.component').then(m => m.DashboardComponent)
|
loadComponent: () => import('./features/dashboard/dashboard.component').then(m => m.DashboardComponent)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'business-units',
|
path: 'business-units',
|
||||||
canActivate: [authGuard],
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
@@ -44,7 +47,6 @@ export const routes: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'applications',
|
path: 'applications',
|
||||||
canActivate: [authGuard],
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
@@ -70,7 +72,6 @@ export const routes: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'environments',
|
path: 'environments',
|
||||||
canActivate: [authGuard],
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
@@ -96,7 +97,6 @@ export const routes: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'persons',
|
path: 'persons',
|
||||||
canActivate: [authGuard],
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
@@ -122,7 +122,6 @@ export const routes: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'contacts',
|
path: 'contacts',
|
||||||
canActivate: [authGuard],
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
@@ -143,8 +142,9 @@ export const routes: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'contact-roles',
|
path: 'contact-roles',
|
||||||
canActivate: [authGuard],
|
|
||||||
loadComponent: () => import('./features/contacts/contact-role-list/contact-role-list.component')
|
loadComponent: () => import('./features/contacts/contact-role-list/contact-role-list.component')
|
||||||
.then(m => m.ContactRoleListComponent)
|
.then(m => m.ContactRoleListComponent)
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<div class="main-layout">
|
||||||
|
<!-- Sidebar Navigation -->
|
||||||
|
<aside class="sidebar">
|
||||||
|
<div class="sidebar-header">
|
||||||
|
<h1>LDPv2</h1>
|
||||||
|
<p class="subtitle">Lifecycle Data Platform</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav class="sidebar-nav">
|
||||||
|
<div
|
||||||
|
*ngFor="let item of navItems"
|
||||||
|
class="nav-item"
|
||||||
|
[class.active]="isActive(item.route)"
|
||||||
|
[style.border-left-color]="item.color"
|
||||||
|
(click)="navigate(item.route)">
|
||||||
|
<span class="nav-icon">{{ item.icon }}</span>
|
||||||
|
<span class="nav-title">{{ item.title }}</span>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="sidebar-footer">
|
||||||
|
<div class="user-info" *ngIf="currentUser">
|
||||||
|
<span class="user-icon">👤</span>
|
||||||
|
<div class="user-details">
|
||||||
|
<div class="username">{{ currentUser.username }}</div>
|
||||||
|
<div class="role-badge">{{ currentUser.role }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button (click)="logout()" class="btn-logout">Logout</button>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<!-- Main Content Area -->
|
||||||
|
<main class="main-content">
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
.main-layout {
|
||||||
|
display: flex;
|
||||||
|
height: 100vh;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
width: 260px;
|
||||||
|
background: linear-gradient(180deg, #667eea 0%, #764ba2 100%);
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-header {
|
||||||
|
padding: 2rem 1.5rem;
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 0 0 0.25rem 0;
|
||||||
|
font-size: 1.75rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-nav {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 1rem 0;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-track {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
border-radius: 3px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 1rem 1.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
border-left: 4px solid transparent;
|
||||||
|
margin: 0.25rem 0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-icon {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin-right: 1rem;
|
||||||
|
width: 30px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-title {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-footer {
|
||||||
|
padding: 1rem 1.5rem;
|
||||||
|
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
|
||||||
|
.user-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
padding: 0.75rem;
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
.user-icon {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-details {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
|
||||||
|
.username {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.role-badge {
|
||||||
|
font-size: 0.7rem;
|
||||||
|
opacity: 0.8;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-logout {
|
||||||
|
width: 100%;
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
color: white;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||||
|
padding: 0.75rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Responsive
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.sidebar {
|
||||||
|
position: fixed;
|
||||||
|
left: -260px;
|
||||||
|
height: 100vh;
|
||||||
|
transition: left 0.3s ease;
|
||||||
|
|
||||||
|
&.open {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Router, RouterModule, NavigationEnd } from '@angular/router';
|
||||||
|
import { AuthService } from '../../auth/auth.service';
|
||||||
|
import { User } from '../../../shared/models/user.model';
|
||||||
|
import { filter } from 'rxjs/operators';
|
||||||
|
|
||||||
|
interface NavItem {
|
||||||
|
title: string;
|
||||||
|
icon: string;
|
||||||
|
route: string;
|
||||||
|
color: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-main-layout',
|
||||||
|
standalone: true,
|
||||||
|
imports: [CommonModule, RouterModule],
|
||||||
|
templateUrl: './main-layout.component.html',
|
||||||
|
styleUrls: ['./main-layout.component.scss']
|
||||||
|
})
|
||||||
|
export class MainLayoutComponent implements OnInit {
|
||||||
|
currentUser: User | null = null;
|
||||||
|
activeRoute: string = '';
|
||||||
|
|
||||||
|
navItems: NavItem[] = [
|
||||||
|
{
|
||||||
|
title: 'Dashboard',
|
||||||
|
icon: '📊',
|
||||||
|
route: '/dashboard',
|
||||||
|
color: '#2196f3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Business Units',
|
||||||
|
icon: '🏢',
|
||||||
|
route: '/business-units',
|
||||||
|
color: '#3f51b5'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Applications',
|
||||||
|
icon: '📱',
|
||||||
|
route: '/applications',
|
||||||
|
color: '#009688'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Environments',
|
||||||
|
icon: '🌍',
|
||||||
|
route: '/environments',
|
||||||
|
color: '#ff9800'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Persons',
|
||||||
|
icon: '👤',
|
||||||
|
route: '/persons',
|
||||||
|
color: '#e91e63'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Contacts',
|
||||||
|
icon: '👥',
|
||||||
|
route: '/contacts',
|
||||||
|
color: '#9c27b0'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Contact Roles',
|
||||||
|
icon: '🎭',
|
||||||
|
route: '/contact-roles',
|
||||||
|
color: '#607d8b'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private router: Router,
|
||||||
|
private authService: AuthService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.currentUser = this.authService.getCurrentUser();
|
||||||
|
this.activeRoute = this.router.url;
|
||||||
|
|
||||||
|
// Listen to route changes to update active route
|
||||||
|
this.router.events.pipe(
|
||||||
|
filter(event => event instanceof NavigationEnd)
|
||||||
|
).subscribe((event: any) => {
|
||||||
|
this.activeRoute = event.url;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
isActive(route: string): boolean {
|
||||||
|
if (route === '/dashboard') {
|
||||||
|
return this.activeRoute === '/dashboard';
|
||||||
|
}
|
||||||
|
return this.activeRoute.startsWith(route);
|
||||||
|
}
|
||||||
|
|
||||||
|
navigate(route: string): void {
|
||||||
|
this.router.navigate([route]);
|
||||||
|
}
|
||||||
|
|
||||||
|
logout(): void {
|
||||||
|
this.authService.logout();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,33 +1,13 @@
|
|||||||
<div class="dashboard">
|
<div class="dashboard-content">
|
||||||
<header class="dashboard-header">
|
<div class="dashboard-header">
|
||||||
<div class="container">
|
<h1>Welcome back, {{ currentUser?.username }}! 👋</h1>
|
||||||
<div class="header-content">
|
<p>Here's an overview of your application lifecycle data.</p>
|
||||||
<div class="branding">
|
|
||||||
<h1>LDPv2</h1>
|
|
||||||
<p class="subtitle">Lifecycle Data Platform</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="user-menu">
|
|
||||||
<span class="user-info" *ngIf="currentUser">
|
|
||||||
<span class="user-icon">👤</span>
|
|
||||||
<span class="username">{{ currentUser.username }}</span>
|
|
||||||
<span class="role-badge">{{ currentUser.role }}</span>
|
|
||||||
</span>
|
|
||||||
<button (click)="logout()" class="btn-logout">Logout</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main class="dashboard-main">
|
|
||||||
<div class="container">
|
|
||||||
<section class="welcome-section">
|
|
||||||
<h2>Welcome back, {{ currentUser?.username }}! 👋</h2>
|
|
||||||
<p>Manage your applications, environments, and business units from one place.</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="stats-section">
|
<section class="stats-section">
|
||||||
|
<h2>Overview</h2>
|
||||||
<div class="stats-grid">
|
<div class="stats-grid">
|
||||||
<div class="stat-card" *ngFor="let stat of stats">
|
<div class="stat-card" *ngFor="let stat of stats" [style.border-left-color]="stat.color">
|
||||||
<div class="stat-icon">{{ stat.icon }}</div>
|
<div class="stat-icon">{{ stat.icon }}</div>
|
||||||
<div class="stat-content">
|
<div class="stat-content">
|
||||||
<div class="stat-value">{{ stat.value }}</div>
|
<div class="stat-value">{{ stat.value }}</div>
|
||||||
@@ -37,59 +17,50 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="features-section">
|
<section class="activity-section">
|
||||||
<h3>Quick Access</h3>
|
<h2>Recent Activity</h2>
|
||||||
<div class="features-grid">
|
<div class="activity-list">
|
||||||
<div
|
<div class="activity-item" *ngFor="let activity of recentActivity">
|
||||||
class="feature-card"
|
<div class="activity-icon">
|
||||||
*ngFor="let feature of features"
|
<span *ngIf="activity.action === 'Created'">✨</span>
|
||||||
(click)="navigate(feature.route)"
|
<span *ngIf="activity.action === 'Updated'">📝</span>
|
||||||
[style.border-left-color]="feature.color">
|
<span *ngIf="activity.action === 'Deleted'">🗑️</span>
|
||||||
<div class="feature-icon">{{ feature.icon }}</div>
|
</div>
|
||||||
<div class="feature-content">
|
<div class="activity-details">
|
||||||
<h4>{{ feature.title }}</h4>
|
<div class="activity-main">
|
||||||
<p>{{ feature.description }}</p>
|
<strong>{{ activity.action }}</strong> {{ activity.entity }}:
|
||||||
|
<span class="entity-name">{{ activity.name }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="activity-time">{{ activity.time }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="feature-arrow">→</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="getting-started">
|
<section class="quick-tips">
|
||||||
<h3>Getting Started</h3>
|
<h2>Quick Tips</h2>
|
||||||
<div class="steps-grid">
|
<div class="tips-grid">
|
||||||
<div class="step-card">
|
<div class="tip-card">
|
||||||
<div class="step-number">1</div>
|
<div class="tip-icon">💡</div>
|
||||||
<h4>Create Business Units</h4>
|
<div class="tip-content">
|
||||||
<p>Organize your applications by business units</p>
|
<h3>Get Started</h3>
|
||||||
<button (click)="navigate('/business-units')" class="btn-link">
|
<p>Use the sidebar to navigate between different sections of the application.</p>
|
||||||
Go to Business Units →
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="step-card">
|
|
||||||
<div class="step-number">2</div>
|
|
||||||
<h4>Add Applications</h4>
|
|
||||||
<p>Register your applications and track their lifecycle</p>
|
|
||||||
<button (click)="navigate('/applications')" class="btn-link">
|
|
||||||
Go to Applications →
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="step-card">
|
<div class="tip-card">
|
||||||
<div class="step-number">3</div>
|
<div class="tip-icon">🔍</div>
|
||||||
<h4>Configure Environments</h4>
|
<div class="tip-content">
|
||||||
<p>Set up deployment environments</p>
|
<h3>Search & Filter</h3>
|
||||||
<button (click)="navigate('/environments')" class="btn-link">
|
<p>Most lists support search and filtering to help you find what you need quickly.</p>
|
||||||
Go to Environments →
|
</div>
|
||||||
</button>
|
</div>
|
||||||
|
<div class="tip-card">
|
||||||
|
<div class="tip-icon">🎯</div>
|
||||||
|
<div class="tip-content">
|
||||||
|
<h3>Track Lifecycle</h3>
|
||||||
|
<p>Monitor your applications' lifecycle from idea to decommission.</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer class="dashboard-footer">
|
|
||||||
<div class="container">
|
|
||||||
<p>LDPv2 - Lifecycle Data Platform v2 | © 2026</p>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
|
|||||||
@@ -1,280 +1,184 @@
|
|||||||
.dashboard {
|
.dashboard-content {
|
||||||
min-height: 100vh;
|
padding: 2rem;
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
max-width: 1400px;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
max-width: 1200px;
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 0 2rem;
|
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-header {
|
.dashboard-header {
|
||||||
background: rgba(255, 255, 255, 0.1);
|
margin-bottom: 2rem;
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
padding: 1.5rem 0;
|
|
||||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
||||||
|
|
||||||
.header-content {
|
h1 {
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.branding h1 {
|
|
||||||
color: white;
|
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
margin: 0;
|
margin: 0 0 0.5rem 0;
|
||||||
font-weight: 700;
|
color: #333;
|
||||||
}
|
|
||||||
|
|
||||||
.branding .subtitle {
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
margin: 0;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-menu {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-info {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
color: white;
|
|
||||||
|
|
||||||
.user-icon { font-size: 1.5rem; }
|
|
||||||
.username { font-weight: 500; }
|
|
||||||
.role-badge {
|
|
||||||
background: rgba(255, 255, 255, 0.2);
|
|
||||||
padding: 0.25rem 0.75rem;
|
|
||||||
border-radius: 12px;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-logout {
|
|
||||||
background: rgba(255, 255, 255, 0.2);
|
|
||||||
color: white;
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
||||||
padding: 0.5rem 1.5rem;
|
|
||||||
border-radius: 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: 500;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.3);
|
|
||||||
transform: translateY(-2px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-main {
|
|
||||||
flex: 1;
|
|
||||||
padding: 3rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.welcome-section {
|
|
||||||
text-align: center;
|
|
||||||
color: white;
|
|
||||||
margin-bottom: 3rem;
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: 2.5rem;
|
|
||||||
margin: 0 0 1rem 0;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
font-size: 1.2rem;
|
margin: 0;
|
||||||
opacity: 0.9;
|
color: #666;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin: 0 0 1.5rem 0;
|
||||||
|
color: #333;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats-grid {
|
.stats-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||||
gap: 1.5rem;
|
gap: 1.5rem;
|
||||||
margin-bottom: 3rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-card {
|
.stat-card {
|
||||||
background: white;
|
background: white;
|
||||||
padding: 2rem;
|
padding: 1.5rem;
|
||||||
border-radius: 12px;
|
border-radius: 8px;
|
||||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 1.5rem;
|
gap: 1rem;
|
||||||
transition: transform 0.3s ease;
|
border-left: 4px solid;
|
||||||
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||||
|
|
||||||
&:hover { transform: translateY(-5px); }
|
&:hover {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
.stat-icon { font-size: 3rem; }
|
.stat-icon {
|
||||||
.stat-value {
|
|
||||||
font-size: 2.5rem;
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-content {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
font-size: 2rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #333;
|
color: #333;
|
||||||
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-label {
|
.stat-label {
|
||||||
color: #666;
|
color: #666;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.features-section {
|
.activity-section {
|
||||||
margin-bottom: 3rem;
|
.activity-list {
|
||||||
|
background: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
h3 {
|
.activity-item {
|
||||||
color: white;
|
display: flex;
|
||||||
font-size: 1.8rem;
|
align-items: center;
|
||||||
margin-bottom: 1.5rem;
|
gap: 1rem;
|
||||||
font-weight: 600;
|
padding: 1rem 1.5rem;
|
||||||
|
border-bottom: 1px solid #f5f5f5;
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-icon {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #f5f5f5;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-details {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.activity-main {
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
|
||||||
|
.entity-name {
|
||||||
|
color: #667eea;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.features-grid {
|
.activity-time {
|
||||||
|
color: #999;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-tips {
|
||||||
|
.tips-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
gap: 1.5rem;
|
gap: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.feature-card {
|
.tip-card {
|
||||||
background: white;
|
background: white;
|
||||||
padding: 2rem;
|
padding: 1.5rem;
|
||||||
border-radius: 12px;
|
border-radius: 8px;
|
||||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
gap: 1rem;
|
||||||
gap: 1.5rem;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
border-left: 4px solid;
|
|
||||||
|
|
||||||
&:hover {
|
.tip-icon {
|
||||||
transform: translateY(-5px);
|
font-size: 2rem;
|
||||||
box-shadow: 0 8px 12px rgba(0, 0, 0, 0.15);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.feature-icon { font-size: 3rem; }
|
.tip-content {
|
||||||
.feature-content {
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
||||||
h4 {
|
h3 {
|
||||||
margin: 0 0 0.5rem 0;
|
margin: 0 0 0.5rem 0;
|
||||||
color: #333;
|
color: #333;
|
||||||
font-size: 1.3rem;
|
font-size: 1.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: #666;
|
color: #666;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.feature-arrow {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.getting-started {
|
|
||||||
h3 {
|
|
||||||
color: white;
|
|
||||||
font-size: 1.8rem;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.steps-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
||||||
gap: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.step-card {
|
|
||||||
background: rgba(255, 255, 255, 0.95);
|
|
||||||
padding: 2rem;
|
|
||||||
border-radius: 12px;
|
|
||||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
||||||
|
|
||||||
.step-number {
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
||||||
color: white;
|
|
||||||
border-radius: 50%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
color: #333;
|
|
||||||
margin: 0 0 0.5rem 0;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
color: #666;
|
|
||||||
margin: 0 0 1rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-link {
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
color: #667eea;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 0;
|
|
||||||
transition: color 0.3s ease;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #764ba2;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-footer {
|
|
||||||
background: rgba(0, 0, 0, 0.2);
|
|
||||||
padding: 1.5rem 0;
|
|
||||||
text-align: center;
|
|
||||||
color: white;
|
|
||||||
margin-top: auto;
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin: 0;
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.dashboard-header .header-content {
|
.dashboard-content {
|
||||||
flex-direction: column;
|
padding: 1rem;
|
||||||
gap: 1rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.welcome-section h2 {
|
.dashboard-header h1 {
|
||||||
font-size: 1.8rem;
|
font-size: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats-grid,
|
.stats-grid,
|
||||||
.features-grid,
|
.tips-grid {
|
||||||
.steps-grid {
|
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { Router } from '@angular/router';
|
|
||||||
import { AuthService } from '../../core/auth/auth.service';
|
import { AuthService } from '../../core/auth/auth.service';
|
||||||
import { User } from '../../shared/models/user.model';
|
import { User } from '../../shared/models/user.model';
|
||||||
|
|
||||||
@@ -14,72 +13,27 @@ import { User } from '../../shared/models/user.model';
|
|||||||
export class DashboardComponent implements OnInit {
|
export class DashboardComponent implements OnInit {
|
||||||
currentUser: User | null = null;
|
currentUser: User | null = null;
|
||||||
|
|
||||||
features = [
|
stats = [
|
||||||
{
|
{ label: 'Business Units', value: '4', icon: '🏢', color: '#3f51b5' },
|
||||||
title: 'Business Units',
|
{ label: 'Applications', value: '7', icon: '📱', color: '#009688' },
|
||||||
description: 'Manage organizational business units',
|
{ label: 'Environments', value: '4', icon: '🌍', color: '#ff9800' },
|
||||||
icon: '🏢',
|
{ label: 'Persons', value: '4', icon: '👤', color: '#e91e63' },
|
||||||
route: '/business-units',
|
{ label: 'Contacts', value: '0', icon: '👥', color: '#9c27b0' },
|
||||||
color: '#3f51b5'
|
{ label: 'Contact Roles', value: '8', icon: '🎭', color: '#607d8b' }
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Applications',
|
|
||||||
description: 'Manage applications and their lifecycle',
|
|
||||||
icon: '📱',
|
|
||||||
route: '/applications',
|
|
||||||
color: '#009688'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Environments',
|
|
||||||
description: 'Manage deployment environments',
|
|
||||||
icon: '🌍',
|
|
||||||
route: '/environments',
|
|
||||||
color: '#ff9800'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Persons',
|
|
||||||
description: 'Manage individual contacts',
|
|
||||||
icon: '👤',
|
|
||||||
route: '/persons',
|
|
||||||
color: '#e91e63'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Contacts',
|
|
||||||
description: 'Manage functional contacts and roles',
|
|
||||||
icon: '👥',
|
|
||||||
route: '/contacts',
|
|
||||||
color: '#9c27b0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Contact Roles',
|
|
||||||
description: 'View predefined contact roles',
|
|
||||||
icon: '🎭',
|
|
||||||
route: '/contact-roles',
|
|
||||||
color: '#607d8b'
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
|
|
||||||
stats = [
|
recentActivity = [
|
||||||
{ label: 'Business Units', value: '4', icon: '🏢' },
|
{ action: 'Created', entity: 'Application', name: 'Mobile App', time: '2 hours ago' },
|
||||||
{ label: 'Applications', value: '7', icon: '📱' },
|
{ action: 'Updated', entity: 'Business Unit', name: 'Digital Services', time: '5 hours ago' },
|
||||||
{ label: 'Environments', value: '4', icon: '🌍' },
|
{ action: 'Created', entity: 'Person', name: 'John Doe', time: '1 day ago' },
|
||||||
{ label: 'Persons', value: '4', icon: '👤' }
|
{ action: 'Updated', entity: 'Environment', name: 'PROD-EU', time: '2 days ago' }
|
||||||
];
|
];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private router: Router,
|
|
||||||
private authService: AuthService
|
private authService: AuthService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.currentUser = this.authService.getCurrentUser();
|
this.currentUser = this.authService.getCurrentUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
navigate(route: string): void {
|
|
||||||
this.router.navigate([route]);
|
|
||||||
}
|
|
||||||
|
|
||||||
logout(): void {
|
|
||||||
this.authService.logout();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user