cloud-ide-layout 1.0.62 → 1.0.64
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-CKLj-6xH.mjs → cloud-ide-layout-cloud-ide-layout-8S-2Ir2T.mjs} +186 -27
- package/fesm2022/cloud-ide-layout-cloud-ide-layout-8S-2Ir2T.mjs.map +1 -0
- package/fesm2022/{cloud-ide-layout-drawer-theme.component-DMn2Cznf.mjs → cloud-ide-layout-drawer-theme.component-j59G67L1.mjs} +2 -2
- package/fesm2022/{cloud-ide-layout-drawer-theme.component-DMn2Cznf.mjs.map → cloud-ide-layout-drawer-theme.component-j59G67L1.mjs.map} +1 -1
- package/fesm2022/{cloud-ide-layout-floating-entity-selection.component-L3hZ4LJm.mjs → cloud-ide-layout-floating-entity-selection.component-Bv5s966h.mjs} +2 -2
- package/fesm2022/{cloud-ide-layout-floating-entity-selection.component-L3hZ4LJm.mjs.map → cloud-ide-layout-floating-entity-selection.component-Bv5s966h.mjs.map} +1 -1
- package/fesm2022/{cloud-ide-layout-home-wrapper.component-ZWphfyNz.mjs → cloud-ide-layout-home-wrapper.component-CI7dPMxZ.mjs} +2 -2
- package/fesm2022/{cloud-ide-layout-home-wrapper.component-ZWphfyNz.mjs.map → cloud-ide-layout-home-wrapper.component-CI7dPMxZ.mjs.map} +1 -1
- package/fesm2022/{cloud-ide-layout-sidedrawer-notes.component-sYWI-yH9.mjs → cloud-ide-layout-sidedrawer-notes.component-Br9LCZ7q.mjs} +2 -2
- package/fesm2022/{cloud-ide-layout-sidedrawer-notes.component-sYWI-yH9.mjs.map → cloud-ide-layout-sidedrawer-notes.component-Br9LCZ7q.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-CKLj-6xH.mjs.map +0 -1
|
@@ -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-Bv5s966h.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');
|
|
@@ -1552,16 +1552,21 @@ class CideLytHeaderWrapperComponent {
|
|
|
1552
1552
|
}
|
|
1553
1553
|
/**
|
|
1554
1554
|
* Load notifications from API
|
|
1555
|
+
* @param showReadOnly - If true, only load read notifications. If false, load all.
|
|
1555
1556
|
*/
|
|
1556
|
-
loadNotifications() {
|
|
1557
|
+
loadNotifications(showReadOnly = false) {
|
|
1557
1558
|
try {
|
|
1558
1559
|
// Get notifications from WebSocket service (real-time)
|
|
1559
1560
|
const wsNotifications = this.wsNotificationService?.allNotifications() || [];
|
|
1560
1561
|
console.log('[Notifications] WebSocket notifications:', wsNotifications.length);
|
|
1561
1562
|
// Load from API to get all notifications (including read status)
|
|
1562
|
-
|
|
1563
|
+
// By default, we can filter to show unread first, but load all for "View All"
|
|
1564
|
+
const params = {
|
|
1563
1565
|
pageSize: 20
|
|
1564
|
-
}
|
|
1566
|
+
};
|
|
1567
|
+
// Optionally filter by status if we only want unread
|
|
1568
|
+
// Note: We load all and filter client-side for better UX
|
|
1569
|
+
this.notificationApiService.getNotifications(params).subscribe({
|
|
1565
1570
|
next: (response) => {
|
|
1566
1571
|
console.log('[Notifications] API response:', response);
|
|
1567
1572
|
if (response && response.success && response.data) {
|
|
@@ -1631,8 +1636,11 @@ class CideLytHeaderWrapperComponent {
|
|
|
1631
1636
|
updateNotificationDropdown() {
|
|
1632
1637
|
const notifs = this.notifications();
|
|
1633
1638
|
const unreadCount = this.unreadCount();
|
|
1634
|
-
//
|
|
1635
|
-
|
|
1639
|
+
// Filter to show only unread notifications in the dropdown (or all if "View All" was clicked)
|
|
1640
|
+
// For now, show first 20 notifications (increased from 10 for better UX)
|
|
1641
|
+
const notificationsToShow = notifs.slice(0, 20);
|
|
1642
|
+
// Map notifications to dropdown items
|
|
1643
|
+
this.notificationItems = notificationsToShow.map(notif => ({
|
|
1636
1644
|
id: notif.id,
|
|
1637
1645
|
label: notif.title,
|
|
1638
1646
|
icon: this.getNotificationIcon(notif.type),
|
|
@@ -1657,7 +1665,7 @@ class CideLytHeaderWrapperComponent {
|
|
|
1657
1665
|
iconColor: 'tw-text-blue-500'
|
|
1658
1666
|
});
|
|
1659
1667
|
}
|
|
1660
|
-
// Add "Clear All" option
|
|
1668
|
+
// Add "Clear All" option (only if there are notifications)
|
|
1661
1669
|
this.notificationItems.push({
|
|
1662
1670
|
id: 'clear-all',
|
|
1663
1671
|
label: 'Clear All',
|
|
@@ -1672,10 +1680,13 @@ class CideLytHeaderWrapperComponent {
|
|
|
1672
1680
|
label: '',
|
|
1673
1681
|
divider: true
|
|
1674
1682
|
});
|
|
1675
|
-
// Add "View All" option
|
|
1683
|
+
// Add "View All" option (show count if more than displayed)
|
|
1684
|
+
const viewAllLabel = notifs.length > 20
|
|
1685
|
+
? `View All Notifications (${notifs.length})`
|
|
1686
|
+
: 'View All Notifications';
|
|
1676
1687
|
this.notificationItems.push({
|
|
1677
1688
|
id: 'view-all',
|
|
1678
|
-
label:
|
|
1689
|
+
label: viewAllLabel,
|
|
1679
1690
|
icon: 'list',
|
|
1680
1691
|
iconColor: 'tw-text-blue-500'
|
|
1681
1692
|
});
|
|
@@ -1716,6 +1727,54 @@ class CideLytHeaderWrapperComponent {
|
|
|
1716
1727
|
};
|
|
1717
1728
|
return colorMap[type] || 'tw-text-gray-500';
|
|
1718
1729
|
}
|
|
1730
|
+
/**
|
|
1731
|
+
* Handle notification item click (from custom template)
|
|
1732
|
+
*/
|
|
1733
|
+
onNotificationItemClick(notification) {
|
|
1734
|
+
// Mark notification as read when clicked
|
|
1735
|
+
this.markNotificationAsRead(String(notification.id));
|
|
1736
|
+
// Navigate to action URL if available
|
|
1737
|
+
if (notification?.action_url) {
|
|
1738
|
+
this.router.navigate([notification.action_url]);
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
/**
|
|
1742
|
+
* Check if notification is read
|
|
1743
|
+
*/
|
|
1744
|
+
isNotificationRead(notification) {
|
|
1745
|
+
return notification.isRead === true;
|
|
1746
|
+
}
|
|
1747
|
+
/**
|
|
1748
|
+
* Get time ago string
|
|
1749
|
+
*/
|
|
1750
|
+
getTimeAgo(timestamp) {
|
|
1751
|
+
const now = new Date();
|
|
1752
|
+
const diff = now.getTime() - new Date(timestamp).getTime();
|
|
1753
|
+
const seconds = Math.floor(diff / 1000);
|
|
1754
|
+
const minutes = Math.floor(seconds / 60);
|
|
1755
|
+
const hours = Math.floor(minutes / 60);
|
|
1756
|
+
const days = Math.floor(hours / 24);
|
|
1757
|
+
if (days > 0)
|
|
1758
|
+
return `${days}d ago`;
|
|
1759
|
+
if (hours > 0)
|
|
1760
|
+
return `${hours}h ago`;
|
|
1761
|
+
if (minutes > 0)
|
|
1762
|
+
return `${minutes}m ago`;
|
|
1763
|
+
return 'Just now';
|
|
1764
|
+
}
|
|
1765
|
+
/**
|
|
1766
|
+
* Get notification icon color class
|
|
1767
|
+
*/
|
|
1768
|
+
getNotificationIconColorClass(type) {
|
|
1769
|
+
const colorMap = {
|
|
1770
|
+
'info': 'tw-text-blue-500',
|
|
1771
|
+
'success': 'tw-text-green-500',
|
|
1772
|
+
'warning': 'tw-text-yellow-500',
|
|
1773
|
+
'error': 'tw-text-red-500',
|
|
1774
|
+
'system': 'tw-text-gray-500'
|
|
1775
|
+
};
|
|
1776
|
+
return colorMap[type] || 'tw-text-gray-500';
|
|
1777
|
+
}
|
|
1719
1778
|
/**
|
|
1720
1779
|
* Handle notification dropdown item click
|
|
1721
1780
|
*/
|
|
@@ -1730,9 +1789,9 @@ class CideLytHeaderWrapperComponent {
|
|
|
1730
1789
|
return;
|
|
1731
1790
|
}
|
|
1732
1791
|
if (item.id === 'view-all') {
|
|
1733
|
-
//
|
|
1734
|
-
console.log('View all notifications');
|
|
1735
|
-
|
|
1792
|
+
// Show all notifications - for now, just reload with more items
|
|
1793
|
+
console.log('[Notifications] View all notifications');
|
|
1794
|
+
this.loadAllNotifications();
|
|
1736
1795
|
return;
|
|
1737
1796
|
}
|
|
1738
1797
|
if (item.id === 'no-notifications' || item.id === 'divider' || item.id === 'divider-1' || item.id === 'divider-2') {
|
|
@@ -1750,19 +1809,28 @@ class CideLytHeaderWrapperComponent {
|
|
|
1750
1809
|
* Mark a single notification as read
|
|
1751
1810
|
*/
|
|
1752
1811
|
markNotificationAsRead(notificationId) {
|
|
1812
|
+
console.log('[Notifications] Marking as read:', notificationId);
|
|
1753
1813
|
// Mark in WebSocket service
|
|
1754
1814
|
if (this.wsNotificationService) {
|
|
1755
1815
|
this.wsNotificationService.markAsRead(notificationId);
|
|
1756
1816
|
}
|
|
1757
1817
|
// Mark in API
|
|
1758
1818
|
this.notificationApiService.markAsRead(notificationId).subscribe({
|
|
1759
|
-
next: () => {
|
|
1760
|
-
console.log('[Notifications] Marked as read:',
|
|
1819
|
+
next: (response) => {
|
|
1820
|
+
console.log('[Notifications] Marked as read successfully:', response);
|
|
1761
1821
|
// Reload notifications to update unread count
|
|
1762
1822
|
this.loadNotifications();
|
|
1763
1823
|
},
|
|
1764
1824
|
error: (error) => {
|
|
1765
1825
|
console.error('[Notifications] Error marking notification as read:', error);
|
|
1826
|
+
console.error('[Notifications] Error details:', {
|
|
1827
|
+
status: error?.status,
|
|
1828
|
+
statusText: error?.statusText,
|
|
1829
|
+
message: error?.message,
|
|
1830
|
+
url: error?.url
|
|
1831
|
+
});
|
|
1832
|
+
// Still reload to get updated state
|
|
1833
|
+
this.loadNotifications();
|
|
1766
1834
|
}
|
|
1767
1835
|
});
|
|
1768
1836
|
}
|
|
@@ -1770,14 +1838,23 @@ class CideLytHeaderWrapperComponent {
|
|
|
1770
1838
|
* Mark all notifications as read
|
|
1771
1839
|
*/
|
|
1772
1840
|
markAllAsRead() {
|
|
1841
|
+
console.log('[Notifications] Marking all as read');
|
|
1773
1842
|
this.notificationApiService.markAllAsRead().subscribe({
|
|
1774
|
-
next: () => {
|
|
1775
|
-
console.log('[Notifications] All notifications marked as read');
|
|
1843
|
+
next: (response) => {
|
|
1844
|
+
console.log('[Notifications] All notifications marked as read successfully:', response);
|
|
1776
1845
|
// Reload notifications to update unread count
|
|
1777
1846
|
this.loadNotifications();
|
|
1778
1847
|
},
|
|
1779
1848
|
error: (error) => {
|
|
1780
1849
|
console.error('[Notifications] Error marking all as read:', error);
|
|
1850
|
+
console.error('[Notifications] Error details:', {
|
|
1851
|
+
status: error?.status,
|
|
1852
|
+
statusText: error?.statusText,
|
|
1853
|
+
message: error?.message,
|
|
1854
|
+
url: error?.url
|
|
1855
|
+
});
|
|
1856
|
+
// Still reload to get updated state
|
|
1857
|
+
this.loadNotifications();
|
|
1781
1858
|
}
|
|
1782
1859
|
});
|
|
1783
1860
|
}
|
|
@@ -1786,22 +1863,104 @@ class CideLytHeaderWrapperComponent {
|
|
|
1786
1863
|
*/
|
|
1787
1864
|
clearAllNotifications() {
|
|
1788
1865
|
if (confirm('Are you sure you want to clear all notifications? This will mark them all as read.')) {
|
|
1866
|
+
console.log('[Notifications] Clearing all notifications');
|
|
1789
1867
|
// First mark all as read
|
|
1790
1868
|
this.notificationApiService.markAllAsRead().subscribe({
|
|
1791
|
-
next: () => {
|
|
1792
|
-
console.log('[Notifications] All notifications
|
|
1793
|
-
//
|
|
1869
|
+
next: (response) => {
|
|
1870
|
+
console.log('[Notifications] All notifications marked as read:', response);
|
|
1871
|
+
// Filter current notifications to mark them as read locally
|
|
1872
|
+
const currentNotifs = this.notifications();
|
|
1873
|
+
const updatedNotifs = currentNotifs.map(notif => ({
|
|
1874
|
+
...notif,
|
|
1875
|
+
isRead: true
|
|
1876
|
+
}));
|
|
1877
|
+
// Clear notifications from view (they're all read now)
|
|
1794
1878
|
this.notifications.set([]);
|
|
1795
1879
|
this.updateNotificationDropdown();
|
|
1796
|
-
// Reload to get updated state
|
|
1797
|
-
|
|
1880
|
+
// Reload after a short delay to get updated state from server
|
|
1881
|
+
// This will show empty or only new unread notifications
|
|
1882
|
+
setTimeout(() => {
|
|
1883
|
+
this.loadNotifications();
|
|
1884
|
+
}, 500);
|
|
1798
1885
|
},
|
|
1799
1886
|
error: (error) => {
|
|
1800
1887
|
console.error('[Notifications] Error clearing all notifications:', error);
|
|
1888
|
+
console.error('[Notifications] Error details:', {
|
|
1889
|
+
status: error?.status,
|
|
1890
|
+
statusText: error?.statusText,
|
|
1891
|
+
message: error?.message,
|
|
1892
|
+
url: error?.url
|
|
1893
|
+
});
|
|
1894
|
+
// Still try to reload
|
|
1895
|
+
this.loadNotifications();
|
|
1801
1896
|
}
|
|
1802
1897
|
});
|
|
1803
1898
|
}
|
|
1804
1899
|
}
|
|
1900
|
+
/**
|
|
1901
|
+
* Load all notifications (for "View All" functionality)
|
|
1902
|
+
*/
|
|
1903
|
+
loadAllNotifications() {
|
|
1904
|
+
try {
|
|
1905
|
+
const wsNotifications = this.wsNotificationService?.allNotifications() || [];
|
|
1906
|
+
console.log('[Notifications] Loading all notifications (View All)');
|
|
1907
|
+
// Load more notifications from API (increase pageSize)
|
|
1908
|
+
this.notificationApiService.getNotifications({
|
|
1909
|
+
pageSize: 100 // Load more for "View All"
|
|
1910
|
+
}).subscribe({
|
|
1911
|
+
next: (response) => {
|
|
1912
|
+
console.log('[Notifications] All notifications API response:', response);
|
|
1913
|
+
if (response && response.success && response.data) {
|
|
1914
|
+
// Convert server notifications to notification payloads
|
|
1915
|
+
const apiPayloads = response.data.map((notif) => ({
|
|
1916
|
+
id: String(notif._id),
|
|
1917
|
+
type: notif.not_type || 'info',
|
|
1918
|
+
category: notif.not_category,
|
|
1919
|
+
title: notif.not_title,
|
|
1920
|
+
message: notif.not_message,
|
|
1921
|
+
data: notif.not_data,
|
|
1922
|
+
action_url: notif.not_action_url,
|
|
1923
|
+
action_label: notif.not_action_label,
|
|
1924
|
+
priority: notif.not_priority || 'normal',
|
|
1925
|
+
created_at: new Date(notif.not_created_at),
|
|
1926
|
+
timestamp: new Date(notif.not_created_at),
|
|
1927
|
+
isRead: notif.not_status === 'read' || notif.not_read_at !== undefined
|
|
1928
|
+
}));
|
|
1929
|
+
// Merge WebSocket and API notifications
|
|
1930
|
+
const mergedNotifications = [];
|
|
1931
|
+
// Add API notifications first
|
|
1932
|
+
apiPayloads.forEach(apiNotif => {
|
|
1933
|
+
mergedNotifications.push(apiNotif);
|
|
1934
|
+
});
|
|
1935
|
+
// Add WebSocket notifications that aren't in API
|
|
1936
|
+
wsNotifications.forEach(wsNotif => {
|
|
1937
|
+
if (!mergedNotifications.find(n => n.id === wsNotif.id)) {
|
|
1938
|
+
mergedNotifications.push({ ...wsNotif, isRead: false });
|
|
1939
|
+
}
|
|
1940
|
+
});
|
|
1941
|
+
// Sort by timestamp (newest first)
|
|
1942
|
+
mergedNotifications.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
1943
|
+
console.log('[Notifications] Total notifications loaded:', mergedNotifications.length);
|
|
1944
|
+
this.notifications.set(mergedNotifications);
|
|
1945
|
+
this.updateNotificationDropdown();
|
|
1946
|
+
}
|
|
1947
|
+
else {
|
|
1948
|
+
console.warn('[Notifications] API response invalid');
|
|
1949
|
+
this.notifications.set(wsNotifications);
|
|
1950
|
+
this.updateNotificationDropdown();
|
|
1951
|
+
}
|
|
1952
|
+
},
|
|
1953
|
+
error: (error) => {
|
|
1954
|
+
console.error('[Notifications] Error loading all notifications:', error);
|
|
1955
|
+
this.notifications.set(wsNotifications);
|
|
1956
|
+
this.updateNotificationDropdown();
|
|
1957
|
+
}
|
|
1958
|
+
});
|
|
1959
|
+
}
|
|
1960
|
+
catch (error) {
|
|
1961
|
+
console.error('[Notifications] Error in loadAllNotifications:', error);
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1805
1964
|
ngAfterViewInit() {
|
|
1806
1965
|
// No need to manually load file details - cideEleFileImage directive will handle it
|
|
1807
1966
|
}
|
|
@@ -2186,12 +2345,12 @@ class CideLytHeaderWrapperComponent {
|
|
|
2186
2345
|
}
|
|
2187
2346
|
}
|
|
2188
2347
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytHeaderWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
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"] }] });
|
|
2348
|
+
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 [menuTemplate]=\"notificationMenuTemplate\"\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 <!-- Custom Notification Menu Template -->\n <ng-template #notificationMenuTemplate let-items=\"items\">\n <div class=\"notification-dropdown-menu\">\n <!-- Header -->\n <div class=\"notification-dropdown-header\">\n <h3 class=\"notification-dropdown-title\">Notifications</h3>\n @if (unreadCount() > 0) {\n <span class=\"notification-unread-badge\">{{ unreadCount() }} unread</span>\n }\n </div>\n\n <!-- Notifications List -->\n <div class=\"notification-dropdown-body\">\n @if (notifications().length === 0) {\n <div class=\"notification-empty-state\">\n <cide-ele-icon class=\"notification-empty-icon\">notifications_off</cide-ele-icon>\n <p class=\"notification-empty-text\">No notifications</p>\n </div>\n } @else {\n @for (notif of notifications().slice(0, 10); track notif.id) {\n <div \n class=\"notification-item\" \n [class.unread]=\"!isNotificationRead(notif)\"\n (click)=\"onNotificationItemClick(notif)\">\n <div class=\"notification-item-icon\">\n <cide-ele-icon [class]=\"getNotificationIconColorClass(notif.type)\">\n {{ getNotificationIcon(notif.type) }}\n </cide-ele-icon>\n </div>\n <div class=\"notification-item-content\">\n <div class=\"notification-item-header\">\n <h4 class=\"notification-item-title\">{{ notif.title }}</h4>\n <span class=\"notification-item-time\">{{ getTimeAgo(notif.timestamp) }}</span>\n </div>\n <p class=\"notification-item-message\">{{ notif.message }}</p>\n @if (notif.priority === 'urgent') {\n <span class=\"notification-priority-badge urgent\">Urgent</span>\n }\n </div>\n @if (!isNotificationRead(notif)) {\n <div class=\"notification-unread-indicator\"></div>\n }\n </div>\n }\n }\n </div>\n\n <!-- Footer Actions -->\n @if (notifications().length > 0) {\n <div class=\"notification-dropdown-footer\">\n <div class=\"notification-actions\">\n @if (unreadCount() > 0) {\n <button \n type=\"button\" \n class=\"notification-action-btn\"\n (click)=\"markAllAsRead()\">\n <cide-ele-icon>done_all</cide-ele-icon>\n <span>Mark all read</span>\n </button>\n }\n <button \n type=\"button\" \n class=\"notification-action-btn\"\n (click)=\"clearAllNotifications()\">\n <cide-ele-icon>clear_all</cide-ele-icon>\n <span>Clear all</span>\n </button>\n <button \n type=\"button\" \n class=\"notification-action-btn primary\"\n (click)=\"loadAllNotifications()\">\n <cide-ele-icon>list</cide-ele-icon>\n <span>View all</span>\n </button>\n </div>\n </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}}.notification-dropdown-menu{width:100%;max-width:400px;background:#fff;border-radius:12px;box-shadow:0 10px 40px #00000026;overflow:hidden;display:flex;flex-direction:column;max-height:600px}.notification-dropdown-header{padding:16px 20px;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid rgba(255,255,255,.1)}.notification-dropdown-title{margin:0;font-size:1.1rem;font-weight:600;letter-spacing:-.01em}.notification-unread-badge{background:#ffffff40;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);padding:4px 12px;border-radius:12px;font-size:.75rem;font-weight:600;border:1px solid rgba(255,255,255,.3)}.notification-dropdown-body{flex:1;overflow-y:auto;max-height:450px;padding:8px 0}.notification-dropdown-body::-webkit-scrollbar{width:6px}.notification-dropdown-body::-webkit-scrollbar-track{background:#f1f1f1}.notification-dropdown-body::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:3px}.notification-dropdown-body::-webkit-scrollbar-thumb:hover{background:#a8a8a8}.notification-empty-state{padding:40px 20px;text-align:center;color:#9ca3af}.notification-empty-icon{font-size:3rem!important;color:#d1d5db!important;margin-bottom:12px}.notification-empty-text{margin:0;font-size:.9rem;color:#6b7280}.notification-item{display:flex;align-items:flex-start;padding:12px 20px;cursor:pointer;transition:all .2s ease;border-left:3px solid transparent;position:relative;gap:12px}.notification-item:hover{background:#f9fafb;border-left-color:#3b82f6}.notification-item.unread{background:#eff6ff;border-left-color:#3b82f6}.notification-item.unread:hover{background:#dbeafe}.notification-item-icon{flex-shrink:0;width:40px;height:40px;border-radius:10px;background:#f3f4f6;display:flex;align-items:center;justify-content:center;transition:all .2s ease}.notification-item.unread .notification-item-icon{background:#dbeafe}.notification-item-icon cide-ele-icon{font-size:1.25rem!important}.notification-item-content{flex:1;min-width:0}.notification-item-header{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:4px}.notification-item-title{margin:0;font-size:.9rem;font-weight:600;color:#111827;line-height:1.4;flex:1}.notification-item-time{font-size:.75rem;color:#6b7280;white-space:nowrap;flex-shrink:0}.notification-item-message{margin:0;font-size:.85rem;color:#4b5563;line-height:1.5;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis}.notification-priority-badge{display:inline-block;margin-top:6px;padding:2px 8px;border-radius:4px;font-size:.7rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px}.notification-priority-badge.urgent{background:#fee2e2;color:#dc2626}.notification-unread-indicator{position:absolute;top:16px;right:16px;width:8px;height:8px;border-radius:50%;background:#3b82f6;box-shadow:0 0 0 2px #fff}.notification-dropdown-footer{padding:12px 20px;background:#f9fafb;border-top:1px solid #e5e7eb}.notification-actions{display:flex;gap:8px;justify-content:flex-end}.notification-action-btn{display:flex;align-items:center;gap:6px;padding:6px 12px;border:1px solid #e5e7eb;background:#fff;border-radius:6px;font-size:.8rem;color:#4b5563;cursor:pointer;transition:all .2s ease;font-weight:500}.notification-action-btn:hover{background:#f3f4f6;border-color:#d1d5db;color:#111827}.notification-action-btn.primary{background:#3b82f6;color:#fff;border-color:#3b82f6}.notification-action-btn.primary:hover{background:#2563eb;border-color:#2563eb}.notification-action-btn cide-ele-icon{font-size:1rem!important}\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"] }] });
|
|
2190
2349
|
}
|
|
2191
2350
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytHeaderWrapperComponent, decorators: [{
|
|
2192
2351
|
type: Component,
|
|
2193
2352
|
args: [{ selector: 'cide-lyt-header-wrapper', imports: [CideInputComponent, CommonModule, CideIconComponent,
|
|
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"] }]
|
|
2353
|
+
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 [menuTemplate]=\"notificationMenuTemplate\"\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 <!-- Custom Notification Menu Template -->\n <ng-template #notificationMenuTemplate let-items=\"items\">\n <div class=\"notification-dropdown-menu\">\n <!-- Header -->\n <div class=\"notification-dropdown-header\">\n <h3 class=\"notification-dropdown-title\">Notifications</h3>\n @if (unreadCount() > 0) {\n <span class=\"notification-unread-badge\">{{ unreadCount() }} unread</span>\n }\n </div>\n\n <!-- Notifications List -->\n <div class=\"notification-dropdown-body\">\n @if (notifications().length === 0) {\n <div class=\"notification-empty-state\">\n <cide-ele-icon class=\"notification-empty-icon\">notifications_off</cide-ele-icon>\n <p class=\"notification-empty-text\">No notifications</p>\n </div>\n } @else {\n @for (notif of notifications().slice(0, 10); track notif.id) {\n <div \n class=\"notification-item\" \n [class.unread]=\"!isNotificationRead(notif)\"\n (click)=\"onNotificationItemClick(notif)\">\n <div class=\"notification-item-icon\">\n <cide-ele-icon [class]=\"getNotificationIconColorClass(notif.type)\">\n {{ getNotificationIcon(notif.type) }}\n </cide-ele-icon>\n </div>\n <div class=\"notification-item-content\">\n <div class=\"notification-item-header\">\n <h4 class=\"notification-item-title\">{{ notif.title }}</h4>\n <span class=\"notification-item-time\">{{ getTimeAgo(notif.timestamp) }}</span>\n </div>\n <p class=\"notification-item-message\">{{ notif.message }}</p>\n @if (notif.priority === 'urgent') {\n <span class=\"notification-priority-badge urgent\">Urgent</span>\n }\n </div>\n @if (!isNotificationRead(notif)) {\n <div class=\"notification-unread-indicator\"></div>\n }\n </div>\n }\n }\n </div>\n\n <!-- Footer Actions -->\n @if (notifications().length > 0) {\n <div class=\"notification-dropdown-footer\">\n <div class=\"notification-actions\">\n @if (unreadCount() > 0) {\n <button \n type=\"button\" \n class=\"notification-action-btn\"\n (click)=\"markAllAsRead()\">\n <cide-ele-icon>done_all</cide-ele-icon>\n <span>Mark all read</span>\n </button>\n }\n <button \n type=\"button\" \n class=\"notification-action-btn\"\n (click)=\"clearAllNotifications()\">\n <cide-ele-icon>clear_all</cide-ele-icon>\n <span>Clear all</span>\n </button>\n <button \n type=\"button\" \n class=\"notification-action-btn primary\"\n (click)=\"loadAllNotifications()\">\n <cide-ele-icon>list</cide-ele-icon>\n <span>View all</span>\n </button>\n </div>\n </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}}.notification-dropdown-menu{width:100%;max-width:400px;background:#fff;border-radius:12px;box-shadow:0 10px 40px #00000026;overflow:hidden;display:flex;flex-direction:column;max-height:600px}.notification-dropdown-header{padding:16px 20px;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid rgba(255,255,255,.1)}.notification-dropdown-title{margin:0;font-size:1.1rem;font-weight:600;letter-spacing:-.01em}.notification-unread-badge{background:#ffffff40;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);padding:4px 12px;border-radius:12px;font-size:.75rem;font-weight:600;border:1px solid rgba(255,255,255,.3)}.notification-dropdown-body{flex:1;overflow-y:auto;max-height:450px;padding:8px 0}.notification-dropdown-body::-webkit-scrollbar{width:6px}.notification-dropdown-body::-webkit-scrollbar-track{background:#f1f1f1}.notification-dropdown-body::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:3px}.notification-dropdown-body::-webkit-scrollbar-thumb:hover{background:#a8a8a8}.notification-empty-state{padding:40px 20px;text-align:center;color:#9ca3af}.notification-empty-icon{font-size:3rem!important;color:#d1d5db!important;margin-bottom:12px}.notification-empty-text{margin:0;font-size:.9rem;color:#6b7280}.notification-item{display:flex;align-items:flex-start;padding:12px 20px;cursor:pointer;transition:all .2s ease;border-left:3px solid transparent;position:relative;gap:12px}.notification-item:hover{background:#f9fafb;border-left-color:#3b82f6}.notification-item.unread{background:#eff6ff;border-left-color:#3b82f6}.notification-item.unread:hover{background:#dbeafe}.notification-item-icon{flex-shrink:0;width:40px;height:40px;border-radius:10px;background:#f3f4f6;display:flex;align-items:center;justify-content:center;transition:all .2s ease}.notification-item.unread .notification-item-icon{background:#dbeafe}.notification-item-icon cide-ele-icon{font-size:1.25rem!important}.notification-item-content{flex:1;min-width:0}.notification-item-header{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:4px}.notification-item-title{margin:0;font-size:.9rem;font-weight:600;color:#111827;line-height:1.4;flex:1}.notification-item-time{font-size:.75rem;color:#6b7280;white-space:nowrap;flex-shrink:0}.notification-item-message{margin:0;font-size:.85rem;color:#4b5563;line-height:1.5;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis}.notification-priority-badge{display:inline-block;margin-top:6px;padding:2px 8px;border-radius:4px;font-size:.7rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px}.notification-priority-badge.urgent{background:#fee2e2;color:#dc2626}.notification-unread-indicator{position:absolute;top:16px;right:16px;width:8px;height:8px;border-radius:50%;background:#3b82f6;box-shadow:0 0 0 2px #fff}.notification-dropdown-footer{padding:12px 20px;background:#f9fafb;border-top:1px solid #e5e7eb}.notification-actions{display:flex;gap:8px;justify-content:flex-end}.notification-action-btn{display:flex;align-items:center;gap:6px;padding:6px 12px;border:1px solid #e5e7eb;background:#fff;border-radius:6px;font-size:.8rem;color:#4b5563;cursor:pointer;transition:all .2s ease;font-weight:500}.notification-action-btn:hover{background:#f3f4f6;border-color:#d1d5db;color:#111827}.notification-action-btn.primary{background:#3b82f6;color:#fff;border-color:#3b82f6}.notification-action-btn.primary:hover{background:#2563eb;border-color:#2563eb}.notification-action-btn cide-ele-icon{font-size:1rem!important}\n"] }]
|
|
2195
2354
|
}], ctorParameters: () => [], propDecorators: { triggerTemplate: [{
|
|
2196
2355
|
type: ViewChild,
|
|
2197
2356
|
args: ['triggerTemplate']
|
|
@@ -3406,8 +3565,8 @@ class CideLytSidedrawerWrapperComponent {
|
|
|
3406
3565
|
}
|
|
3407
3566
|
ngOnInit() {
|
|
3408
3567
|
// Initialize the component map (You'd likely populate this from a config or service)
|
|
3409
|
-
this.componentMap['drowar_notes'] = () => import('./cloud-ide-layout-sidedrawer-notes.component-
|
|
3410
|
-
this.componentMap['drawer_theme'] = () => import('./cloud-ide-layout-drawer-theme.component-
|
|
3568
|
+
this.componentMap['drowar_notes'] = () => import('./cloud-ide-layout-sidedrawer-notes.component-Br9LCZ7q.mjs').then(m => m.CideLytSidedrawerNotesComponent);
|
|
3569
|
+
this.componentMap['drawer_theme'] = () => import('./cloud-ide-layout-drawer-theme.component-j59G67L1.mjs').then(m => m.CideLytDrawerThemeComponent);
|
|
3411
3570
|
}
|
|
3412
3571
|
async loadComponent(configFor) {
|
|
3413
3572
|
console.log('🔍 SIDEDRAWER - Loading component:', configFor, 'Current tab:', this.currentTabId);
|
|
@@ -3930,7 +4089,7 @@ const layoutControlPannelChildRoutes = [{
|
|
|
3930
4089
|
},
|
|
3931
4090
|
{
|
|
3932
4091
|
path: "home",
|
|
3933
|
-
loadComponent: () => import('./cloud-ide-layout-home-wrapper.component-
|
|
4092
|
+
loadComponent: () => import('./cloud-ide-layout-home-wrapper.component-CI7dPMxZ.mjs').then(c => c.CideLytHomeWrapperComponent),
|
|
3934
4093
|
canActivate: [authGuard],
|
|
3935
4094
|
data: {
|
|
3936
4095
|
reuseTab: true, // For CustomRouteReuseStrategy
|
|
@@ -5498,4 +5657,4 @@ var floatingEntityRightsSharing_component = /*#__PURE__*/Object.freeze({
|
|
|
5498
5657
|
*/
|
|
5499
5658
|
|
|
5500
5659
|
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 };
|
|
5501
|
-
//# sourceMappingURL=cloud-ide-layout-cloud-ide-layout-
|
|
5660
|
+
//# sourceMappingURL=cloud-ide-layout-cloud-ide-layout-8S-2Ir2T.mjs.map
|