cloud-ide-layout 1.0.60 → 1.0.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/{cloud-ide-layout-cloud-ide-layout-1E6BVapU.mjs → cloud-ide-layout-cloud-ide-layout-CKLj-6xH.mjs} +358 -10
- package/fesm2022/cloud-ide-layout-cloud-ide-layout-CKLj-6xH.mjs.map +1 -0
- package/fesm2022/{cloud-ide-layout-drawer-theme.component-Bss-muvl.mjs → cloud-ide-layout-drawer-theme.component-DMn2Cznf.mjs} +2 -2
- package/fesm2022/{cloud-ide-layout-drawer-theme.component-Bss-muvl.mjs.map → cloud-ide-layout-drawer-theme.component-DMn2Cznf.mjs.map} +1 -1
- package/fesm2022/{cloud-ide-layout-floating-entity-selection.component-Rj3H5MCt.mjs → cloud-ide-layout-floating-entity-selection.component-L3hZ4LJm.mjs} +2 -2
- package/fesm2022/{cloud-ide-layout-floating-entity-selection.component-Rj3H5MCt.mjs.map → cloud-ide-layout-floating-entity-selection.component-L3hZ4LJm.mjs.map} +1 -1
- package/fesm2022/{cloud-ide-layout-home-wrapper.component-CAhqIqjG.mjs → cloud-ide-layout-home-wrapper.component-ZWphfyNz.mjs} +2 -2
- package/fesm2022/{cloud-ide-layout-home-wrapper.component-CAhqIqjG.mjs.map → cloud-ide-layout-home-wrapper.component-ZWphfyNz.mjs.map} +1 -1
- package/fesm2022/{cloud-ide-layout-sidedrawer-notes.component-CbJfxbUI.mjs → cloud-ide-layout-sidedrawer-notes.component-sYWI-yH9.mjs} +2 -2
- package/fesm2022/{cloud-ide-layout-sidedrawer-notes.component-CbJfxbUI.mjs.map → cloud-ide-layout-sidedrawer-notes.component-sYWI-yH9.mjs.map} +1 -1
- package/fesm2022/cloud-ide-layout.mjs +1 -1
- package/package.json +1 -1
- package/fesm2022/cloud-ide-layout-cloud-ide-layout-1E6BVapU.mjs.map +0 -1
|
@@ -7,7 +7,7 @@ import { map, filter, tap, catchError, shareReplay, take, distinctUntilChanged }
|
|
|
7
7
|
import * as i2 from '@angular/router';
|
|
8
8
|
import { Router, NavigationEnd, RouteReuseStrategy, RouterModule } from '@angular/router';
|
|
9
9
|
import { Title } from '@angular/platform-browser';
|
|
10
|
-
import { CideEleFileManagerService, CideElementsService, CideEleFloatingContainerService, CideInputComponent, CideIconComponent, CideEleDropdownComponent, CideEleFileImageDirective, CideEleResizerDirective, TooltipDirective, CideSpinnerComponent, CideEleSkeletonLoaderComponent, CideEleFloatingContainerManagerComponent, CideEleGlobalNotificationsComponent, CideEleBreadcrumbComponent, CideEleButtonComponent } from 'cloud-ide-element';
|
|
10
|
+
import { CideEleFileManagerService, CideElementsService, CideEleFloatingContainerService, WebSocketNotificationService, NotificationApiService, CideInputComponent, CideIconComponent, CideEleDropdownComponent, CideEleFileImageDirective, CideEleResizerDirective, TooltipDirective, CideSpinnerComponent, CideEleSkeletonLoaderComponent, CideEleFloatingContainerManagerComponent, CideEleGlobalNotificationsComponent, CideEleBreadcrumbComponent, CideEleButtonComponent } from 'cloud-ide-element';
|
|
11
11
|
import * as i1 from '@angular/common';
|
|
12
12
|
import { CommonModule, NgClass, NgFor, NgIf, isPlatformBrowser } from '@angular/common';
|
|
13
13
|
import { FINANCIAL_YEAR_SERVICE_TOKEN, ACADEMIC_YEAR_SERVICE_TOKEN, AUTH_SERVICE_TOKEN, authGuard, ENTITY_SERVICE_TOKEN } from 'cloud-ide-shared';
|
|
@@ -1266,7 +1266,7 @@ class CideLytFloatingEntitySelectionService {
|
|
|
1266
1266
|
}
|
|
1267
1267
|
try {
|
|
1268
1268
|
// Use relative import to avoid circular dependency
|
|
1269
|
-
const module = await import('./cloud-ide-layout-floating-entity-selection.component-
|
|
1269
|
+
const module = await import('./cloud-ide-layout-floating-entity-selection.component-L3hZ4LJm.mjs');
|
|
1270
1270
|
if (module.CideLytFloatingEntitySelectionComponent) {
|
|
1271
1271
|
this.containerService.registerComponent('entity-selection-header', module.CideLytFloatingEntitySelectionComponent);
|
|
1272
1272
|
console.log('✅ Entity selection component registered successfully');
|
|
@@ -1349,6 +1349,7 @@ class CideLytHeaderWrapperComponent {
|
|
|
1349
1349
|
triggerTemplate;
|
|
1350
1350
|
financialYearTriggerTemplate;
|
|
1351
1351
|
academicYearTriggerTemplate;
|
|
1352
|
+
notificationTriggerTemplate;
|
|
1352
1353
|
// Inject app state service to get active entity
|
|
1353
1354
|
appStateService = inject(AppStateService);
|
|
1354
1355
|
// Inject floating entity selection service
|
|
@@ -1364,6 +1365,11 @@ class CideLytHeaderWrapperComponent {
|
|
|
1364
1365
|
currentAcademicYear = signal(null, ...(ngDevMode ? [{ debugName: "currentAcademicYear" }] : []));
|
|
1365
1366
|
currentFinancialYearName = signal('FY', ...(ngDevMode ? [{ debugName: "currentFinancialYearName" }] : []));
|
|
1366
1367
|
currentAcademicYearName = signal('AY', ...(ngDevMode ? [{ debugName: "currentAcademicYearName" }] : []));
|
|
1368
|
+
// Signals for notifications
|
|
1369
|
+
notifications = signal([], ...(ngDevMode ? [{ debugName: "notifications" }] : []));
|
|
1370
|
+
unreadCount = computed(() => this.wsNotificationService?.unreadNotificationsCount() || 0, ...(ngDevMode ? [{ debugName: "unreadCount" }] : []));
|
|
1371
|
+
isNotificationDropdownOpen = signal(false, ...(ngDevMode ? [{ debugName: "isNotificationDropdownOpen" }] : []));
|
|
1372
|
+
notificationItems = [];
|
|
1367
1373
|
// Financial Year Dropdown Configuration
|
|
1368
1374
|
financialYearItems = [];
|
|
1369
1375
|
financialYearConfig = {
|
|
@@ -1382,6 +1388,14 @@ class CideLytHeaderWrapperComponent {
|
|
|
1382
1388
|
menuWidth: 'tw-w-72',
|
|
1383
1389
|
usePortal: true
|
|
1384
1390
|
};
|
|
1391
|
+
// Notification Dropdown Configuration
|
|
1392
|
+
notificationConfig = {
|
|
1393
|
+
triggerIcon: '',
|
|
1394
|
+
triggerSize: 'md',
|
|
1395
|
+
menuPosition: 'right',
|
|
1396
|
+
menuWidth: 'tw-w-96',
|
|
1397
|
+
usePortal: true
|
|
1398
|
+
};
|
|
1385
1399
|
// Profile Dropdown Configuration (moved from more options)
|
|
1386
1400
|
profileItems = [
|
|
1387
1401
|
{
|
|
@@ -1463,6 +1477,8 @@ class CideLytHeaderWrapperComponent {
|
|
|
1463
1477
|
fileManagerService = inject(CideLytFileManagerService);
|
|
1464
1478
|
router = inject(Router);
|
|
1465
1479
|
authService = inject(AUTH_SERVICE_TOKEN);
|
|
1480
|
+
wsNotificationService = inject(WebSocketNotificationService);
|
|
1481
|
+
notificationApiService = inject(NotificationApiService);
|
|
1466
1482
|
constructor() {
|
|
1467
1483
|
// Trigger page-data workflow for header (without rendering breadcrumb)
|
|
1468
1484
|
const entityId = this.appStateService.activeEntity()?._id || undefined;
|
|
@@ -1478,6 +1494,313 @@ class CideLytHeaderWrapperComponent {
|
|
|
1478
1494
|
ngOnInit() {
|
|
1479
1495
|
this.loadFinancialYears();
|
|
1480
1496
|
this.loadAcademicYears();
|
|
1497
|
+
// Initialize notification dropdown with empty state
|
|
1498
|
+
this.updateNotificationDropdown();
|
|
1499
|
+
// Then try to load notifications
|
|
1500
|
+
this.initializeNotifications();
|
|
1501
|
+
}
|
|
1502
|
+
/**
|
|
1503
|
+
* Initialize notification system
|
|
1504
|
+
*/
|
|
1505
|
+
initializeNotifications() {
|
|
1506
|
+
try {
|
|
1507
|
+
const user = this.appStateService.currentUser();
|
|
1508
|
+
if (!user || !user._id) {
|
|
1509
|
+
console.warn('[Notifications] User not available, skipping initialization');
|
|
1510
|
+
return;
|
|
1511
|
+
}
|
|
1512
|
+
// Get token from localStorage (using auth service storage key)
|
|
1513
|
+
const token = localStorage.getItem('cide_auth_token') || localStorage.getItem('auth_token') || localStorage.getItem('token') || '';
|
|
1514
|
+
if (!token) {
|
|
1515
|
+
console.warn('[Notifications] No token found, skipping WebSocket connection');
|
|
1516
|
+
// Still try to load notifications from API (might work if GET is public)
|
|
1517
|
+
this.loadNotifications();
|
|
1518
|
+
return;
|
|
1519
|
+
}
|
|
1520
|
+
if (!this.wsNotificationService) {
|
|
1521
|
+
console.error('[Notifications] WebSocket service not available');
|
|
1522
|
+
return;
|
|
1523
|
+
}
|
|
1524
|
+
console.log('[Notifications] Initializing with user:', user._id);
|
|
1525
|
+
// Connect WebSocket
|
|
1526
|
+
this.wsNotificationService.connect(token, String(user._id));
|
|
1527
|
+
// Subscribe to real-time notifications
|
|
1528
|
+
this.wsNotificationService.notification$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
|
|
1529
|
+
next: (notification) => {
|
|
1530
|
+
console.log('[Notifications] New notification received:', notification);
|
|
1531
|
+
this.loadNotifications();
|
|
1532
|
+
},
|
|
1533
|
+
error: (error) => {
|
|
1534
|
+
console.error('[Notifications] Error in notification stream:', error);
|
|
1535
|
+
}
|
|
1536
|
+
});
|
|
1537
|
+
// Subscribe to connection status
|
|
1538
|
+
this.wsNotificationService.connectionStatus$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
|
|
1539
|
+
next: (status) => {
|
|
1540
|
+
console.log('[Notifications] Connection status:', status);
|
|
1541
|
+
},
|
|
1542
|
+
error: (error) => {
|
|
1543
|
+
console.error('[Notifications] Error in connection status:', error);
|
|
1544
|
+
}
|
|
1545
|
+
});
|
|
1546
|
+
// Load initial notifications from API
|
|
1547
|
+
this.loadNotifications();
|
|
1548
|
+
}
|
|
1549
|
+
catch (error) {
|
|
1550
|
+
console.error('[Notifications] Error initializing notifications:', error);
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
/**
|
|
1554
|
+
* Load notifications from API
|
|
1555
|
+
*/
|
|
1556
|
+
loadNotifications() {
|
|
1557
|
+
try {
|
|
1558
|
+
// Get notifications from WebSocket service (real-time)
|
|
1559
|
+
const wsNotifications = this.wsNotificationService?.allNotifications() || [];
|
|
1560
|
+
console.log('[Notifications] WebSocket notifications:', wsNotifications.length);
|
|
1561
|
+
// Load from API to get all notifications (including read status)
|
|
1562
|
+
this.notificationApiService.getNotifications({
|
|
1563
|
+
pageSize: 20
|
|
1564
|
+
}).subscribe({
|
|
1565
|
+
next: (response) => {
|
|
1566
|
+
console.log('[Notifications] API response:', response);
|
|
1567
|
+
if (response && response.success && response.data) {
|
|
1568
|
+
// Convert server notifications to notification payloads
|
|
1569
|
+
const apiPayloads = response.data.map((notif) => ({
|
|
1570
|
+
id: String(notif._id),
|
|
1571
|
+
type: notif.not_type || 'info',
|
|
1572
|
+
category: notif.not_category,
|
|
1573
|
+
title: notif.not_title,
|
|
1574
|
+
message: notif.not_message,
|
|
1575
|
+
data: notif.not_data,
|
|
1576
|
+
action_url: notif.not_action_url,
|
|
1577
|
+
action_label: notif.not_action_label,
|
|
1578
|
+
priority: notif.not_priority || 'normal',
|
|
1579
|
+
created_at: new Date(notif.not_created_at),
|
|
1580
|
+
timestamp: new Date(notif.not_created_at),
|
|
1581
|
+
// Store read status for filtering
|
|
1582
|
+
isRead: notif.not_status === 'read' || notif.not_read_at !== undefined
|
|
1583
|
+
}));
|
|
1584
|
+
console.log('[Notifications] Converted API payloads:', apiPayloads.length);
|
|
1585
|
+
// Merge WebSocket and API notifications (API takes priority for read status)
|
|
1586
|
+
const mergedNotifications = [];
|
|
1587
|
+
// Add API notifications first (they have read status)
|
|
1588
|
+
apiPayloads.forEach(apiNotif => {
|
|
1589
|
+
mergedNotifications.push(apiNotif);
|
|
1590
|
+
});
|
|
1591
|
+
// Add WebSocket notifications that aren't in API (new real-time notifications)
|
|
1592
|
+
wsNotifications.forEach(wsNotif => {
|
|
1593
|
+
if (!mergedNotifications.find(n => n.id === wsNotif.id)) {
|
|
1594
|
+
mergedNotifications.push({ ...wsNotif, isRead: false });
|
|
1595
|
+
}
|
|
1596
|
+
});
|
|
1597
|
+
// Sort by timestamp (newest first)
|
|
1598
|
+
mergedNotifications.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
1599
|
+
console.log('[Notifications] Total merged notifications:', mergedNotifications.length);
|
|
1600
|
+
// Update WebSocket service with read status
|
|
1601
|
+
if (this.wsNotificationService) {
|
|
1602
|
+
// Update unread count based on read status
|
|
1603
|
+
const unread = mergedNotifications.filter(n => !n.isRead);
|
|
1604
|
+
// Note: WebSocket service manages its own unread count, but we sync here
|
|
1605
|
+
}
|
|
1606
|
+
this.notifications.set(mergedNotifications);
|
|
1607
|
+
this.updateNotificationDropdown();
|
|
1608
|
+
}
|
|
1609
|
+
else {
|
|
1610
|
+
console.warn('[Notifications] API response invalid, using WebSocket notifications only');
|
|
1611
|
+
// Fallback to WebSocket notifications only
|
|
1612
|
+
this.notifications.set(wsNotifications);
|
|
1613
|
+
this.updateNotificationDropdown();
|
|
1614
|
+
}
|
|
1615
|
+
},
|
|
1616
|
+
error: (error) => {
|
|
1617
|
+
console.error('[Notifications] Error loading from API:', error);
|
|
1618
|
+
// Fallback to WebSocket notifications only
|
|
1619
|
+
this.notifications.set(wsNotifications);
|
|
1620
|
+
this.updateNotificationDropdown();
|
|
1621
|
+
}
|
|
1622
|
+
});
|
|
1623
|
+
}
|
|
1624
|
+
catch (error) {
|
|
1625
|
+
console.error('[Notifications] Error in loadNotifications:', error);
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
/**
|
|
1629
|
+
* Update notification dropdown items
|
|
1630
|
+
*/
|
|
1631
|
+
updateNotificationDropdown() {
|
|
1632
|
+
const notifs = this.notifications();
|
|
1633
|
+
const unreadCount = this.unreadCount();
|
|
1634
|
+
// Map notifications to dropdown items (show first 10)
|
|
1635
|
+
this.notificationItems = notifs.slice(0, 10).map(notif => ({
|
|
1636
|
+
id: notif.id,
|
|
1637
|
+
label: notif.title,
|
|
1638
|
+
icon: this.getNotificationIcon(notif.type),
|
|
1639
|
+
iconColor: this.getNotificationIconColor(notif.type),
|
|
1640
|
+
// Note: description is not supported by DropdownItem interface, but keeping for future use
|
|
1641
|
+
// description: notif.message,
|
|
1642
|
+
}));
|
|
1643
|
+
// Add action buttons if there are notifications
|
|
1644
|
+
if (notifs.length > 0) {
|
|
1645
|
+
// Add divider before actions
|
|
1646
|
+
this.notificationItems.push({
|
|
1647
|
+
id: 'divider-1',
|
|
1648
|
+
label: '',
|
|
1649
|
+
divider: true
|
|
1650
|
+
});
|
|
1651
|
+
// Add "Mark All as Read" if there are unread notifications
|
|
1652
|
+
if (unreadCount > 0) {
|
|
1653
|
+
this.notificationItems.push({
|
|
1654
|
+
id: 'mark-all-read',
|
|
1655
|
+
label: 'Mark All as Read',
|
|
1656
|
+
icon: 'done_all',
|
|
1657
|
+
iconColor: 'tw-text-blue-500'
|
|
1658
|
+
});
|
|
1659
|
+
}
|
|
1660
|
+
// Add "Clear All" option
|
|
1661
|
+
this.notificationItems.push({
|
|
1662
|
+
id: 'clear-all',
|
|
1663
|
+
label: 'Clear All',
|
|
1664
|
+
icon: 'clear_all',
|
|
1665
|
+
iconColor: 'tw-text-red-500',
|
|
1666
|
+
textColor: 'tw-text-red-600',
|
|
1667
|
+
hoverBgColor: 'hover:tw-bg-red-50'
|
|
1668
|
+
});
|
|
1669
|
+
// Add divider before "View All"
|
|
1670
|
+
this.notificationItems.push({
|
|
1671
|
+
id: 'divider-2',
|
|
1672
|
+
label: '',
|
|
1673
|
+
divider: true
|
|
1674
|
+
});
|
|
1675
|
+
// Add "View All" option
|
|
1676
|
+
this.notificationItems.push({
|
|
1677
|
+
id: 'view-all',
|
|
1678
|
+
label: 'View All Notifications',
|
|
1679
|
+
icon: 'list',
|
|
1680
|
+
iconColor: 'tw-text-blue-500'
|
|
1681
|
+
});
|
|
1682
|
+
}
|
|
1683
|
+
else {
|
|
1684
|
+
this.notificationItems = [{
|
|
1685
|
+
id: 'no-notifications',
|
|
1686
|
+
label: 'No notifications',
|
|
1687
|
+
icon: 'notifications_off',
|
|
1688
|
+
iconColor: 'tw-text-gray-400',
|
|
1689
|
+
disabled: true
|
|
1690
|
+
}];
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
/**
|
|
1694
|
+
* Get icon for notification type
|
|
1695
|
+
*/
|
|
1696
|
+
getNotificationIcon(type) {
|
|
1697
|
+
const iconMap = {
|
|
1698
|
+
'info': 'info',
|
|
1699
|
+
'success': 'check_circle',
|
|
1700
|
+
'warning': 'warning',
|
|
1701
|
+
'error': 'error',
|
|
1702
|
+
'system': 'settings'
|
|
1703
|
+
};
|
|
1704
|
+
return iconMap[type] || 'notifications';
|
|
1705
|
+
}
|
|
1706
|
+
/**
|
|
1707
|
+
* Get icon color for notification type
|
|
1708
|
+
*/
|
|
1709
|
+
getNotificationIconColor(type) {
|
|
1710
|
+
const colorMap = {
|
|
1711
|
+
'info': 'tw-text-blue-500',
|
|
1712
|
+
'success': 'tw-text-green-500',
|
|
1713
|
+
'warning': 'tw-text-yellow-500',
|
|
1714
|
+
'error': 'tw-text-red-500',
|
|
1715
|
+
'system': 'tw-text-gray-500'
|
|
1716
|
+
};
|
|
1717
|
+
return colorMap[type] || 'tw-text-gray-500';
|
|
1718
|
+
}
|
|
1719
|
+
/**
|
|
1720
|
+
* Handle notification dropdown item click
|
|
1721
|
+
*/
|
|
1722
|
+
onNotificationClick(item) {
|
|
1723
|
+
// Handle action buttons
|
|
1724
|
+
if (item.id === 'mark-all-read') {
|
|
1725
|
+
this.markAllAsRead();
|
|
1726
|
+
return;
|
|
1727
|
+
}
|
|
1728
|
+
if (item.id === 'clear-all') {
|
|
1729
|
+
this.clearAllNotifications();
|
|
1730
|
+
return;
|
|
1731
|
+
}
|
|
1732
|
+
if (item.id === 'view-all') {
|
|
1733
|
+
// Navigate to notifications page or open full panel
|
|
1734
|
+
console.log('View all notifications');
|
|
1735
|
+
// TODO: Navigate to full notifications page
|
|
1736
|
+
return;
|
|
1737
|
+
}
|
|
1738
|
+
if (item.id === 'no-notifications' || item.id === 'divider' || item.id === 'divider-1' || item.id === 'divider-2') {
|
|
1739
|
+
return;
|
|
1740
|
+
}
|
|
1741
|
+
// Mark notification as read when clicked
|
|
1742
|
+
this.markNotificationAsRead(String(item.id));
|
|
1743
|
+
// Navigate to action URL if available
|
|
1744
|
+
const notification = this.notifications().find(n => n.id === item.id);
|
|
1745
|
+
if (notification?.action_url) {
|
|
1746
|
+
this.router.navigate([notification.action_url]);
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
/**
|
|
1750
|
+
* Mark a single notification as read
|
|
1751
|
+
*/
|
|
1752
|
+
markNotificationAsRead(notificationId) {
|
|
1753
|
+
// Mark in WebSocket service
|
|
1754
|
+
if (this.wsNotificationService) {
|
|
1755
|
+
this.wsNotificationService.markAsRead(notificationId);
|
|
1756
|
+
}
|
|
1757
|
+
// Mark in API
|
|
1758
|
+
this.notificationApiService.markAsRead(notificationId).subscribe({
|
|
1759
|
+
next: () => {
|
|
1760
|
+
console.log('[Notifications] Marked as read:', notificationId);
|
|
1761
|
+
// Reload notifications to update unread count
|
|
1762
|
+
this.loadNotifications();
|
|
1763
|
+
},
|
|
1764
|
+
error: (error) => {
|
|
1765
|
+
console.error('[Notifications] Error marking notification as read:', error);
|
|
1766
|
+
}
|
|
1767
|
+
});
|
|
1768
|
+
}
|
|
1769
|
+
/**
|
|
1770
|
+
* Mark all notifications as read
|
|
1771
|
+
*/
|
|
1772
|
+
markAllAsRead() {
|
|
1773
|
+
this.notificationApiService.markAllAsRead().subscribe({
|
|
1774
|
+
next: () => {
|
|
1775
|
+
console.log('[Notifications] All notifications marked as read');
|
|
1776
|
+
// Reload notifications to update unread count
|
|
1777
|
+
this.loadNotifications();
|
|
1778
|
+
},
|
|
1779
|
+
error: (error) => {
|
|
1780
|
+
console.error('[Notifications] Error marking all as read:', error);
|
|
1781
|
+
}
|
|
1782
|
+
});
|
|
1783
|
+
}
|
|
1784
|
+
/**
|
|
1785
|
+
* Clear all notifications (mark all as read and remove from view)
|
|
1786
|
+
*/
|
|
1787
|
+
clearAllNotifications() {
|
|
1788
|
+
if (confirm('Are you sure you want to clear all notifications? This will mark them all as read.')) {
|
|
1789
|
+
// First mark all as read
|
|
1790
|
+
this.notificationApiService.markAllAsRead().subscribe({
|
|
1791
|
+
next: () => {
|
|
1792
|
+
console.log('[Notifications] All notifications cleared');
|
|
1793
|
+
// Clear local notifications array
|
|
1794
|
+
this.notifications.set([]);
|
|
1795
|
+
this.updateNotificationDropdown();
|
|
1796
|
+
// Reload to get updated state
|
|
1797
|
+
this.loadNotifications();
|
|
1798
|
+
},
|
|
1799
|
+
error: (error) => {
|
|
1800
|
+
console.error('[Notifications] Error clearing all notifications:', error);
|
|
1801
|
+
}
|
|
1802
|
+
});
|
|
1803
|
+
}
|
|
1481
1804
|
}
|
|
1482
1805
|
ngAfterViewInit() {
|
|
1483
1806
|
// No need to manually load file details - cideEleFileImage directive will handle it
|
|
@@ -1614,9 +1937,20 @@ class CideLytHeaderWrapperComponent {
|
|
|
1614
1937
|
else if (!label) {
|
|
1615
1938
|
label = 'Financial Year';
|
|
1616
1939
|
}
|
|
1940
|
+
// Add status indicators to label
|
|
1941
|
+
const statusIndicators = [];
|
|
1942
|
+
if (year.accyr_iscurrent) {
|
|
1943
|
+
statusIndicators.push('Current');
|
|
1944
|
+
}
|
|
1945
|
+
if (year.accyr_islocked) {
|
|
1946
|
+
statusIndicators.push('Locked');
|
|
1947
|
+
}
|
|
1948
|
+
const fullLabel = statusIndicators.length > 0
|
|
1949
|
+
? `${label} (${statusIndicators.join(', ')})`
|
|
1950
|
+
: label;
|
|
1617
1951
|
return {
|
|
1618
1952
|
id: year._id,
|
|
1619
|
-
label:
|
|
1953
|
+
label: fullLabel,
|
|
1620
1954
|
icon: 'calendar_today',
|
|
1621
1955
|
iconColor: 'tw-text-blue-500'
|
|
1622
1956
|
};
|
|
@@ -1664,9 +1998,20 @@ class CideLytHeaderWrapperComponent {
|
|
|
1664
1998
|
else if (!label) {
|
|
1665
1999
|
label = 'Academic Year';
|
|
1666
2000
|
}
|
|
2001
|
+
// Add status indicators to label
|
|
2002
|
+
const statusIndicators = [];
|
|
2003
|
+
if (year.acayr_iscurrent) {
|
|
2004
|
+
statusIndicators.push('Current');
|
|
2005
|
+
}
|
|
2006
|
+
if (year.acayr_islocked) {
|
|
2007
|
+
statusIndicators.push('Locked');
|
|
2008
|
+
}
|
|
2009
|
+
const fullLabel = statusIndicators.length > 0
|
|
2010
|
+
? `${label} (${statusIndicators.join(', ')})`
|
|
2011
|
+
: label;
|
|
1667
2012
|
return {
|
|
1668
2013
|
id: year._id,
|
|
1669
|
-
label:
|
|
2014
|
+
label: fullLabel,
|
|
1670
2015
|
icon: 'school',
|
|
1671
2016
|
iconColor: 'tw-text-green-500'
|
|
1672
2017
|
};
|
|
@@ -1841,12 +2186,12 @@ class CideLytHeaderWrapperComponent {
|
|
|
1841
2186
|
}
|
|
1842
2187
|
}
|
|
1843
2188
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytHeaderWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1844
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideLytHeaderWrapperComponent, isStandalone: true, selector: "cide-lyt-header-wrapper", viewQueries: [{ propertyName: "triggerTemplate", first: true, predicate: ["triggerTemplate"], descendants: true }, { propertyName: "financialYearTriggerTemplate", first: true, predicate: ["financialYearTriggerTemplate"], descendants: true }, { propertyName: "academicYearTriggerTemplate", first: true, predicate: ["academicYearTriggerTemplate"], descendants: true }], ngImport: i0, template: "<header id=\"cide-lyt-header-wrapper\" class=\"cide-lyt-header tw-w-full tw-select-none cide-lyt-header-wrapper-hide\">\n <!-- Logo Section -->\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"header-logo-container tw-flex tw-items-center tw-gap-3 tw-cursor-pointer\" (click)=\"onLogoClick()\"\n (keydown.enter)=\"onLogoClick()\" (keydown.space)=\"onLogoClick()\" tabindex=\"0\" role=\"button\"\n aria-label=\"Navigate to home\" title=\"Click to go to control panel home\">\n @if (appStateService.activeEntity()?.syen_photo_id_cyfm) {\n <img cideEleFileImage [fileId]=\"(appStateService.activeEntity()?.syen_photo_id_cyfm || '')\"\n [altText]=\"'Entity Logo'\" class=\"tw-w-8 tw-h-8 tw-object-contain\">\n } @else {\n <cide-ele-icon name=\"business\" class=\"tw-w-8 tw-h-8 tw-text-blue-600\"></cide-ele-icon>\n }\n\n </div>\n @if (appStateService.activeEntity()?.syen_name) {\n <span\n class=\"tw-text-md tw-font-semibold tw-text-blue-600 hover:tw-text-blue-800 tw-cursor-pointer sm:block tw-transition-colors tw-duration-200 hover:tw-underline\"\n (click)=\"onEntityNameClick()\" title=\"Click to switch entity\">\n {{ appStateService.activeEntity()?.syen_name }}\n </span>\n }\n </div>\n <!-- Search Section -->\n <div class=\"header-search-container\">\n <cide-ele-input id=\"cide_lyt_header_search\" placeholder=\"Search...\" leadingIcon=\"search\"\n size=\"md\"></cide-ele-input>\n </div>\n\n <!-- Icons Section -->\n <div class=\"header-icons-container\">\n <!-- Financial Year Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"financialYearItems\" [config]=\"financialYearConfig\"\n [triggerTemplate]=\"financialYearTriggerTemplate\"\n (itemClick)=\"onFinancialYearClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Financial Year</div>\n </div>\n \n <ng-template #financialYearTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-year-pill\">\n <cide-ele-icon size=\"2xs\" type=\"none\" class=\"tw-mr-1\">calendar_today</cide-ele-icon>\n <span class=\"header-year-pill-text\">{{ currentFinancialYearName() }}</span>\n </div>\n </ng-template>\n\n <!-- Academic Year Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"academicYearItems\" [config]=\"academicYearConfig\"\n [triggerTemplate]=\"academicYearTriggerTemplate\"\n (itemClick)=\"onAcademicYearClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Academic Year</div>\n </div>\n \n <ng-template #academicYearTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-year-pill\">\n <cide-ele-icon size=\"2xs\" type=\"none\" class=\"tw-mr-1\">school</cide-ele-icon>\n <span class=\"header-year-pill-text\">{{ currentAcademicYearName() }}</span>\n </div>\n </ng-template>\n\n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>notifications</cide-ele-icon>\n <div class=\"header-badge\">3</div>\n <div class=\"header-tooltip\">Notifications</div>\n </div>\n\n <div class=\"header-divider\"></div>\n\n <!-- Profile with Dropdown -->\n <div class=\"header-icon user-profile\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"profileItems\" [config]=\"profileConfig\"\n [triggerTemplate]=\"triggerTemplate\"\n (itemClick)=\"onProfileClick($event)\">\n <ng-template #triggerTemplate>\n @if (appStateService.currentUser()?.user_photo_id_cyfm) {\n <div class=\"profile-avatar\">\n <img cideEleFileImage [fileId]=\"(appStateService.currentUser()?.user_photo_id_cyfm || '')\"\n [altText]=\"'User Profile Photo'\" class=\"tw-w-full tw-h-full tw-object-cover tw-rounded-full\">\n </div>\n } @else {\n <div class=\"profile-avatar\">\n <cide-ele-icon name=\"person\" class=\"tw-w-6 tw-h-6 tw-text-white\"></cide-ele-icon>\n </div>\n }\n </ng-template>\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">My Account</div>\n </div>\n </div>\n</header>", styles: [".cide-lyt-header{display:flex;align-items:center;justify-content:space-between;background:linear-gradient(to right,#fffffff2,#f9fafbf2);box-shadow:0 2px 8px #00000008;padding:0 1rem;position:relative;z-index:20;transition:all .3s cubic-bezier(.4,0,.2,1);will-change:transform;border-bottom:1px solid rgba(229,231,235,.8);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.header-logo-container{height:100%;display:flex;align-items:center;padding:.5rem 0;position:relative;transition:all .3s cubic-bezier(.4,0,.2,1);border-radius:8px;outline:none}.header-logo-container img{height:30px;max-height:100%;transition:all .3s ease;border-radius:5px;overflow:hidden;box-shadow:0 1px 4px #0000000d}.header-logo-container:hover img{transform:scale(1.03);filter:brightness(1.05);box-shadow:0 2px 6px #00000014}.header-logo-container:after{content:\"\";position:absolute;top:-50%;left:-50%;width:200%;height:200%;background:linear-gradient(to bottom right,#fff0,#ffffff4d,#fff0);transform:rotate(30deg);opacity:0;transition:transform .6s ease,opacity .6s ease;pointer-events:none}.header-logo-container:hover:after,.header-logo-container:focus:after{opacity:1;transform:rotate(30deg) translate(50%,50%)}.header-search-container{flex-grow:1;max-width:600px;margin:0 2rem;position:relative;transition:all .3s ease}::ng-deep .header-search-container #cide_lyt_header_search{width:100%;background-color:#f9fafbcc;border-radius:20px!important;transition:all .3s ease;overflow:visible;transform:translateZ(0)}::ng-deep .header-search-container #cide_lyt_header_search:hover{box-shadow:0 3px 12px #00000014;background-color:#fff;transform:translateY(-1px)}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-input{background-color:transparent;font-size:.85rem!important;letter-spacing:.01em}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-leading-icon{color:#6b7280b3!important;font-size:1.1rem!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within{transform:translateY(-1px) scale(1.01)}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-input{border-color:#3b82f6!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-leading-icon{color:#3b82f6!important}.header-icons-container{display:flex;align-items:center;gap:1rem}.header-icon{position:relative;width:32px;height:32px;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-dropdown-container{position:relative;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-icon:before{content:\"\";position:absolute;inset:0;background-color:#3b82f61a;border-radius:.5rem;opacity:0;transform:scale(.8);transition:all .2s cubic-bezier(.4,0,.2,1)}.header-icon:hover:before{opacity:1;transform:scale(1)}.header-icon:hover{color:#3b82f6}.header-icon:active{transform:scale(.95)}.header-tooltip{position:absolute;bottom:-26px;left:50%;transform:translate(-50%);background-color:#374151e6;color:#fff;padding:.25rem .6rem;border-radius:.25rem;font-size:.7rem;white-space:nowrap;opacity:0;pointer-events:none;transition:all .2s cubic-bezier(.4,0,.2,1);z-index:1000;box-shadow:0 2px 5px #0003;letter-spacing:.01em;will-change:transform,opacity}.header-tooltip:before{content:\"\";position:absolute;bottom:100%;left:50%;transform:translate(-50%);border-width:5px;border-style:solid;border-color:transparent transparent rgba(55,65,81,.9) transparent}.header-icon:hover .header-tooltip{opacity:1;transform:translate(-50%) translateY(0)}.header-badge{position:absolute;top:0;right:0;min-width:16px;height:16px;border-radius:8px;background-color:#ef4444;color:#fff;font-size:9px;display:flex;align-items:center;justify-content:center;padding:0 4px;box-shadow:0 1px 3px #ef44444d;font-weight:600;z-index:2;transition:all .2s ease}.header-icon:hover .header-badge{transform:scale(1.1)}.header-divider{height:20px;width:1px;background-color:#e5e7ebcc;margin:0 6px}.header-year-dropdown-wrapper{position:relative;display:flex;align-items:center;justify-content:center}.header-year-pill{position:relative;display:flex;align-items:center;padding:.25rem .625rem;background:linear-gradient(135deg,#3b82f61a,#2563eb26);border:1px solid rgba(59,130,246,.3);border-radius:9999px;color:#2563eb;font-size:.6875rem;font-weight:600;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;white-space:nowrap;box-shadow:0 1px 2px #3b82f61a;min-height:22px;height:22px;line-height:1}.header-year-pill:hover{background:linear-gradient(135deg,#3b82f626,#2563eb33);border-color:#3b82f666;transform:translateY(-1px);box-shadow:0 2px 6px #3b82f626}.header-year-pill-text{max-width:180px;overflow:hidden;text-overflow:ellipsis;letter-spacing:-.01em;line-height:1;display:inline-block}::ng-deep .header-dropdown-container .dropdown-trigger{background:transparent!important;border:none!important;border-radius:0!important;padding:0!important;width:100%!important;height:100%!important;min-width:auto!important;box-shadow:none!important;display:flex!important;align-items:center!important;justify-content:center!important;transition:none!important;cursor:pointer!important}::ng-deep .header-dropdown-container .dropdown-trigger:hover{background:transparent!important}::ng-deep .header-dropdown-container .dropdown-trigger:hover .header-year-pill{background:linear-gradient(135deg,#3b82f626,#2563eb33)!important;border-color:#3b82f666!important;transform:translateY(-1px)!important;box-shadow:0 2px 6px #3b82f626!important}::ng-deep .header-dropdown-container .dropdown-trigger:focus,::ng-deep .header-dropdown-container .dropdown-trigger:focus-visible,::ng-deep .header-dropdown-container .dropdown-trigger:active{outline:none!important;box-shadow:0 2px 6px #3b82f626!important}.profile-avatar{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px #2563eb33;transition:all .2s cubic-bezier(.4,0,.2,1);letter-spacing:-.5px;cursor:pointer;border:2px solid transparent}.profile-avatar:hover,.header-icon:hover .profile-avatar{transform:scale(1.08);box-shadow:0 3px 8px #2563eb4d;border-color:#3b82f64d}::ng-deep .user-profile .dropdown-trigger{background:transparent!important;border:none!important;padding:0!important;width:auto!important;height:auto!important;border-radius:0!important}::ng-deep .user-profile .dropdown-trigger:hover{background:transparent!important}::ng-deep .user-profile .dropdown-trigger:focus,::ng-deep .user-profile .dropdown-trigger:focus-visible,::ng-deep .user-profile .dropdown-trigger:active{outline:none!important;box-shadow:none!important}.header-avatar{width:36px;height:36px;border-radius:50%;overflow:hidden;transition:all .2s cubic-bezier(.4,0,.2,1);border:2px solid transparent;box-shadow:0 2px 4px #0000001a}.header-avatar:hover{border-color:#3b82f6;transform:scale(1.05);box-shadow:0 3px 6px #3b82f64d}@media (max-width: 768px){.header-search-container{margin:0 1rem}.header-icons-container{gap:.5rem}}@media (max-width: 640px){.header-search-container{max-width:200px;margin:0 .5rem}}\n"], dependencies: [{ kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }, { kind: "directive", type: CideEleFileImageDirective, selector: "[cideEleFileImage]", inputs: ["fileId", "altText"] }] });
|
|
2189
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideLytHeaderWrapperComponent, isStandalone: true, selector: "cide-lyt-header-wrapper", viewQueries: [{ propertyName: "triggerTemplate", first: true, predicate: ["triggerTemplate"], descendants: true }, { propertyName: "financialYearTriggerTemplate", first: true, predicate: ["financialYearTriggerTemplate"], descendants: true }, { propertyName: "academicYearTriggerTemplate", first: true, predicate: ["academicYearTriggerTemplate"], descendants: true }, { propertyName: "notificationTriggerTemplate", first: true, predicate: ["notificationTriggerTemplate"], descendants: true }], ngImport: i0, template: "<header id=\"cide-lyt-header-wrapper\" class=\"cide-lyt-header tw-w-full tw-select-none cide-lyt-header-wrapper-hide\">\n <!-- Logo Section -->\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"header-logo-container tw-flex tw-items-center tw-gap-3 tw-cursor-pointer\" (click)=\"onLogoClick()\"\n (keydown.enter)=\"onLogoClick()\" (keydown.space)=\"onLogoClick()\" tabindex=\"0\" role=\"button\"\n aria-label=\"Navigate to home\" title=\"Click to go to control panel home\">\n @if (appStateService.activeEntity()?.syen_photo_id_cyfm) {\n <img cideEleFileImage [fileId]=\"(appStateService.activeEntity()?.syen_photo_id_cyfm || '')\"\n [altText]=\"'Entity Logo'\" class=\"tw-w-8 tw-h-8 tw-object-contain\">\n } @else {\n <cide-ele-icon name=\"business\" class=\"tw-w-8 tw-h-8 tw-text-blue-600\"></cide-ele-icon>\n }\n\n </div>\n @if (appStateService.activeEntity()?.syen_name) {\n <span\n class=\"tw-text-md tw-font-semibold tw-text-blue-600 hover:tw-text-blue-800 tw-cursor-pointer sm:block tw-transition-colors tw-duration-200 hover:tw-underline\"\n (click)=\"onEntityNameClick()\" title=\"Click to switch entity\">\n {{ appStateService.activeEntity()?.syen_name }}\n </span>\n }\n </div>\n <!-- Search Section -->\n <div class=\"header-search-container\">\n <cide-ele-input id=\"cide_lyt_header_search\" placeholder=\"Search...\" leadingIcon=\"search\"\n size=\"md\"></cide-ele-input>\n </div>\n\n <!-- Icons Section -->\n <div class=\"header-icons-container\">\n <!-- Financial Year Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"financialYearItems\" [config]=\"financialYearConfig\"\n [triggerTemplate]=\"financialYearTriggerTemplate\"\n (itemClick)=\"onFinancialYearClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Financial Year</div>\n </div>\n \n <ng-template #financialYearTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-year-pill\">\n <cide-ele-icon size=\"2xs\" type=\"none\" class=\"tw-mr-1\">calendar_today</cide-ele-icon>\n <span class=\"header-year-pill-text\">{{ currentFinancialYearName() }}</span>\n </div>\n </ng-template>\n\n <!-- Academic Year Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"academicYearItems\" [config]=\"academicYearConfig\"\n [triggerTemplate]=\"academicYearTriggerTemplate\"\n (itemClick)=\"onAcademicYearClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Academic Year</div>\n </div>\n \n <ng-template #academicYearTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-year-pill\">\n <cide-ele-icon size=\"2xs\" type=\"none\" class=\"tw-mr-1\">school</cide-ele-icon>\n <span class=\"header-year-pill-text\">{{ currentAcademicYearName() }}</span>\n </div>\n </ng-template>\n\n <!-- Notifications Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown \n [items]=\"notificationItems\" \n [config]=\"notificationConfig\"\n [triggerTemplate]=\"notificationTriggerTemplate\"\n (itemClick)=\"onNotificationClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Notifications</div>\n </div>\n \n <ng-template #notificationTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-icon notification-icon\" [class.active]=\"isOpen\">\n <cide-ele-icon>notifications</cide-ele-icon>\n @if (unreadCount() > 0) {\n <div class=\"header-badge\">{{ unreadCount() > 99 ? '99+' : unreadCount() }}</div>\n }\n </div>\n </ng-template>\n\n <div class=\"header-divider\"></div>\n\n <!-- Profile with Dropdown -->\n <div class=\"header-icon user-profile\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"profileItems\" [config]=\"profileConfig\"\n [triggerTemplate]=\"triggerTemplate\"\n (itemClick)=\"onProfileClick($event)\">\n <ng-template #triggerTemplate>\n @if (appStateService.currentUser()?.user_photo_id_cyfm) {\n <div class=\"profile-avatar\">\n <img cideEleFileImage [fileId]=\"(appStateService.currentUser()?.user_photo_id_cyfm || '')\"\n [altText]=\"'User Profile Photo'\" class=\"tw-w-full tw-h-full tw-object-cover tw-rounded-full\">\n </div>\n } @else {\n <div class=\"profile-avatar\">\n <cide-ele-icon name=\"person\" class=\"tw-w-6 tw-h-6 tw-text-white\"></cide-ele-icon>\n </div>\n }\n </ng-template>\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">My Account</div>\n </div>\n </div>\n</header>", styles: [".cide-lyt-header{display:flex;align-items:center;justify-content:space-between;background:linear-gradient(to right,#fffffff2,#f9fafbf2);box-shadow:0 2px 8px #00000008;padding:0 1rem;position:relative;z-index:20;transition:all .3s cubic-bezier(.4,0,.2,1);will-change:transform;border-bottom:1px solid rgba(229,231,235,.8);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.header-logo-container{height:100%;display:flex;align-items:center;padding:.5rem 0;position:relative;transition:all .3s cubic-bezier(.4,0,.2,1);border-radius:8px;outline:none}.header-logo-container img{height:30px;max-height:100%;transition:all .3s ease;border-radius:5px;overflow:hidden;box-shadow:0 1px 4px #0000000d}.header-logo-container:hover img{transform:scale(1.03);filter:brightness(1.05);box-shadow:0 2px 6px #00000014}.header-logo-container:after{content:\"\";position:absolute;top:-50%;left:-50%;width:200%;height:200%;background:linear-gradient(to bottom right,#fff0,#ffffff4d,#fff0);transform:rotate(30deg);opacity:0;transition:transform .6s ease,opacity .6s ease;pointer-events:none}.header-logo-container:hover:after,.header-logo-container:focus:after{opacity:1;transform:rotate(30deg) translate(50%,50%)}.header-search-container{flex-grow:1;max-width:600px;margin:0 2rem;position:relative;transition:all .3s ease}::ng-deep .header-search-container #cide_lyt_header_search{width:100%;background-color:#f9fafbcc;border-radius:20px!important;transition:all .3s ease;overflow:visible;transform:translateZ(0)}::ng-deep .header-search-container #cide_lyt_header_search:hover{box-shadow:0 3px 12px #00000014;background-color:#fff;transform:translateY(-1px)}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-input{background-color:transparent;font-size:.85rem!important;letter-spacing:.01em}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-leading-icon{color:#6b7280b3!important;font-size:1.1rem!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within{transform:translateY(-1px) scale(1.01)}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-input{border-color:#3b82f6!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-leading-icon{color:#3b82f6!important}.header-icons-container{display:flex;align-items:center;gap:1rem}.header-icon{position:relative;width:32px;height:32px;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-dropdown-container{position:relative;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-icon:before{content:\"\";position:absolute;inset:0;background-color:#3b82f61a;border-radius:.5rem;opacity:0;transform:scale(.8);transition:all .2s cubic-bezier(.4,0,.2,1)}.header-icon:hover:before{opacity:1;transform:scale(1)}.header-icon:hover{color:#3b82f6}.header-icon:active{transform:scale(.95)}.header-tooltip{position:absolute;bottom:-26px;left:50%;transform:translate(-50%);background-color:#374151e6;color:#fff;padding:.25rem .6rem;border-radius:.25rem;font-size:.7rem;white-space:nowrap;opacity:0;pointer-events:none;transition:all .2s cubic-bezier(.4,0,.2,1);z-index:1000;box-shadow:0 2px 5px #0003;letter-spacing:.01em;will-change:transform,opacity}.header-tooltip:before{content:\"\";position:absolute;bottom:100%;left:50%;transform:translate(-50%);border-width:5px;border-style:solid;border-color:transparent transparent rgba(55,65,81,.9) transparent}.header-icon:hover .header-tooltip{opacity:1;transform:translate(-50%) translateY(0)}.header-badge{position:absolute;top:0;right:0;min-width:16px;height:16px;border-radius:8px;background-color:#ef4444;color:#fff;font-size:9px;display:flex;align-items:center;justify-content:center;padding:0 4px;box-shadow:0 1px 3px #ef44444d;font-weight:600;z-index:2;transition:all .2s ease}.header-icon:hover .header-badge{transform:scale(1.1)}.header-divider{height:20px;width:1px;background-color:#e5e7ebcc;margin:0 6px}.header-year-dropdown-wrapper{position:relative;display:flex;align-items:center;justify-content:center}.header-year-pill{position:relative;display:flex;align-items:center;padding:.25rem .625rem;background:linear-gradient(135deg,#3b82f61a,#2563eb26);border:1px solid rgba(59,130,246,.3);border-radius:9999px;color:#2563eb;font-size:.6875rem;font-weight:600;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;white-space:nowrap;box-shadow:0 1px 2px #3b82f61a;min-height:22px;height:22px;line-height:1}.header-year-pill:hover{background:linear-gradient(135deg,#3b82f626,#2563eb33);border-color:#3b82f666;transform:translateY(-1px);box-shadow:0 2px 6px #3b82f626}.header-year-pill-text{max-width:180px;overflow:hidden;text-overflow:ellipsis;letter-spacing:-.01em;line-height:1;display:inline-block}::ng-deep .header-dropdown-container .dropdown-trigger{background:transparent!important;border:none!important;border-radius:0!important;padding:0!important;width:100%!important;height:100%!important;min-width:auto!important;box-shadow:none!important;display:flex!important;align-items:center!important;justify-content:center!important;transition:none!important;cursor:pointer!important}::ng-deep .header-dropdown-container .dropdown-trigger:hover{background:transparent!important}::ng-deep .header-dropdown-container .dropdown-trigger:hover .header-year-pill{background:linear-gradient(135deg,#3b82f626,#2563eb33)!important;border-color:#3b82f666!important;transform:translateY(-1px)!important;box-shadow:0 2px 6px #3b82f626!important}::ng-deep .header-dropdown-container .dropdown-trigger:focus,::ng-deep .header-dropdown-container .dropdown-trigger:focus-visible,::ng-deep .header-dropdown-container .dropdown-trigger:active{outline:none!important;box-shadow:0 2px 6px #3b82f626!important}.profile-avatar{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px #2563eb33;transition:all .2s cubic-bezier(.4,0,.2,1);letter-spacing:-.5px;cursor:pointer;border:2px solid transparent}.profile-avatar:hover,.header-icon:hover .profile-avatar{transform:scale(1.08);box-shadow:0 3px 8px #2563eb4d;border-color:#3b82f64d}::ng-deep .user-profile .dropdown-trigger{background:transparent!important;border:none!important;padding:0!important;width:auto!important;height:auto!important;border-radius:0!important}::ng-deep .user-profile .dropdown-trigger:hover{background:transparent!important}::ng-deep .user-profile .dropdown-trigger:focus,::ng-deep .user-profile .dropdown-trigger:focus-visible,::ng-deep .user-profile .dropdown-trigger:active{outline:none!important;box-shadow:none!important}.header-avatar{width:36px;height:36px;border-radius:50%;overflow:hidden;transition:all .2s cubic-bezier(.4,0,.2,1);border:2px solid transparent;box-shadow:0 2px 4px #0000001a}.header-avatar:hover{border-color:#3b82f6;transform:scale(1.05);box-shadow:0 3px 6px #3b82f64d}@media (max-width: 768px){.header-search-container{margin:0 1rem}.header-icons-container{gap:.5rem}}@media (max-width: 640px){.header-search-container{max-width:200px;margin:0 .5rem}}\n"], dependencies: [{ kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }, { kind: "directive", type: CideEleFileImageDirective, selector: "[cideEleFileImage]", inputs: ["fileId", "altText"] }] });
|
|
1845
2190
|
}
|
|
1846
2191
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytHeaderWrapperComponent, decorators: [{
|
|
1847
2192
|
type: Component,
|
|
1848
2193
|
args: [{ selector: 'cide-lyt-header-wrapper', imports: [CideInputComponent, CommonModule, CideIconComponent,
|
|
1849
|
-
CideEleDropdownComponent, CideEleFileImageDirective], template: "<header id=\"cide-lyt-header-wrapper\" class=\"cide-lyt-header tw-w-full tw-select-none cide-lyt-header-wrapper-hide\">\n <!-- Logo Section -->\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"header-logo-container tw-flex tw-items-center tw-gap-3 tw-cursor-pointer\" (click)=\"onLogoClick()\"\n (keydown.enter)=\"onLogoClick()\" (keydown.space)=\"onLogoClick()\" tabindex=\"0\" role=\"button\"\n aria-label=\"Navigate to home\" title=\"Click to go to control panel home\">\n @if (appStateService.activeEntity()?.syen_photo_id_cyfm) {\n <img cideEleFileImage [fileId]=\"(appStateService.activeEntity()?.syen_photo_id_cyfm || '')\"\n [altText]=\"'Entity Logo'\" class=\"tw-w-8 tw-h-8 tw-object-contain\">\n } @else {\n <cide-ele-icon name=\"business\" class=\"tw-w-8 tw-h-8 tw-text-blue-600\"></cide-ele-icon>\n }\n\n </div>\n @if (appStateService.activeEntity()?.syen_name) {\n <span\n class=\"tw-text-md tw-font-semibold tw-text-blue-600 hover:tw-text-blue-800 tw-cursor-pointer sm:block tw-transition-colors tw-duration-200 hover:tw-underline\"\n (click)=\"onEntityNameClick()\" title=\"Click to switch entity\">\n {{ appStateService.activeEntity()?.syen_name }}\n </span>\n }\n </div>\n <!-- Search Section -->\n <div class=\"header-search-container\">\n <cide-ele-input id=\"cide_lyt_header_search\" placeholder=\"Search...\" leadingIcon=\"search\"\n size=\"md\"></cide-ele-input>\n </div>\n\n <!-- Icons Section -->\n <div class=\"header-icons-container\">\n <!-- Financial Year Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"financialYearItems\" [config]=\"financialYearConfig\"\n [triggerTemplate]=\"financialYearTriggerTemplate\"\n (itemClick)=\"onFinancialYearClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Financial Year</div>\n </div>\n \n <ng-template #financialYearTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-year-pill\">\n <cide-ele-icon size=\"2xs\" type=\"none\" class=\"tw-mr-1\">calendar_today</cide-ele-icon>\n <span class=\"header-year-pill-text\">{{ currentFinancialYearName() }}</span>\n </div>\n </ng-template>\n\n <!-- Academic Year Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"academicYearItems\" [config]=\"academicYearConfig\"\n [triggerTemplate]=\"academicYearTriggerTemplate\"\n (itemClick)=\"onAcademicYearClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Academic Year</div>\n </div>\n \n <ng-template #academicYearTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-year-pill\">\n <cide-ele-icon size=\"2xs\" type=\"none\" class=\"tw-mr-1\">school</cide-ele-icon>\n <span class=\"header-year-pill-text\">{{ currentAcademicYearName() }}</span>\n </div>\n </ng-template>\n\n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>notifications</cide-ele-icon>\n <div class=\"header-badge\">3</div>\n <div class=\"header-tooltip\">Notifications</div>\n </div>\n\n <div class=\"header-divider\"></div>\n\n <!-- Profile with Dropdown -->\n <div class=\"header-icon user-profile\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"profileItems\" [config]=\"profileConfig\"\n [triggerTemplate]=\"triggerTemplate\"\n (itemClick)=\"onProfileClick($event)\">\n <ng-template #triggerTemplate>\n @if (appStateService.currentUser()?.user_photo_id_cyfm) {\n <div class=\"profile-avatar\">\n <img cideEleFileImage [fileId]=\"(appStateService.currentUser()?.user_photo_id_cyfm || '')\"\n [altText]=\"'User Profile Photo'\" class=\"tw-w-full tw-h-full tw-object-cover tw-rounded-full\">\n </div>\n } @else {\n <div class=\"profile-avatar\">\n <cide-ele-icon name=\"person\" class=\"tw-w-6 tw-h-6 tw-text-white\"></cide-ele-icon>\n </div>\n }\n </ng-template>\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">My Account</div>\n </div>\n </div>\n</header>", styles: [".cide-lyt-header{display:flex;align-items:center;justify-content:space-between;background:linear-gradient(to right,#fffffff2,#f9fafbf2);box-shadow:0 2px 8px #00000008;padding:0 1rem;position:relative;z-index:20;transition:all .3s cubic-bezier(.4,0,.2,1);will-change:transform;border-bottom:1px solid rgba(229,231,235,.8);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.header-logo-container{height:100%;display:flex;align-items:center;padding:.5rem 0;position:relative;transition:all .3s cubic-bezier(.4,0,.2,1);border-radius:8px;outline:none}.header-logo-container img{height:30px;max-height:100%;transition:all .3s ease;border-radius:5px;overflow:hidden;box-shadow:0 1px 4px #0000000d}.header-logo-container:hover img{transform:scale(1.03);filter:brightness(1.05);box-shadow:0 2px 6px #00000014}.header-logo-container:after{content:\"\";position:absolute;top:-50%;left:-50%;width:200%;height:200%;background:linear-gradient(to bottom right,#fff0,#ffffff4d,#fff0);transform:rotate(30deg);opacity:0;transition:transform .6s ease,opacity .6s ease;pointer-events:none}.header-logo-container:hover:after,.header-logo-container:focus:after{opacity:1;transform:rotate(30deg) translate(50%,50%)}.header-search-container{flex-grow:1;max-width:600px;margin:0 2rem;position:relative;transition:all .3s ease}::ng-deep .header-search-container #cide_lyt_header_search{width:100%;background-color:#f9fafbcc;border-radius:20px!important;transition:all .3s ease;overflow:visible;transform:translateZ(0)}::ng-deep .header-search-container #cide_lyt_header_search:hover{box-shadow:0 3px 12px #00000014;background-color:#fff;transform:translateY(-1px)}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-input{background-color:transparent;font-size:.85rem!important;letter-spacing:.01em}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-leading-icon{color:#6b7280b3!important;font-size:1.1rem!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within{transform:translateY(-1px) scale(1.01)}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-input{border-color:#3b82f6!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-leading-icon{color:#3b82f6!important}.header-icons-container{display:flex;align-items:center;gap:1rem}.header-icon{position:relative;width:32px;height:32px;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-dropdown-container{position:relative;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-icon:before{content:\"\";position:absolute;inset:0;background-color:#3b82f61a;border-radius:.5rem;opacity:0;transform:scale(.8);transition:all .2s cubic-bezier(.4,0,.2,1)}.header-icon:hover:before{opacity:1;transform:scale(1)}.header-icon:hover{color:#3b82f6}.header-icon:active{transform:scale(.95)}.header-tooltip{position:absolute;bottom:-26px;left:50%;transform:translate(-50%);background-color:#374151e6;color:#fff;padding:.25rem .6rem;border-radius:.25rem;font-size:.7rem;white-space:nowrap;opacity:0;pointer-events:none;transition:all .2s cubic-bezier(.4,0,.2,1);z-index:1000;box-shadow:0 2px 5px #0003;letter-spacing:.01em;will-change:transform,opacity}.header-tooltip:before{content:\"\";position:absolute;bottom:100%;left:50%;transform:translate(-50%);border-width:5px;border-style:solid;border-color:transparent transparent rgba(55,65,81,.9) transparent}.header-icon:hover .header-tooltip{opacity:1;transform:translate(-50%) translateY(0)}.header-badge{position:absolute;top:0;right:0;min-width:16px;height:16px;border-radius:8px;background-color:#ef4444;color:#fff;font-size:9px;display:flex;align-items:center;justify-content:center;padding:0 4px;box-shadow:0 1px 3px #ef44444d;font-weight:600;z-index:2;transition:all .2s ease}.header-icon:hover .header-badge{transform:scale(1.1)}.header-divider{height:20px;width:1px;background-color:#e5e7ebcc;margin:0 6px}.header-year-dropdown-wrapper{position:relative;display:flex;align-items:center;justify-content:center}.header-year-pill{position:relative;display:flex;align-items:center;padding:.25rem .625rem;background:linear-gradient(135deg,#3b82f61a,#2563eb26);border:1px solid rgba(59,130,246,.3);border-radius:9999px;color:#2563eb;font-size:.6875rem;font-weight:600;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;white-space:nowrap;box-shadow:0 1px 2px #3b82f61a;min-height:22px;height:22px;line-height:1}.header-year-pill:hover{background:linear-gradient(135deg,#3b82f626,#2563eb33);border-color:#3b82f666;transform:translateY(-1px);box-shadow:0 2px 6px #3b82f626}.header-year-pill-text{max-width:180px;overflow:hidden;text-overflow:ellipsis;letter-spacing:-.01em;line-height:1;display:inline-block}::ng-deep .header-dropdown-container .dropdown-trigger{background:transparent!important;border:none!important;border-radius:0!important;padding:0!important;width:100%!important;height:100%!important;min-width:auto!important;box-shadow:none!important;display:flex!important;align-items:center!important;justify-content:center!important;transition:none!important;cursor:pointer!important}::ng-deep .header-dropdown-container .dropdown-trigger:hover{background:transparent!important}::ng-deep .header-dropdown-container .dropdown-trigger:hover .header-year-pill{background:linear-gradient(135deg,#3b82f626,#2563eb33)!important;border-color:#3b82f666!important;transform:translateY(-1px)!important;box-shadow:0 2px 6px #3b82f626!important}::ng-deep .header-dropdown-container .dropdown-trigger:focus,::ng-deep .header-dropdown-container .dropdown-trigger:focus-visible,::ng-deep .header-dropdown-container .dropdown-trigger:active{outline:none!important;box-shadow:0 2px 6px #3b82f626!important}.profile-avatar{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px #2563eb33;transition:all .2s cubic-bezier(.4,0,.2,1);letter-spacing:-.5px;cursor:pointer;border:2px solid transparent}.profile-avatar:hover,.header-icon:hover .profile-avatar{transform:scale(1.08);box-shadow:0 3px 8px #2563eb4d;border-color:#3b82f64d}::ng-deep .user-profile .dropdown-trigger{background:transparent!important;border:none!important;padding:0!important;width:auto!important;height:auto!important;border-radius:0!important}::ng-deep .user-profile .dropdown-trigger:hover{background:transparent!important}::ng-deep .user-profile .dropdown-trigger:focus,::ng-deep .user-profile .dropdown-trigger:focus-visible,::ng-deep .user-profile .dropdown-trigger:active{outline:none!important;box-shadow:none!important}.header-avatar{width:36px;height:36px;border-radius:50%;overflow:hidden;transition:all .2s cubic-bezier(.4,0,.2,1);border:2px solid transparent;box-shadow:0 2px 4px #0000001a}.header-avatar:hover{border-color:#3b82f6;transform:scale(1.05);box-shadow:0 3px 6px #3b82f64d}@media (max-width: 768px){.header-search-container{margin:0 1rem}.header-icons-container{gap:.5rem}}@media (max-width: 640px){.header-search-container{max-width:200px;margin:0 .5rem}}\n"] }]
|
|
2194
|
+
CideEleDropdownComponent, CideEleFileImageDirective], template: "<header id=\"cide-lyt-header-wrapper\" class=\"cide-lyt-header tw-w-full tw-select-none cide-lyt-header-wrapper-hide\">\n <!-- Logo Section -->\n <div class=\"tw-flex tw-items-center tw-gap-3\">\n <div class=\"header-logo-container tw-flex tw-items-center tw-gap-3 tw-cursor-pointer\" (click)=\"onLogoClick()\"\n (keydown.enter)=\"onLogoClick()\" (keydown.space)=\"onLogoClick()\" tabindex=\"0\" role=\"button\"\n aria-label=\"Navigate to home\" title=\"Click to go to control panel home\">\n @if (appStateService.activeEntity()?.syen_photo_id_cyfm) {\n <img cideEleFileImage [fileId]=\"(appStateService.activeEntity()?.syen_photo_id_cyfm || '')\"\n [altText]=\"'Entity Logo'\" class=\"tw-w-8 tw-h-8 tw-object-contain\">\n } @else {\n <cide-ele-icon name=\"business\" class=\"tw-w-8 tw-h-8 tw-text-blue-600\"></cide-ele-icon>\n }\n\n </div>\n @if (appStateService.activeEntity()?.syen_name) {\n <span\n class=\"tw-text-md tw-font-semibold tw-text-blue-600 hover:tw-text-blue-800 tw-cursor-pointer sm:block tw-transition-colors tw-duration-200 hover:tw-underline\"\n (click)=\"onEntityNameClick()\" title=\"Click to switch entity\">\n {{ appStateService.activeEntity()?.syen_name }}\n </span>\n }\n </div>\n <!-- Search Section -->\n <div class=\"header-search-container\">\n <cide-ele-input id=\"cide_lyt_header_search\" placeholder=\"Search...\" leadingIcon=\"search\"\n size=\"md\"></cide-ele-input>\n </div>\n\n <!-- Icons Section -->\n <div class=\"header-icons-container\">\n <!-- Financial Year Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"financialYearItems\" [config]=\"financialYearConfig\"\n [triggerTemplate]=\"financialYearTriggerTemplate\"\n (itemClick)=\"onFinancialYearClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Financial Year</div>\n </div>\n \n <ng-template #financialYearTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-year-pill\">\n <cide-ele-icon size=\"2xs\" type=\"none\" class=\"tw-mr-1\">calendar_today</cide-ele-icon>\n <span class=\"header-year-pill-text\">{{ currentFinancialYearName() }}</span>\n </div>\n </ng-template>\n\n <!-- Academic Year Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"academicYearItems\" [config]=\"academicYearConfig\"\n [triggerTemplate]=\"academicYearTriggerTemplate\"\n (itemClick)=\"onAcademicYearClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Academic Year</div>\n </div>\n \n <ng-template #academicYearTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-year-pill\">\n <cide-ele-icon size=\"2xs\" type=\"none\" class=\"tw-mr-1\">school</cide-ele-icon>\n <span class=\"header-year-pill-text\">{{ currentAcademicYearName() }}</span>\n </div>\n </ng-template>\n\n <!-- Notifications Dropdown -->\n <div class=\"header-dropdown-container\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown \n [items]=\"notificationItems\" \n [config]=\"notificationConfig\"\n [triggerTemplate]=\"notificationTriggerTemplate\"\n (itemClick)=\"onNotificationClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">Notifications</div>\n </div>\n \n <ng-template #notificationTriggerTemplate let-isOpen=\"isOpen\">\n <div class=\"header-icon notification-icon\" [class.active]=\"isOpen\">\n <cide-ele-icon>notifications</cide-ele-icon>\n @if (unreadCount() > 0) {\n <div class=\"header-badge\">{{ unreadCount() > 99 ? '99+' : unreadCount() }}</div>\n }\n </div>\n </ng-template>\n\n <div class=\"header-divider\"></div>\n\n <!-- Profile with Dropdown -->\n <div class=\"header-icon user-profile\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown [items]=\"profileItems\" [config]=\"profileConfig\"\n [triggerTemplate]=\"triggerTemplate\"\n (itemClick)=\"onProfileClick($event)\">\n <ng-template #triggerTemplate>\n @if (appStateService.currentUser()?.user_photo_id_cyfm) {\n <div class=\"profile-avatar\">\n <img cideEleFileImage [fileId]=\"(appStateService.currentUser()?.user_photo_id_cyfm || '')\"\n [altText]=\"'User Profile Photo'\" class=\"tw-w-full tw-h-full tw-object-cover tw-rounded-full\">\n </div>\n } @else {\n <div class=\"profile-avatar\">\n <cide-ele-icon name=\"person\" class=\"tw-w-6 tw-h-6 tw-text-white\"></cide-ele-icon>\n </div>\n }\n </ng-template>\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">My Account</div>\n </div>\n </div>\n</header>", styles: [".cide-lyt-header{display:flex;align-items:center;justify-content:space-between;background:linear-gradient(to right,#fffffff2,#f9fafbf2);box-shadow:0 2px 8px #00000008;padding:0 1rem;position:relative;z-index:20;transition:all .3s cubic-bezier(.4,0,.2,1);will-change:transform;border-bottom:1px solid rgba(229,231,235,.8);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.header-logo-container{height:100%;display:flex;align-items:center;padding:.5rem 0;position:relative;transition:all .3s cubic-bezier(.4,0,.2,1);border-radius:8px;outline:none}.header-logo-container img{height:30px;max-height:100%;transition:all .3s ease;border-radius:5px;overflow:hidden;box-shadow:0 1px 4px #0000000d}.header-logo-container:hover img{transform:scale(1.03);filter:brightness(1.05);box-shadow:0 2px 6px #00000014}.header-logo-container:after{content:\"\";position:absolute;top:-50%;left:-50%;width:200%;height:200%;background:linear-gradient(to bottom right,#fff0,#ffffff4d,#fff0);transform:rotate(30deg);opacity:0;transition:transform .6s ease,opacity .6s ease;pointer-events:none}.header-logo-container:hover:after,.header-logo-container:focus:after{opacity:1;transform:rotate(30deg) translate(50%,50%)}.header-search-container{flex-grow:1;max-width:600px;margin:0 2rem;position:relative;transition:all .3s ease}::ng-deep .header-search-container #cide_lyt_header_search{width:100%;background-color:#f9fafbcc;border-radius:20px!important;transition:all .3s ease;overflow:visible;transform:translateZ(0)}::ng-deep .header-search-container #cide_lyt_header_search:hover{box-shadow:0 3px 12px #00000014;background-color:#fff;transform:translateY(-1px)}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-input{background-color:transparent;font-size:.85rem!important;letter-spacing:.01em}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-leading-icon{color:#6b7280b3!important;font-size:1.1rem!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within{transform:translateY(-1px) scale(1.01)}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-input{border-color:#3b82f6!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-leading-icon{color:#3b82f6!important}.header-icons-container{display:flex;align-items:center;gap:1rem}.header-icon{position:relative;width:32px;height:32px;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-dropdown-container{position:relative;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-icon:before{content:\"\";position:absolute;inset:0;background-color:#3b82f61a;border-radius:.5rem;opacity:0;transform:scale(.8);transition:all .2s cubic-bezier(.4,0,.2,1)}.header-icon:hover:before{opacity:1;transform:scale(1)}.header-icon:hover{color:#3b82f6}.header-icon:active{transform:scale(.95)}.header-tooltip{position:absolute;bottom:-26px;left:50%;transform:translate(-50%);background-color:#374151e6;color:#fff;padding:.25rem .6rem;border-radius:.25rem;font-size:.7rem;white-space:nowrap;opacity:0;pointer-events:none;transition:all .2s cubic-bezier(.4,0,.2,1);z-index:1000;box-shadow:0 2px 5px #0003;letter-spacing:.01em;will-change:transform,opacity}.header-tooltip:before{content:\"\";position:absolute;bottom:100%;left:50%;transform:translate(-50%);border-width:5px;border-style:solid;border-color:transparent transparent rgba(55,65,81,.9) transparent}.header-icon:hover .header-tooltip{opacity:1;transform:translate(-50%) translateY(0)}.header-badge{position:absolute;top:0;right:0;min-width:16px;height:16px;border-radius:8px;background-color:#ef4444;color:#fff;font-size:9px;display:flex;align-items:center;justify-content:center;padding:0 4px;box-shadow:0 1px 3px #ef44444d;font-weight:600;z-index:2;transition:all .2s ease}.header-icon:hover .header-badge{transform:scale(1.1)}.header-divider{height:20px;width:1px;background-color:#e5e7ebcc;margin:0 6px}.header-year-dropdown-wrapper{position:relative;display:flex;align-items:center;justify-content:center}.header-year-pill{position:relative;display:flex;align-items:center;padding:.25rem .625rem;background:linear-gradient(135deg,#3b82f61a,#2563eb26);border:1px solid rgba(59,130,246,.3);border-radius:9999px;color:#2563eb;font-size:.6875rem;font-weight:600;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;white-space:nowrap;box-shadow:0 1px 2px #3b82f61a;min-height:22px;height:22px;line-height:1}.header-year-pill:hover{background:linear-gradient(135deg,#3b82f626,#2563eb33);border-color:#3b82f666;transform:translateY(-1px);box-shadow:0 2px 6px #3b82f626}.header-year-pill-text{max-width:180px;overflow:hidden;text-overflow:ellipsis;letter-spacing:-.01em;line-height:1;display:inline-block}::ng-deep .header-dropdown-container .dropdown-trigger{background:transparent!important;border:none!important;border-radius:0!important;padding:0!important;width:100%!important;height:100%!important;min-width:auto!important;box-shadow:none!important;display:flex!important;align-items:center!important;justify-content:center!important;transition:none!important;cursor:pointer!important}::ng-deep .header-dropdown-container .dropdown-trigger:hover{background:transparent!important}::ng-deep .header-dropdown-container .dropdown-trigger:hover .header-year-pill{background:linear-gradient(135deg,#3b82f626,#2563eb33)!important;border-color:#3b82f666!important;transform:translateY(-1px)!important;box-shadow:0 2px 6px #3b82f626!important}::ng-deep .header-dropdown-container .dropdown-trigger:focus,::ng-deep .header-dropdown-container .dropdown-trigger:focus-visible,::ng-deep .header-dropdown-container .dropdown-trigger:active{outline:none!important;box-shadow:0 2px 6px #3b82f626!important}.profile-avatar{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px #2563eb33;transition:all .2s cubic-bezier(.4,0,.2,1);letter-spacing:-.5px;cursor:pointer;border:2px solid transparent}.profile-avatar:hover,.header-icon:hover .profile-avatar{transform:scale(1.08);box-shadow:0 3px 8px #2563eb4d;border-color:#3b82f64d}::ng-deep .user-profile .dropdown-trigger{background:transparent!important;border:none!important;padding:0!important;width:auto!important;height:auto!important;border-radius:0!important}::ng-deep .user-profile .dropdown-trigger:hover{background:transparent!important}::ng-deep .user-profile .dropdown-trigger:focus,::ng-deep .user-profile .dropdown-trigger:focus-visible,::ng-deep .user-profile .dropdown-trigger:active{outline:none!important;box-shadow:none!important}.header-avatar{width:36px;height:36px;border-radius:50%;overflow:hidden;transition:all .2s cubic-bezier(.4,0,.2,1);border:2px solid transparent;box-shadow:0 2px 4px #0000001a}.header-avatar:hover{border-color:#3b82f6;transform:scale(1.05);box-shadow:0 3px 6px #3b82f64d}@media (max-width: 768px){.header-search-container{margin:0 1rem}.header-icons-container{gap:.5rem}}@media (max-width: 640px){.header-search-container{max-width:200px;margin:0 .5rem}}\n"] }]
|
|
1850
2195
|
}], ctorParameters: () => [], propDecorators: { triggerTemplate: [{
|
|
1851
2196
|
type: ViewChild,
|
|
1852
2197
|
args: ['triggerTemplate']
|
|
@@ -1856,6 +2201,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
1856
2201
|
}], academicYearTriggerTemplate: [{
|
|
1857
2202
|
type: ViewChild,
|
|
1858
2203
|
args: ['academicYearTriggerTemplate']
|
|
2204
|
+
}], notificationTriggerTemplate: [{
|
|
2205
|
+
type: ViewChild,
|
|
2206
|
+
args: ['notificationTriggerTemplate']
|
|
1859
2207
|
}] } });
|
|
1860
2208
|
|
|
1861
2209
|
class CideLytUserStatusService {
|
|
@@ -3058,8 +3406,8 @@ class CideLytSidedrawerWrapperComponent {
|
|
|
3058
3406
|
}
|
|
3059
3407
|
ngOnInit() {
|
|
3060
3408
|
// Initialize the component map (You'd likely populate this from a config or service)
|
|
3061
|
-
this.componentMap['drowar_notes'] = () => import('./cloud-ide-layout-sidedrawer-notes.component-
|
|
3062
|
-
this.componentMap['drawer_theme'] = () => import('./cloud-ide-layout-drawer-theme.component-
|
|
3409
|
+
this.componentMap['drowar_notes'] = () => import('./cloud-ide-layout-sidedrawer-notes.component-sYWI-yH9.mjs').then(m => m.CideLytSidedrawerNotesComponent);
|
|
3410
|
+
this.componentMap['drawer_theme'] = () => import('./cloud-ide-layout-drawer-theme.component-DMn2Cznf.mjs').then(m => m.CideLytDrawerThemeComponent);
|
|
3063
3411
|
}
|
|
3064
3412
|
async loadComponent(configFor) {
|
|
3065
3413
|
console.log('🔍 SIDEDRAWER - Loading component:', configFor, 'Current tab:', this.currentTabId);
|
|
@@ -3582,7 +3930,7 @@ const layoutControlPannelChildRoutes = [{
|
|
|
3582
3930
|
},
|
|
3583
3931
|
{
|
|
3584
3932
|
path: "home",
|
|
3585
|
-
loadComponent: () => import('./cloud-ide-layout-home-wrapper.component-
|
|
3933
|
+
loadComponent: () => import('./cloud-ide-layout-home-wrapper.component-ZWphfyNz.mjs').then(c => c.CideLytHomeWrapperComponent),
|
|
3586
3934
|
canActivate: [authGuard],
|
|
3587
3935
|
data: {
|
|
3588
3936
|
reuseTab: true, // For CustomRouteReuseStrategy
|
|
@@ -5150,4 +5498,4 @@ var floatingEntityRightsSharing_component = /*#__PURE__*/Object.freeze({
|
|
|
5150
5498
|
*/
|
|
5151
5499
|
|
|
5152
5500
|
export { AppStateHelperService as A, CideLytSharedWrapperComponent as C, ENVIRONMENT_CONFIG as E, CideLytSidebarService as a, CideLytRequestService as b, CideLytSidedrawerService as c, CideLytThemeService as d, AppStateService as e, CloudIdeLayoutService as f, CloudIdeLayoutComponent as g, CideLytSharedService as h, layoutControlPannelChildRoutes as i, CustomRouteReuseStrategy as j, CideLytUserStatusService as k, layoutRoutes as l, CacheManagerService as m, CideLytFileManagerService as n, CideLytFloatingEntityRightsSharingComponent as o, processThemeVariable as p, CideLytFloatingEntityRightsSharingService as q, setCSSVariable as s, themeFactory as t };
|
|
5153
|
-
//# sourceMappingURL=cloud-ide-layout-cloud-ide-layout-
|
|
5501
|
+
//# sourceMappingURL=cloud-ide-layout-cloud-ide-layout-CKLj-6xH.mjs.map
|