eiu-app-kit 1.0.2 → 1.0.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"eiu-app-kit.mjs","sources":["../../../projects/eiu-app-kit/src/lib/eiu-app-kit.tokens.ts","../../../projects/eiu-app-kit/src/lib/app-launcher/eiu-app-launcher-menu.token.ts","../../../projects/eiu-app-kit/src/lib/app-launcher/eiu-app-launcher.component.ts","../../../projects/eiu-app-kit/src/lib/app-launcher/eiu-app-launcher.component.html","../../../projects/eiu-app-kit/src/lib/app-launcher/eiu-app-launcher.module.ts","../../../projects/eiu-app-kit/src/lib/sidebar-shared/logo/eiu-sidebar-logo.component.ts","../../../projects/eiu-app-kit/src/lib/sidebar-shared/logo/eiu-sidebar-logo.component.html","../../../projects/eiu-app-kit/src/lib/sidebar-shared/contact/eiu-contact-support.component.ts","../../../projects/eiu-app-kit/src/lib/sidebar-shared/contact/eiu-contact-support.component.html","../../../projects/eiu-app-kit/src/lib/sidebar-shared/eiu-sidebar-shared.module.ts","../../../projects/eiu-app-kit/src/lib/footer/eiu-app-footer.component.ts","../../../projects/eiu-app-kit/src/lib/footer/eiu-app-footer.component.html","../../../projects/eiu-app-kit/src/lib/footer/eiu-app-footer.module.ts","../../../projects/eiu-app-kit/src/lib/feature-news/constants.ts","../../../projects/eiu-app-kit/src/lib/feature-news/news-api.service.ts","../../../projects/eiu-app-kit/src/lib/feature-news/feature-news-dialog.service.ts","../../../projects/eiu-app-kit/src/lib/feature-news/feature-news.service.ts","../../../projects/eiu-app-kit/src/lib/feature-news/feature-news-dialog.component.ts","../../../projects/eiu-app-kit/src/lib/feature-news/feature-news-dialog.component.html","../../../projects/eiu-app-kit/src/lib/feature-news/eiu-app-feature-news.module.ts","../../../projects/eiu-app-kit/src/public-api.ts","../../../projects/eiu-app-kit/src/eiu-app-kit.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\r\n\r\n/**\r\n * Base URL API EIU App (ví dụ `environment.API_EIU_APP`).\r\n * Dùng cho News API, icon launcher, … — cung cấp một lần trong `AppModule`.\r\n */\r\nexport const EIU_APP_API_BASE_URL = new InjectionToken<string>(\r\n 'EIU_APP_API_BASE_URL'\r\n);\r\n","import { InjectionToken } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\nimport { EiuAppLauncherMenuItem } from './eiu-app-launcher-menu.model';\r\n\r\nexport interface EiuAppLauncherMenuLoader {\r\n loadItems(): Observable<EiuAppLauncherMenuItem[]>;\r\n}\r\n\r\n/**\r\n * Host app cung cấp cách load danh sách ứng dụng (ví dụ `ProjectService.getAllProject()`).\r\n */\r\nexport const EIU_APP_LAUNCHER_MENU_LOADER = new InjectionToken<EiuAppLauncherMenuLoader>(\r\n 'EIU_APP_LAUNCHER_MENU_LOADER'\r\n);\r\n","import {\n AfterViewInit,\n ChangeDetectorRef,\n Component,\n EventEmitter,\n HostListener,\n Inject,\n OnInit,\n Input,\n Output\n} from '@angular/core';\nimport { EIU_APP_API_BASE_URL } from '../eiu-app-kit.tokens';\nimport {\n EIU_APP_LAUNCHER_MENU_LOADER,\n EiuAppLauncherMenuLoader\n} from './eiu-app-launcher-menu.token';\n\nexport interface EiuAppLauncherViewItem {\n label: string;\n icon: string;\n link: string;\n isActive: boolean;\n}\n\n@Component({\n selector: 'app-eiu-app-launcher',\n templateUrl: './eiu-app-launcher.component.html',\n styleUrls: ['./eiu-app-launcher.component.css']\n})\nexport class EiuAppLauncherComponent implements OnInit, AfterViewInit {\n /** Phát ra khi user bấm icon menu (sidebar). Host gắn với store / layout. */\n @Output() readonly sidebarToggle = new EventEmitter<void>();\n @Input() appLabel = 'Ứng dụng';\n\n isScreenWide = true;\n menuItems: EiuAppLauncherViewItem[] = [];\n\n private readonly _apiBase: string;\n\n constructor(\n @Inject(EIU_APP_LAUNCHER_MENU_LOADER)\n private readonly _menuLoader: EiuAppLauncherMenuLoader,\n @Inject(EIU_APP_API_BASE_URL) apiBaseUrl: string,\n private readonly _cdr: ChangeDetectorRef\n ) {\n this._apiBase = (apiBaseUrl || '').replace(/\\/$/, '');\n }\n\n ngOnInit(): void {\n this._loadMenu();\n }\n\n @HostListener('window:resize')\n onResize(): void {\n this._adjustMenuPosition();\n }\n\n ngAfterViewInit(): void {\n this._adjustMenuPosition();\n this._cdr.detectChanges();\n }\n\n onToggleMenuSidebar(): void {\n this.sidebarToggle.emit();\n }\n\n private _adjustMenuPosition(): void {\n this.isScreenWide = window.innerWidth > 1300;\n }\n\n private _loadMenu(): void {\n this._menuLoader.loadItems().subscribe({\n next: (res) => {\n this.menuItems = (res ?? [])\n .filter((x) => x.link)\n .sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0))\n .map((x) => ({\n label: x.name_VI ?? '',\n icon: this._iconUrl(x.imageUrl),\n link: x.link as string,\n isActive: this._isActive(x.link as string)\n }));\n },\n error: (err) => console.error(err)\n });\n }\n\n private _iconUrl(imageUrl: string | null): string {\n if (!imageUrl) {\n return '';\n }\n if (/^https?:\\/\\//i.test(imageUrl)) {\n return imageUrl;\n }\n const path = imageUrl.replace(/^\\//, '');\n return this._apiBase ? `${this._apiBase}/${path}` : path;\n }\n\n private _isActive(link: string): boolean {\n try {\n const currentDomain = new URL(window.location.href).origin;\n const linkDomain = new URL(link).origin;\n return currentDomain === linkDomain;\n } catch {\n return false;\n }\n }\n\n}\n","<ul class=\"navbar-nav\">\n <li class=\"nav-item\">\n <a class=\"nav-link\" href=\"#\" (click)=\"onToggleMenuSidebar(); $event.preventDefault()\" role=\"button\"><i\n class=\"fas fa-bars\"></i></a>\n </li>\n <ng-container *ngIf=\"isScreenWide\">\n <li class=\"nav-item\" *ngFor=\"let menuItem of menuItems | slice: 0:5\">\n <a class=\"nav-link\" href=\"{{ menuItem.link }}\" [ngClass]=\"{ active: menuItem.isActive }\" target=\"_blank\">\n {{ menuItem.label }}\n </a>\n </li>\n </ng-container>\n <li class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" role=\"button\" aria-expanded=\"false\">\n {{ appLabel }}\n </a>\n\n <!-- Mega Menu -->\n <div class=\"mega-dropdown\" id=\"megaDropdown\">\n <div class=\"menu-item-card\" *ngFor=\"let menuItem of menuItems\">\n <a class=\"dropdown-item\" href=\"{{ menuItem.link }}\" [ngClass]=\"{ active: menuItem.isActive }\"\n target=\"_blank\">\n <div class=\"icon-container\">\n <img [src]=\"menuItem.icon\" alt=\"\" height=\"25\" width=\"25\" />\n </div>\n <span>{{ menuItem.label }}</span>\n </a>\n </div>\n </div>\n </li>\n</ul>","import { CommonModule } from '@angular/common';\r\nimport { NgModule } from '@angular/core';\r\nimport { EiuAppLauncherComponent } from './eiu-app-launcher.component';\r\n\r\n/**\r\n * Import ở shell layout (ví dụ `ThemeModule`).\r\n * Cần `EIU_APP_API_BASE_URL` và `EIU_APP_LAUNCHER_MENU_LOADER` trong `providers`.\r\n */\r\n@NgModule({\r\n imports: [CommonModule],\r\n declarations: [EiuAppLauncherComponent],\r\n exports: [EiuAppLauncherComponent]\r\n})\r\nexport class EiuAppLauncherModule { }\r\n","import { Component, Input } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-eiu-sidebar-logo',\r\n templateUrl: './eiu-sidebar-logo.component.html',\r\n styleUrls: ['./eiu-sidebar-logo.component.css']\r\n})\r\nexport class EiuSidebarLogoComponent {\r\n @Input() imageUrl = '';\r\n @Input() alt = 'Đại học Quốc tế Miền Đông (EIU)';\r\n @Input() text = 'Đại học Quốc tế Miền Đông (EIU)';\r\n @Input() homeLink = '/';\r\n}\r\n","<a [routerLink]=\"[homeLink]\" class=\"brand-link\">\r\n <img\r\n class=\"brand-image\"\r\n [src]=\"imageUrl\"\r\n [alt]=\"alt\"\r\n height=\"40\"\r\n />\r\n <strong class=\"brand-text font-weight-light\">{{ text }}</strong>\r\n</a>\r\n","import { Component, Input } from '@angular/core';\nimport { EiuAppSidebarContactItem } from '../sidebar-shared.model';\n\n@Component({\n selector: 'app-eiu-contact-support',\n templateUrl: './eiu-contact-support.component.html',\n styleUrls: ['./eiu-contact-support.component.css']\n})\nexport class EiuContactSupportComponent {\n @Input() title = 'Liên hệ';\n @Input() contacts: EiuAppSidebarContactItem[] = [];\n\n get sortedContacts(): EiuAppSidebarContactItem[] {\n return [...(this.contacts || [])].sort(\n (a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0)\n );\n }\n}\n","<div class=\"box-contact\">\n <div class=\"header-contact\"></div>\n <li class=\"nav-header\">\n <strong class=\"contact-title\">\n <i class=\"nav-icon fa fa-headphones\"></i>&nbsp;&nbsp;{{ title }}\n </strong>\n </li>\n <li class=\"nav-item\" *ngFor=\"let item of sortedContacts\">\n <div class=\"nav-link contact-content\">\n <p class=\"text contact-name\">{{ item?.fullName }}</p>\n <div class=\"contact-line\">\n <a class=\"text-sm contact-link\" [href]=\"'tel:' + item?.phoneNumber\" [title]=\"item?.phoneNumber\">\n <span class=\"contact-meta\">M: {{ item?.phoneNumber }}</span>\n </a>\n </div>\n <div class=\"contact-line\">\n <a class=\"text-sm contact-link\" [href]=\"'mailto:' + item?.email\" [title]=\"item?.email\">\n <span class=\"contact-meta\">E: {{ item?.email }}</span>\n </a>\n </div>\n </div>\n </li>\n</div>","import { CommonModule } from '@angular/common';\r\nimport { NgModule } from '@angular/core';\r\nimport { RouterModule } from '@angular/router';\r\nimport { EiuContactSupportComponent } from './contact/eiu-contact-support.component';\r\nimport { EiuSidebarLogoComponent } from './logo/eiu-sidebar-logo.component';\r\n\r\n@NgModule({\r\n imports: [CommonModule, RouterModule],\r\n declarations: [EiuSidebarLogoComponent, EiuContactSupportComponent],\r\n exports: [EiuSidebarLogoComponent, EiuContactSupportComponent]\r\n})\r\nexport class EiuSidebarSharedModule { }\r\n","import { Component, EventEmitter, Input, Output } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-eiu-app-footer',\r\n templateUrl: './eiu-app-footer.component.html',\r\n styleUrls: ['./eiu-app-footer.component.css']\r\n})\r\nexport class EiuAppFooterComponent {\r\n @Input() appVersion = '';\r\n\r\n @Input() copyrightYear = '2023';\r\n\r\n @Input() companyName = 'IT - EIU';\r\n\r\n @Input() companyUrl = 'https://sites.google.com/eiu.edu.vn/oit/';\r\n\r\n @Input() allRightsText = 'All rights reserved.';\r\n\r\n @Input() versionLabel = 'Version';\r\n\r\n @Output() readonly newFeatureClick = new EventEmitter<void>();\r\n\r\n onNewFeatureDialogClick(event: Event): void {\r\n event.preventDefault();\r\n this.newFeatureClick.emit();\r\n }\r\n}\r\n","<div class=\"main-footer\">\r\n <div class=\"footer-bar\">\r\n <div class=\"footer-bar__copy\">\r\n <span>Copyright © {{ copyrightYear }}</span>\r\n <a\r\n class=\"footer-bar__link\"\r\n href=\"https://sites.google.com/eiu.edu.vn/oit/\"\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n >\r\n {{ companyName }}\r\n </a>\r\n <span>. {{ allRightsText }}</span>\r\n </div>\r\n \r\n <div class=\"footer-bar__version\">\r\n <button\r\n type=\"button\"\r\n class=\"footer-version-chip-wrap\"\r\n (click)=\"onNewFeatureDialogClick($event)\"\r\n [attr.aria-label]=\"\r\n 'Application version ' + appVersion + '. Nhấn để sao chép phiên bản vào clipboard'\r\n \"\r\n title=\"Sao chép phiên bản vào clipboard\"\r\n >\r\n <div class=\"footer-version-chip\">\r\n <span class=\"footer-radar\" aria-hidden=\"true\">\r\n <span class=\"footer-radar__sweep\"></span>\r\n <svg class=\"footer-radar__dot\" viewBox=\"0 0 24 24\" focusable=\"false\" aria-hidden=\"true\">\r\n <circle class=\"footer-radar__dot-shape\" cx=\"12\" cy=\"12\" r=\"3.25\" />\r\n </svg>\r\n </span>\r\n <div class=\"footer-version\">\r\n <span class=\"footer-version__label\">{{ versionLabel }}</span>\r\n <span class=\"footer-version__sep\" aria-hidden=\"true\">·</span>\r\n <span class=\"footer-version__value\" translate=\"no\">{{ appVersion }}</span>\r\n </div>\r\n </div>\r\n </button>\r\n </div>\r\n </div>\r\n</div>","import { CommonModule } from '@angular/common';\r\nimport { NgModule } from '@angular/core';\r\nimport { EiuAppFooterComponent } from './eiu-app-footer.component';\r\n\r\n@NgModule({\r\n imports: [CommonModule],\r\n declarations: [EiuAppFooterComponent],\r\n exports: [EiuAppFooterComponent]\r\n})\r\nexport class EiuAppFooterModule {}\r\n","/** Prefix localStorage: feature_news_seen::<userId>::<projectIdentifier> */\r\nexport const FEATURE_NEWS_SEEN_STORAGE_KEY_PREFIX = 'feature_news_seen::';\r\n\r\n/**\r\n * Mặc định project identifier trên Redmine (EIU App).\r\n * Ứng dụng host có thể dùng hằng này hoặc chuỗi riêng khi gọi service.\r\n */\r\nexport const FEATURE_NEWS_REDMINE_PROJECT_IDENTIFIER =\r\n 'login-sso-quan-ly-nhan-su';\r\n","import { HttpClient, HttpParams } from '@angular/common/http';\r\nimport { Injectable, inject } from '@angular/core';\r\nimport { Observable, catchError, of } from 'rxjs';\r\nimport { EIU_APP_API_BASE_URL } from '../eiu-app-kit.tokens';\r\nimport { OperationResult } from './models/operation-result.model';\r\nimport { RedmineNewsResponse } from './models/redmine-news.model';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class NewsApiService {\r\n private readonly _httpClient = inject(HttpClient);\r\n private readonly _apiBaseUrl = inject(EIU_APP_API_BASE_URL);\r\n\r\n getNewsByProjectIdentifier(\r\n projectIdentifier: string,\r\n limit = 1\r\n ): Observable<OperationResult<RedmineNewsResponse>> {\r\n const params = new HttpParams()\r\n .set('projectIdentifier', projectIdentifier)\r\n .set('limit', String(limit));\r\n const url = `${this._apiBaseUrl}/News/GetRedmineNewsByProjectIdentifier`;\r\n\r\n return this._httpClient\r\n .get<OperationResult<RedmineNewsResponse>>(url, { params })\r\n .pipe(\r\n catchError((error: unknown) =>\r\n of({\r\n success: false,\r\n statusCode: 500,\r\n message:\r\n error instanceof Error\r\n ? error.message\r\n : 'Cannot get feature news from API.',\r\n data: null\r\n })\r\n )\r\n );\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { BehaviorSubject, Observable, Subject, take } from 'rxjs';\r\nimport { RedmineNewsItem } from './models/redmine-news.model';\r\n\r\nexport interface FeatureNewsDialogState {\r\n news: RedmineNewsItem[];\r\n}\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class FeatureNewsDialogService {\r\n private readonly _dialogState = new BehaviorSubject<FeatureNewsDialogState | null>(\r\n null\r\n );\r\n private _closeNotifier: Subject<void> | null = null;\r\n\r\n readonly dialogState$ = this._dialogState.asObservable();\r\n\r\n open(news: RedmineNewsItem[]): Observable<void> {\r\n this._closeNotifier = new Subject<void>();\r\n this._dialogState.next({ news });\r\n return this._closeNotifier.asObservable().pipe(take(1));\r\n }\r\n\r\n close(): void {\r\n this._dialogState.next(null);\r\n this._closeNotifier?.next();\r\n this._closeNotifier?.complete();\r\n this._closeNotifier = null;\r\n }\r\n}\r\n","import { Injectable, inject } from '@angular/core';\r\nimport { Observable, catchError, map, of, switchMap, tap } from 'rxjs';\r\nimport { FEATURE_NEWS_SEEN_STORAGE_KEY_PREFIX } from './constants';\r\nimport { FeatureNewsDialogService } from './feature-news-dialog.service';\r\nimport { NewsApiService } from './news-api.service';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class FeatureNewsService {\r\n private readonly _newsApiService = inject(NewsApiService);\r\n private readonly _featureNewsDialogService = inject(FeatureNewsDialogService);\r\n\r\n buildSeenKey(userId: string, projectIdentifier: string): string {\r\n return `${FEATURE_NEWS_SEEN_STORAGE_KEY_PREFIX}${userId}::${projectIdentifier}`;\r\n }\r\n\r\n hasSeenLatestNews(\r\n userId: string,\r\n projectIdentifier: string,\r\n latestNewsId: number\r\n ): boolean {\r\n const key = this.buildSeenKey(userId, projectIdentifier);\r\n return localStorage.getItem(key) === String(latestNewsId);\r\n }\r\n\r\n markSeen(userId: string, projectIdentifier: string, latestNewsId: number): void {\r\n const key = this.buildSeenKey(userId, projectIdentifier);\r\n localStorage.setItem(key, String(latestNewsId));\r\n }\r\n\r\n checkAndShowFeatureNews(\r\n userId: string,\r\n projectIdentifier: string\r\n ): Observable<void> {\r\n return this._newsApiService.getNewsByProjectIdentifier(projectIdentifier, 1).pipe(\r\n switchMap((result) => {\r\n const news = result.success ? (result.data?.news ?? []).slice(0, 1) : [];\r\n if (!news.length) {\r\n return of(void 0);\r\n }\r\n const latestNews = news[0];\r\n if (this.hasSeenLatestNews(userId, projectIdentifier, latestNews.id)) {\r\n return of(void 0);\r\n }\r\n\r\n return this._featureNewsDialogService.open(news).pipe(\r\n tap(() => this.markSeen(userId, projectIdentifier, latestNews.id)),\r\n map(() => void 0)\r\n );\r\n }),\r\n catchError(() => of(void 0))\r\n );\r\n }\r\n\r\n showLatestFeatureNewsManually(\r\n userId: string,\r\n projectIdentifier: string\r\n ): Observable<void> {\r\n return this._newsApiService.getNewsByProjectIdentifier(projectIdentifier, 1).pipe(\r\n switchMap((result) => {\r\n const news = result.success ? (result.data?.news ?? []).slice(0, 1) : [];\r\n if (!news.length) {\r\n return of(void 0);\r\n }\r\n const latestNews = news[0];\r\n return this._featureNewsDialogService.open(news).pipe(\r\n tap(() => this.markSeen(userId, projectIdentifier, latestNews.id)),\r\n map(() => void 0)\r\n );\r\n }),\r\n catchError(() => of(void 0))\r\n );\r\n }\r\n}\r\n","import { Component, OnDestroy, OnInit, inject } from '@angular/core';\nimport { Subscription } from 'rxjs';\nimport { RedmineNewsItem } from './models/redmine-news.model';\nimport {\n FeatureNewsDialogService,\n FeatureNewsDialogState\n} from './feature-news-dialog.service';\n\n@Component({\n selector: 'app-feature-news-dialog',\n templateUrl: './feature-news-dialog.component.html',\n styleUrls: ['./feature-news-dialog.component.scss']\n})\nexport class FeatureNewsDialogComponent implements OnInit, OnDestroy {\n private readonly _featureNewsDialogService = inject(FeatureNewsDialogService);\n private _subscription: Subscription | null = null;\n protected dialogState: FeatureNewsDialogState | null = null;\n\n ngOnInit(): void {\n this._subscription = this._featureNewsDialogService.dialogState$.subscribe(\n (state) => {\n this.dialogState = state;\n }\n );\n }\n\n ngOnDestroy(): void {\n this._subscription?.unsubscribe();\n }\n\n getSummary(item: RedmineNewsItem): string {\n return this._truncateText(item.summary || '', 200);\n }\n\n closeDialog(): void {\n this._featureNewsDialogService.close();\n }\n\n private _truncateText(text: string, maxLength: number): string {\n if (!text) {\n return '';\n }\n if (text.length <= maxLength) {\n return text;\n }\n return `${text.slice(0, maxLength)}...`;\n }\n}\n","<div class=\"feature-news-overlay\" *ngIf=\"dialogState\">\n <div class=\"feature-news-dialog\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"feature-news-title\">\n <div class=\"feature-news-header\">\n <div class=\"feature-news-header__main\">\n <div class=\"feature-news-brand\">\n <div class=\"feature-news-title-wrap mt-2\">\n <span id=\"feature-news-title\" class=\"feature-news-chip\">Cập nhật tính năng</span>\n </div>\n </div>\n </div>\n <button type=\"button\" class=\"feature-news-close\" aria-label=\"Dong\" (click)=\"closeDialog()\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n </div>\n\n <div class=\"feature-news-body\">\n <div class=\"feature-news-item\" *ngFor=\"let item of dialogState?.news\">\n <div class=\"feature-news-item-head\">\n <h5 class=\"feature-news-content-label mt-2\">{{ item?.title }}</h5>\n <span class=\"feature-news-item-tag\">Mới nhất</span>\n </div>\n <div class=\"feature-news-content-block\" *ngIf=\"item?.summary\">\n <div class=\"feature-news-content-label mt-2\">Tóm tắt</div>\n <div class=\"feature-news-content-panel\">\n <p class=\"feature-news-item-summary\">{{ getSummary(item) }}</p>\n </div>\n </div>\n <div class=\"feature-news-content-block\" *ngIf=\"item?.description\">\n <div class=\"feature-news-content-label mt-2\">Chi tiết</div>\n <div class=\"feature-news-content-panel feature-news-content-panel--detail\">\n <p class=\"feature-news-item-description\">{{ item?.description }}</p>\n </div>\n </div>\n <div class=\"feature-news-item-meta\">\n <span class=\"feature-news-item-meta__dot\" *ngIf=\"item?.author?.name\" aria-hidden=\"true\"></span>\n <span class=\"feature-news-item-meta__date\">{{\n item?.createdOn | date : 'dd/MM/yyyy'\n }}</span>\n\n </div>\n </div>\n </div>\n\n <div class=\"feature-news-footer\">\n <div class=\"feature-news-footer-note\">\n <span class=\"feature-news-footer-note__icon\" aria-hidden=\"true\"></span>\n Thông báo chỉ hiện khi có tin mới; bạn luôn có thể xem lại từ footer.\n </div>\n <button type=\"button\" class=\"feature-news-confirm-btn\" (click)=\"closeDialog()\">\n Đã hiểu\n </button>\n </div>\n </div>\n</div>","import { CommonModule } from '@angular/common';\r\nimport { NgModule } from '@angular/core';\r\nimport { FeatureNewsDialogComponent } from './feature-news-dialog.component';\r\n\r\n/**\r\n * Import module này ở shell layout (hoặc `AppModule`) để có `<app-feature-news-dialog />`.\r\n * Nhớ cung cấp `EIU_APP_API_BASE_URL` trong providers.\r\n */\r\n@NgModule({\r\n imports: [CommonModule],\r\n declarations: [FeatureNewsDialogComponent],\r\n exports: [FeatureNewsDialogComponent]\r\n})\r\nexport class EiuAppFeatureNewsModule {}\r\n","/*\n * EIU App Kit — tái sử dụng giữa các Angular app (feature news Redmine, launcher header, …)\n */\n\nexport * from './lib/eiu-app-kit.tokens';\nexport * from './lib/app-launcher/eiu-app-launcher-menu.model';\nexport * from './lib/app-launcher/eiu-app-launcher-menu.token';\nexport * from './lib/app-launcher/eiu-app-launcher.component';\nexport * from './lib/app-launcher/eiu-app-launcher.module';\nexport * from './lib/sidebar-shared/sidebar-shared.model';\nexport * from './lib/sidebar-shared/logo/eiu-sidebar-logo.component';\nexport * from './lib/sidebar-shared/contact/eiu-contact-support.component';\nexport * from './lib/sidebar-shared/eiu-sidebar-shared.module';\nexport * from './lib/footer/eiu-app-footer.component';\nexport * from './lib/footer/eiu-app-footer.module';\nexport * from './lib/feature-news/constants';\nexport * from './lib/feature-news/models/operation-result.model';\nexport * from './lib/feature-news/models/redmine-news.model';\nexport * from './lib/feature-news/news-api.service';\nexport * from './lib/feature-news/feature-news-dialog.service';\nexport * from './lib/feature-news/feature-news.service';\nexport * from './lib/feature-news/feature-news-dialog.component';\nexport * from './lib/feature-news/eiu-app-feature-news.module';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1"],"mappings":"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"}
1
+ {"version":3,"file":"eiu-app-kit.mjs","sources":["../../../projects/eiu-app-kit/src/lib/eiu-app-kit.tokens.ts","../../../projects/eiu-app-kit/src/lib/app-launcher/eiu-app-launcher-menu.token.ts","../../../projects/eiu-app-kit/src/lib/app-launcher/eiu-app-launcher.component.ts","../../../projects/eiu-app-kit/src/lib/app-launcher/eiu-app-launcher.component.html","../../../projects/eiu-app-kit/src/lib/app-launcher/eiu-app-launcher.module.ts","../../../projects/eiu-app-kit/src/lib/user-menu/eiu-app-user-menu.component.ts","../../../projects/eiu-app-kit/src/lib/user-menu/eiu-app-user-menu.component.html","../../../projects/eiu-app-kit/src/lib/user-menu/eiu-app-user-menu.module.ts","../../../projects/eiu-app-kit/src/lib/sidebar-shared/logo/eiu-sidebar-logo.component.ts","../../../projects/eiu-app-kit/src/lib/sidebar-shared/logo/eiu-sidebar-logo.component.html","../../../projects/eiu-app-kit/src/lib/sidebar-shared/contact/eiu-contact-support.component.ts","../../../projects/eiu-app-kit/src/lib/sidebar-shared/contact/eiu-contact-support.component.html","../../../projects/eiu-app-kit/src/lib/sidebar-shared/eiu-sidebar-shared.module.ts","../../../projects/eiu-app-kit/src/lib/footer/eiu-app-footer.component.ts","../../../projects/eiu-app-kit/src/lib/footer/eiu-app-footer.component.html","../../../projects/eiu-app-kit/src/lib/footer/eiu-app-footer.module.ts","../../../projects/eiu-app-kit/src/lib/feature-news/constants.ts","../../../projects/eiu-app-kit/src/lib/feature-news/news-api.service.ts","../../../projects/eiu-app-kit/src/lib/feature-news/feature-news-dialog.service.ts","../../../projects/eiu-app-kit/src/lib/feature-news/feature-news.service.ts","../../../projects/eiu-app-kit/src/lib/feature-news/feature-news-dialog.component.ts","../../../projects/eiu-app-kit/src/lib/feature-news/feature-news-dialog.component.html","../../../projects/eiu-app-kit/src/lib/feature-news/eiu-app-feature-news.module.ts","../../../projects/eiu-app-kit/src/public-api.ts","../../../projects/eiu-app-kit/src/eiu-app-kit.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\r\n\r\n/**\r\n * Base URL API EIU App (ví dụ `environment.API_EIU_APP`).\r\n * Dùng cho News API, icon launcher, … — cung cấp một lần trong `AppModule`.\r\n */\r\nexport const EIU_APP_API_BASE_URL = new InjectionToken<string>(\r\n 'EIU_APP_API_BASE_URL'\r\n);\r\n","import { InjectionToken } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\nimport { EiuAppLauncherMenuItem } from './eiu-app-launcher-menu.model';\r\n\r\nexport interface EiuAppLauncherMenuLoader {\r\n loadItems(): Observable<EiuAppLauncherMenuItem[]>;\r\n}\r\n\r\n/**\r\n * Host app cung cấp cách load danh sách ứng dụng (ví dụ `ProjectService.getAllProject()`).\r\n */\r\nexport const EIU_APP_LAUNCHER_MENU_LOADER = new InjectionToken<EiuAppLauncherMenuLoader>(\r\n 'EIU_APP_LAUNCHER_MENU_LOADER'\r\n);\r\n","import {\n AfterViewInit,\n ChangeDetectorRef,\n Component,\n EventEmitter,\n HostListener,\n Inject,\n OnInit,\n Input,\n Output\n} from '@angular/core';\nimport { EIU_APP_API_BASE_URL } from '../eiu-app-kit.tokens';\nimport {\n EIU_APP_LAUNCHER_MENU_LOADER,\n EiuAppLauncherMenuLoader\n} from './eiu-app-launcher-menu.token';\n\nexport interface EiuAppLauncherViewItem {\n label: string;\n icon: string;\n link: string;\n isActive: boolean;\n}\n\n@Component({\n selector: 'app-eiu-app-launcher',\n templateUrl: './eiu-app-launcher.component.html',\n styleUrls: ['./eiu-app-launcher.component.css']\n})\nexport class EiuAppLauncherComponent implements OnInit, AfterViewInit {\n /** Phát ra khi user bấm icon menu (sidebar). Host gắn với store / layout. */\n @Output() readonly sidebarToggle = new EventEmitter<void>();\n @Input() appLabel = 'Ứng dụng';\n\n isScreenWide = true;\n menuItems: EiuAppLauncherViewItem[] = [];\n\n private readonly _apiBase: string;\n\n constructor(\n @Inject(EIU_APP_LAUNCHER_MENU_LOADER)\n private readonly _menuLoader: EiuAppLauncherMenuLoader,\n @Inject(EIU_APP_API_BASE_URL) apiBaseUrl: string,\n private readonly _cdr: ChangeDetectorRef\n ) {\n this._apiBase = (apiBaseUrl || '').replace(/\\/$/, '');\n }\n\n ngOnInit(): void {\n this._loadMenu();\n }\n\n @HostListener('window:resize')\n onResize(): void {\n this._adjustMenuPosition();\n }\n\n ngAfterViewInit(): void {\n this._adjustMenuPosition();\n this._cdr.detectChanges();\n }\n\n onToggleMenuSidebar(): void {\n this.sidebarToggle.emit();\n }\n\n private _adjustMenuPosition(): void {\n this.isScreenWide = window.innerWidth > 1300;\n }\n\n private _loadMenu(): void {\n this._menuLoader.loadItems().subscribe({\n next: (res) => {\n this.menuItems = (res ?? [])\n .filter((x) => x.link)\n .sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0))\n .map((x) => ({\n label: x.name_VI ?? '',\n icon: this._iconUrl(x.imageUrl),\n link: x.link as string,\n isActive: this._isActive(x.link as string)\n }));\n },\n error: (err) => console.error(err)\n });\n }\n\n private _iconUrl(imageUrl: string | null): string {\n if (!imageUrl) {\n return '';\n }\n if (/^https?:\\/\\//i.test(imageUrl)) {\n return imageUrl;\n }\n const path = imageUrl.replace(/^\\//, '');\n return this._apiBase ? `${this._apiBase}/${path}` : path;\n }\n\n private _isActive(link: string): boolean {\n try {\n const currentDomain = new URL(window.location.href).origin;\n const linkDomain = new URL(link).origin;\n return currentDomain === linkDomain;\n } catch {\n return false;\n }\n }\n\n}\n","<ul class=\"navbar-nav\">\n <li class=\"nav-item\">\n <a class=\"nav-link\" href=\"#\" (click)=\"onToggleMenuSidebar(); $event.preventDefault()\" role=\"button\"><i\n class=\"fas fa-bars\"></i></a>\n </li>\n <ng-container *ngIf=\"isScreenWide\">\n <li class=\"nav-item\" *ngFor=\"let menuItem of menuItems | slice: 0:5\">\n <a class=\"nav-link\" href=\"{{ menuItem.link }}\" [ngClass]=\"{ active: menuItem.isActive }\" target=\"_blank\">\n {{ menuItem.label }}\n </a>\n </li>\n </ng-container>\n <li class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" role=\"button\" aria-expanded=\"false\">\n {{ appLabel }}\n </a>\n\n <!-- Mega Menu -->\n <div class=\"mega-dropdown\" id=\"megaDropdown\">\n <div class=\"menu-item-card\" *ngFor=\"let menuItem of menuItems\">\n <a class=\"dropdown-item\" href=\"{{ menuItem.link }}\" [ngClass]=\"{ active: menuItem.isActive }\"\n target=\"_blank\">\n <div class=\"icon-container\">\n <img [src]=\"menuItem.icon\" alt=\"\" height=\"25\" width=\"25\" />\n </div>\n <span>{{ menuItem.label }}</span>\n </a>\n </div>\n </div>\n </li>\n</ul>","import { CommonModule } from '@angular/common';\r\nimport { NgModule } from '@angular/core';\r\nimport { EiuAppLauncherComponent } from './eiu-app-launcher.component';\r\n\r\n/**\r\n * Import ở shell layout (ví dụ `ThemeModule`).\r\n * Cần `EIU_APP_API_BASE_URL` và `EIU_APP_LAUNCHER_MENU_LOADER` trong `providers`.\r\n */\r\n@NgModule({\r\n imports: [CommonModule],\r\n declarations: [EiuAppLauncherComponent],\r\n exports: [EiuAppLauncherComponent]\r\n})\r\nexport class EiuAppLauncherModule { }\r\n","import {\r\n Component,\r\n ElementRef,\r\n EventEmitter,\r\n HostListener,\r\n Input,\r\n Output,\r\n ViewChild\r\n} from '@angular/core';\r\nimport { EiuUserMenuProfile } from './eiu-user-menu.model';\r\n\r\n@Component({\r\n selector: 'app-eiu-user-menu',\r\n templateUrl: './eiu-app-user-menu.component.html',\r\n styleUrls: ['./eiu-app-user-menu.component.scss']\r\n})\r\nexport class EiuAppUserMenuComponent {\r\n @ViewChild('root', { static: true }) private readonly _root!: ElementRef<HTMLElement>;\r\n\r\n /** Thông tin user — host bind từ service token / session. */\r\n @Input() profile: EiuUserMenuProfile | null = null;\r\n\r\n /** Ảnh mặc định khi `picture` lỗi hoặc trống (đường dẫn trong assets của host). */\r\n @Input() fallbackAvatar = 'assets/img/icons/default-profile.png';\r\n\r\n @Input() changePasswordLabel = 'Đổi mật khẩu';\r\n @Input() logoutLabel = 'Đăng xuất';\r\n\r\n /** Host xử lý (ví dụ redirect SSO đổi mật khẩu). */\r\n @Output() readonly changePassword = new EventEmitter<void>();\r\n /** Host xử lý (ví dụ Keycloak logout + clear storage). */\r\n @Output() readonly logout = new EventEmitter<void>();\r\n\r\n menuOpen = false;\r\n\r\n onTriggerClick(event: Event): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.menuOpen = !this.menuOpen;\r\n }\r\n\r\n onChangePasswordClick(event: Event): void {\r\n event.preventDefault();\r\n this.changePassword.emit();\r\n this.menuOpen = false;\r\n }\r\n\r\n onLogoutClick(event: Event): void {\r\n event.preventDefault();\r\n this.logout.emit();\r\n this.menuOpen = false;\r\n }\r\n\r\n onAvatarError(event: Event): void {\r\n const img = event.target as HTMLImageElement;\r\n if (img && img.src !== this._absoluteFallback()) {\r\n img.src = this.fallbackAvatar;\r\n }\r\n }\r\n\r\n @HostListener('document:click', ['$event'])\r\n onDocumentClick(event: MouseEvent): void {\r\n if (!this.menuOpen) {\r\n return;\r\n }\r\n const root = this._root?.nativeElement;\r\n if (root && !root.contains(event.target as Node)) {\r\n this.menuOpen = false;\r\n }\r\n }\r\n\r\n @HostListener('document:keydown.escape')\r\n onEscape(): void {\r\n this.menuOpen = false;\r\n }\r\n\r\n private _absoluteFallback(): string {\r\n try {\r\n return new URL(this.fallbackAvatar, window.location.origin).href;\r\n } catch {\r\n return this.fallbackAvatar;\r\n }\r\n }\r\n}\r\n","<div class=\"eiu-user-menu\" #root *ngIf=\"profile as p\">\r\n <div class=\"eiu-user-menu__shell\">\r\n <a\r\n class=\"nav-link eiu-user-menu__trigger\"\r\n href=\"#\"\r\n role=\"button\"\r\n [attr.aria-expanded]=\"menuOpen\"\r\n [attr.aria-haspopup]=\"true\"\r\n (click)=\"onTriggerClick($event)\"\r\n >\r\n <div class=\"eiu-user-menu__trigger-inner\">\r\n <img\r\n [src]=\"p.picture || fallbackAvatar\"\r\n [alt]=\"p.fullName\"\r\n width=\"25\"\r\n height=\"25\"\r\n class=\"eiu-user-menu__img eiu-user-menu__img--sm\"\r\n (error)=\"onAvatarError($event)\"\r\n />\r\n <span class=\"eiu-user-menu__name text-grey-8 text-capitalize\">{{ p.fullName }}</span>\r\n </div>\r\n </a>\r\n\r\n <div class=\"eiu-user-menu__dropdown\" *ngIf=\"menuOpen\" role=\"menu\">\r\n <div class=\"eiu-user-menu__header bg-eiu-primary\">\r\n <img\r\n [src]=\"p.picture || fallbackAvatar\"\r\n [alt]=\"p.fullName\"\r\n width=\"90\"\r\n height=\"90\"\r\n class=\"eiu-user-menu__img eiu-user-menu__img--lg\"\r\n (error)=\"onAvatarError($event)\"\r\n />\r\n <p>\r\n <span>{{ p.fullName }}</span>\r\n <small *ngIf=\"p.email as email\">\r\n <span class=\"mr-2\">{{ email }}</span>\r\n </small>\r\n </p>\r\n </div>\r\n <div class=\"eiu-user-menu__footer\">\r\n <a\r\n href=\"#\"\r\n class=\"btn btn-default btn-flat float-left\"\r\n role=\"menuitem\"\r\n (click)=\"onChangePasswordClick($event)\"\r\n >\r\n <i class=\"fa fa-exchange-alt mr-1\"></i>\r\n {{ changePasswordLabel }}\r\n </a>\r\n <a\r\n href=\"#\"\r\n class=\"btn btn-default btn-flat float-right\"\r\n role=\"menuitem\"\r\n (click)=\"onLogoutClick($event)\"\r\n >\r\n <i class=\"fa fa-sign-out-alt mr-1\"></i>\r\n {{ logoutLabel }}\r\n </a>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n","import { CommonModule } from '@angular/common';\r\nimport { NgModule } from '@angular/core';\r\nimport { EiuAppUserMenuComponent } from './eiu-app-user-menu.component';\r\n\r\n/**\r\n * Menu user header (avatar, đổi mật khẩu, đăng xuất).\r\n * Host cung cấp `[profile]` và xử lý `(changePassword)` / `(logout)`.\r\n */\r\n@NgModule({\r\n imports: [CommonModule],\r\n declarations: [EiuAppUserMenuComponent],\r\n exports: [EiuAppUserMenuComponent]\r\n})\r\nexport class EiuAppUserMenuModule {}\r\n","import { Component, Input } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-eiu-sidebar-logo',\r\n templateUrl: './eiu-sidebar-logo.component.html',\r\n styleUrls: ['./eiu-sidebar-logo.component.css']\r\n})\r\nexport class EiuSidebarLogoComponent {\r\n @Input() imageUrl = '';\r\n @Input() alt = 'Đại học Quốc tế Miền Đông (EIU)';\r\n @Input() text = 'Đại học Quốc tế Miền Đông (EIU)';\r\n @Input() homeLink = '/';\r\n}\r\n","<a [routerLink]=\"[homeLink]\" class=\"brand-link\">\r\n <img\r\n class=\"brand-image\"\r\n [src]=\"imageUrl\"\r\n [alt]=\"alt\"\r\n height=\"40\"\r\n />\r\n <strong class=\"brand-text font-weight-light\">{{ text }}</strong>\r\n</a>\r\n","import { Component, Input } from '@angular/core';\nimport { EiuAppSidebarContactItem } from '../sidebar-shared.model';\n\n@Component({\n selector: 'app-eiu-contact-support',\n templateUrl: './eiu-contact-support.component.html',\n styleUrls: ['./eiu-contact-support.component.css']\n})\nexport class EiuContactSupportComponent {\n @Input() title = 'Liên hệ';\n @Input() contacts: EiuAppSidebarContactItem[] = [];\n\n get sortedContacts(): EiuAppSidebarContactItem[] {\n return [...(this.contacts || [])].sort(\n (a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0)\n );\n }\n}\n","<div class=\"box-contact\">\n <div class=\"header-contact\"></div>\n <li class=\"nav-header\">\n <strong class=\"contact-title\">\n <i class=\"nav-icon fa fa-headphones\"></i>&nbsp;&nbsp;{{ title }}\n </strong>\n </li>\n <li class=\"nav-item\" *ngFor=\"let item of sortedContacts\">\n <div class=\"nav-link contact-content\">\n <p class=\"text contact-name\">{{ item?.fullName }}</p>\n <div class=\"contact-line\">\n <a class=\"text-sm contact-link\" [href]=\"'tel:' + item?.phoneNumber\" [title]=\"item?.phoneNumber\">\n <span class=\"contact-meta\">M: {{ item?.phoneNumber }}</span>\n </a>\n </div>\n <div class=\"contact-line\">\n <a class=\"text-sm contact-link\" [href]=\"'mailto:' + item?.email\" [title]=\"item?.email\">\n <span class=\"contact-meta\">E: {{ item?.email }}</span>\n </a>\n </div>\n </div>\n </li>\n</div>","import { CommonModule } from '@angular/common';\r\nimport { NgModule } from '@angular/core';\r\nimport { RouterModule } from '@angular/router';\r\nimport { EiuContactSupportComponent } from './contact/eiu-contact-support.component';\r\nimport { EiuSidebarLogoComponent } from './logo/eiu-sidebar-logo.component';\r\n\r\n@NgModule({\r\n imports: [CommonModule, RouterModule],\r\n declarations: [EiuSidebarLogoComponent, EiuContactSupportComponent],\r\n exports: [EiuSidebarLogoComponent, EiuContactSupportComponent]\r\n})\r\nexport class EiuSidebarSharedModule { }\r\n","import { Component, EventEmitter, Input, Output } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-eiu-app-footer',\r\n templateUrl: './eiu-app-footer.component.html',\r\n styleUrls: ['./eiu-app-footer.component.css']\r\n})\r\nexport class EiuAppFooterComponent {\r\n @Input() appVersion = '';\r\n\r\n @Input() copyrightYear = '2023';\r\n\r\n @Input() companyName = 'IT - EIU';\r\n\r\n @Input() companyUrl = 'https://sites.google.com/eiu.edu.vn/oit/';\r\n\r\n @Input() allRightsText = 'All rights reserved.';\r\n\r\n @Input() versionLabel = 'Version';\r\n\r\n @Output() readonly newFeatureClick = new EventEmitter<void>();\r\n\r\n onNewFeatureDialogClick(event: Event): void {\r\n event.preventDefault();\r\n this.newFeatureClick.emit();\r\n }\r\n}\r\n","<div class=\"main-footer\">\r\n <div class=\"footer-bar\">\r\n <div class=\"footer-bar__copy\">\r\n <span>Copyright © {{ copyrightYear }}</span>\r\n <a\r\n class=\"footer-bar__link\"\r\n href=\"https://sites.google.com/eiu.edu.vn/oit/\"\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n >\r\n {{ companyName }}\r\n </a>\r\n <span>. {{ allRightsText }}</span>\r\n </div>\r\n \r\n <div class=\"footer-bar__version\">\r\n <button\r\n type=\"button\"\r\n class=\"footer-version-chip-wrap\"\r\n (click)=\"onNewFeatureDialogClick($event)\"\r\n [attr.aria-label]=\"\r\n 'Application version ' + appVersion + '. Nhấn để sao chép phiên bản vào clipboard'\r\n \"\r\n title=\"Sao chép phiên bản vào clipboard\"\r\n >\r\n <div class=\"footer-version-chip\">\r\n <span class=\"footer-radar\" aria-hidden=\"true\">\r\n <span class=\"footer-radar__sweep\"></span>\r\n <svg class=\"footer-radar__dot\" viewBox=\"0 0 24 24\" focusable=\"false\" aria-hidden=\"true\">\r\n <circle class=\"footer-radar__dot-shape\" cx=\"12\" cy=\"12\" r=\"3.25\" />\r\n </svg>\r\n </span>\r\n <div class=\"footer-version\">\r\n <span class=\"footer-version__label\">{{ versionLabel }}</span>\r\n <span class=\"footer-version__sep\" aria-hidden=\"true\">·</span>\r\n <span class=\"footer-version__value\" translate=\"no\">{{ appVersion }}</span>\r\n </div>\r\n </div>\r\n </button>\r\n </div>\r\n </div>\r\n</div>","import { CommonModule } from '@angular/common';\r\nimport { NgModule } from '@angular/core';\r\nimport { EiuAppFooterComponent } from './eiu-app-footer.component';\r\n\r\n@NgModule({\r\n imports: [CommonModule],\r\n declarations: [EiuAppFooterComponent],\r\n exports: [EiuAppFooterComponent]\r\n})\r\nexport class EiuAppFooterModule {}\r\n","/** Prefix localStorage: feature_news_seen::<userId>::<projectIdentifier> */\r\nexport const FEATURE_NEWS_SEEN_STORAGE_KEY_PREFIX = 'feature_news_seen::';\r\n\r\n/**\r\n * Mặc định project identifier trên Redmine (EIU App).\r\n * Ứng dụng host có thể dùng hằng này hoặc chuỗi riêng khi gọi service.\r\n */\r\nexport const FEATURE_NEWS_REDMINE_PROJECT_IDENTIFIER =\r\n 'login-sso-quan-ly-nhan-su';\r\n","import { HttpClient, HttpParams } from '@angular/common/http';\r\nimport { Injectable, inject } from '@angular/core';\r\nimport { Observable, catchError, of } from 'rxjs';\r\nimport { EIU_APP_API_BASE_URL } from '../eiu-app-kit.tokens';\r\nimport { OperationResult } from './models/operation-result.model';\r\nimport { RedmineNewsResponse } from './models/redmine-news.model';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class NewsApiService {\r\n private readonly _httpClient = inject(HttpClient);\r\n private readonly _apiBaseUrl = inject(EIU_APP_API_BASE_URL);\r\n\r\n getNewsByProjectIdentifier(\r\n projectIdentifier: string,\r\n limit = 1\r\n ): Observable<OperationResult<RedmineNewsResponse>> {\r\n const params = new HttpParams()\r\n .set('projectIdentifier', projectIdentifier)\r\n .set('limit', String(limit));\r\n const url = `${this._apiBaseUrl}/News/GetRedmineNewsByProjectIdentifier`;\r\n\r\n return this._httpClient\r\n .get<OperationResult<RedmineNewsResponse>>(url, { params })\r\n .pipe(\r\n catchError((error: unknown) =>\r\n of({\r\n success: false,\r\n statusCode: 500,\r\n message:\r\n error instanceof Error\r\n ? error.message\r\n : 'Cannot get feature news from API.',\r\n data: null\r\n })\r\n )\r\n );\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { BehaviorSubject, Observable, Subject, take } from 'rxjs';\r\nimport { RedmineNewsItem } from './models/redmine-news.model';\r\n\r\nexport interface FeatureNewsDialogState {\r\n news: RedmineNewsItem[];\r\n}\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class FeatureNewsDialogService {\r\n private readonly _dialogState = new BehaviorSubject<FeatureNewsDialogState | null>(\r\n null\r\n );\r\n private _closeNotifier: Subject<void> | null = null;\r\n\r\n readonly dialogState$ = this._dialogState.asObservable();\r\n\r\n open(news: RedmineNewsItem[]): Observable<void> {\r\n this._closeNotifier = new Subject<void>();\r\n this._dialogState.next({ news });\r\n return this._closeNotifier.asObservable().pipe(take(1));\r\n }\r\n\r\n close(): void {\r\n this._dialogState.next(null);\r\n this._closeNotifier?.next();\r\n this._closeNotifier?.complete();\r\n this._closeNotifier = null;\r\n }\r\n}\r\n","import { Injectable, inject } from '@angular/core';\r\nimport { Observable, catchError, map, of, switchMap, tap } from 'rxjs';\r\nimport { FEATURE_NEWS_SEEN_STORAGE_KEY_PREFIX } from './constants';\r\nimport { FeatureNewsDialogService } from './feature-news-dialog.service';\r\nimport { NewsApiService } from './news-api.service';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class FeatureNewsService {\r\n private readonly _newsApiService = inject(NewsApiService);\r\n private readonly _featureNewsDialogService = inject(FeatureNewsDialogService);\r\n\r\n buildSeenKey(userId: string, projectIdentifier: string): string {\r\n return `${FEATURE_NEWS_SEEN_STORAGE_KEY_PREFIX}${userId}::${projectIdentifier}`;\r\n }\r\n\r\n hasSeenLatestNews(\r\n userId: string,\r\n projectIdentifier: string,\r\n latestNewsId: number\r\n ): boolean {\r\n const key = this.buildSeenKey(userId, projectIdentifier);\r\n return localStorage.getItem(key) === String(latestNewsId);\r\n }\r\n\r\n markSeen(userId: string, projectIdentifier: string, latestNewsId: number): void {\r\n const key = this.buildSeenKey(userId, projectIdentifier);\r\n localStorage.setItem(key, String(latestNewsId));\r\n }\r\n\r\n checkAndShowFeatureNews(\r\n userId: string,\r\n projectIdentifier: string\r\n ): Observable<void> {\r\n return this._newsApiService.getNewsByProjectIdentifier(projectIdentifier, 1).pipe(\r\n switchMap((result) => {\r\n const news = result.success ? (result.data?.news ?? []).slice(0, 1) : [];\r\n if (!news.length) {\r\n return of(void 0);\r\n }\r\n const latestNews = news[0];\r\n if (this.hasSeenLatestNews(userId, projectIdentifier, latestNews.id)) {\r\n return of(void 0);\r\n }\r\n\r\n return this._featureNewsDialogService.open(news).pipe(\r\n tap(() => this.markSeen(userId, projectIdentifier, latestNews.id)),\r\n map(() => void 0)\r\n );\r\n }),\r\n catchError(() => of(void 0))\r\n );\r\n }\r\n\r\n showLatestFeatureNewsManually(\r\n userId: string,\r\n projectIdentifier: string\r\n ): Observable<void> {\r\n return this._newsApiService.getNewsByProjectIdentifier(projectIdentifier, 1).pipe(\r\n switchMap((result) => {\r\n const news = result.success ? (result.data?.news ?? []).slice(0, 1) : [];\r\n if (!news.length) {\r\n return of(void 0);\r\n }\r\n const latestNews = news[0];\r\n return this._featureNewsDialogService.open(news).pipe(\r\n tap(() => this.markSeen(userId, projectIdentifier, latestNews.id)),\r\n map(() => void 0)\r\n );\r\n }),\r\n catchError(() => of(void 0))\r\n );\r\n }\r\n}\r\n","import { Component, OnDestroy, OnInit, inject } from '@angular/core';\nimport { Subscription } from 'rxjs';\nimport { RedmineNewsItem } from './models/redmine-news.model';\nimport {\n FeatureNewsDialogService,\n FeatureNewsDialogState\n} from './feature-news-dialog.service';\n\n@Component({\n selector: 'app-feature-news-dialog',\n templateUrl: './feature-news-dialog.component.html',\n styleUrls: ['./feature-news-dialog.component.scss']\n})\nexport class FeatureNewsDialogComponent implements OnInit, OnDestroy {\n private readonly _featureNewsDialogService = inject(FeatureNewsDialogService);\n private _subscription: Subscription | null = null;\n protected dialogState: FeatureNewsDialogState | null = null;\n\n ngOnInit(): void {\n this._subscription = this._featureNewsDialogService.dialogState$.subscribe(\n (state) => {\n this.dialogState = state;\n }\n );\n }\n\n ngOnDestroy(): void {\n this._subscription?.unsubscribe();\n }\n\n getSummary(item: RedmineNewsItem): string {\n return this._truncateText(item.summary || '', 200);\n }\n\n closeDialog(): void {\n this._featureNewsDialogService.close();\n }\n\n private _truncateText(text: string, maxLength: number): string {\n if (!text) {\n return '';\n }\n if (text.length <= maxLength) {\n return text;\n }\n return `${text.slice(0, maxLength)}...`;\n }\n}\n","<div class=\"feature-news-overlay\" *ngIf=\"dialogState\">\n <div class=\"feature-news-dialog\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"feature-news-title\">\n <div class=\"feature-news-header\">\n <div class=\"feature-news-header__main\">\n <div class=\"feature-news-brand\">\n <div class=\"feature-news-title-wrap mt-2\">\n <span id=\"feature-news-title\" class=\"feature-news-chip\">Cập nhật tính năng</span>\n </div>\n </div>\n </div>\n <button type=\"button\" class=\"feature-news-close\" aria-label=\"Dong\" (click)=\"closeDialog()\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n </div>\n\n <div class=\"feature-news-body\">\n <div class=\"feature-news-item\" *ngFor=\"let item of dialogState?.news\">\n <div class=\"feature-news-item-head\">\n <h5 class=\"feature-news-content-label mt-2\">{{ item?.title }}</h5>\n <span class=\"feature-news-item-tag\">Mới nhất</span>\n </div>\n <div class=\"feature-news-content-block\" *ngIf=\"item?.summary\">\n <div class=\"feature-news-content-label mt-2\">Tóm tắt</div>\n <div class=\"feature-news-content-panel\">\n <p class=\"feature-news-item-summary\">{{ getSummary(item) }}</p>\n </div>\n </div>\n <div class=\"feature-news-content-block\" *ngIf=\"item?.description\">\n <div class=\"feature-news-content-label mt-2\">Chi tiết</div>\n <div class=\"feature-news-content-panel feature-news-content-panel--detail\">\n <p class=\"feature-news-item-description\">{{ item?.description }}</p>\n </div>\n </div>\n <div class=\"feature-news-item-meta\">\n <span class=\"feature-news-item-meta__dot\" *ngIf=\"item?.author?.name\" aria-hidden=\"true\"></span>\n <span class=\"feature-news-item-meta__date\">{{\n item?.createdOn | date : 'dd/MM/yyyy'\n }}</span>\n\n </div>\n </div>\n </div>\n\n <div class=\"feature-news-footer\">\n <div class=\"feature-news-footer-note\">\n <span class=\"feature-news-footer-note__icon\" aria-hidden=\"true\"></span>\n Thông báo chỉ hiện khi có tin mới; bạn luôn có thể xem lại từ footer.\n </div>\n <button type=\"button\" class=\"feature-news-confirm-btn\" (click)=\"closeDialog()\">\n Đã hiểu\n </button>\n </div>\n </div>\n</div>","import { CommonModule } from '@angular/common';\r\nimport { NgModule } from '@angular/core';\r\nimport { FeatureNewsDialogComponent } from './feature-news-dialog.component';\r\n\r\n/**\r\n * Import module này ở shell layout (hoặc `AppModule`) để có `<app-feature-news-dialog />`.\r\n * Nhớ cung cấp `EIU_APP_API_BASE_URL` trong providers.\r\n */\r\n@NgModule({\r\n imports: [CommonModule],\r\n declarations: [FeatureNewsDialogComponent],\r\n exports: [FeatureNewsDialogComponent]\r\n})\r\nexport class EiuAppFeatureNewsModule {}\r\n","/*\r\n * EIU App Kit — tái sử dụng giữa các Angular app (feature news Redmine, launcher header, …)\r\n */\r\n\r\nexport * from './lib/eiu-app-kit.tokens';\r\nexport * from './lib/app-launcher/eiu-app-launcher-menu.model';\r\nexport * from './lib/app-launcher/eiu-app-launcher-menu.token';\r\nexport * from './lib/app-launcher/eiu-app-launcher.component';\r\nexport * from './lib/app-launcher/eiu-app-launcher.module';\r\nexport * from './lib/user-menu/eiu-user-menu.model';\r\nexport * from './lib/user-menu/eiu-app-user-menu.component';\r\nexport * from './lib/user-menu/eiu-app-user-menu.module';\r\nexport * from './lib/sidebar-shared/sidebar-shared.model';\r\nexport * from './lib/sidebar-shared/logo/eiu-sidebar-logo.component';\r\nexport * from './lib/sidebar-shared/contact/eiu-contact-support.component';\r\nexport * from './lib/sidebar-shared/eiu-sidebar-shared.module';\r\nexport * from './lib/footer/eiu-app-footer.component';\r\nexport * from './lib/footer/eiu-app-footer.module';\r\nexport * from './lib/feature-news/constants';\r\nexport * from './lib/feature-news/models/operation-result.model';\r\nexport * from './lib/feature-news/models/redmine-news.model';\r\nexport * from './lib/feature-news/news-api.service';\r\nexport * from './lib/feature-news/feature-news-dialog.service';\r\nexport * from './lib/feature-news/feature-news.service';\r\nexport * from './lib/feature-news/feature-news-dialog.component';\r\nexport * from './lib/feature-news/eiu-app-feature-news.module';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1"],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { EventEmitter } from '@angular/core';
2
+ import { EiuUserMenuProfile } from './eiu-user-menu.model';
3
+ import * as i0 from "@angular/core";
4
+ export declare class EiuAppUserMenuComponent {
5
+ private readonly _root;
6
+ /** Thông tin user — host bind từ service token / session. */
7
+ profile: EiuUserMenuProfile | null;
8
+ /** Ảnh mặc định khi `picture` lỗi hoặc trống (đường dẫn trong assets của host). */
9
+ fallbackAvatar: string;
10
+ changePasswordLabel: string;
11
+ logoutLabel: string;
12
+ /** Host xử lý (ví dụ redirect SSO đổi mật khẩu). */
13
+ readonly changePassword: EventEmitter<void>;
14
+ /** Host xử lý (ví dụ Keycloak logout + clear storage). */
15
+ readonly logout: EventEmitter<void>;
16
+ menuOpen: boolean;
17
+ onTriggerClick(event: Event): void;
18
+ onChangePasswordClick(event: Event): void;
19
+ onLogoutClick(event: Event): void;
20
+ onAvatarError(event: Event): void;
21
+ onDocumentClick(event: MouseEvent): void;
22
+ onEscape(): void;
23
+ private _absoluteFallback;
24
+ static ɵfac: i0.ɵɵFactoryDeclaration<EiuAppUserMenuComponent, never>;
25
+ static ɵcmp: i0.ɵɵComponentDeclaration<EiuAppUserMenuComponent, "app-eiu-user-menu", never, { "profile": "profile"; "fallbackAvatar": "fallbackAvatar"; "changePasswordLabel": "changePasswordLabel"; "logoutLabel": "logoutLabel"; }, { "changePassword": "changePassword"; "logout": "logout"; }, never, never, false, never>;
26
+ }
@@ -0,0 +1,12 @@
1
+ import * as i0 from "@angular/core";
2
+ import * as i1 from "./eiu-app-user-menu.component";
3
+ import * as i2 from "@angular/common";
4
+ /**
5
+ * Menu user header (avatar, đổi mật khẩu, đăng xuất).
6
+ * Host cung cấp `[profile]` và xử lý `(changePassword)` / `(logout)`.
7
+ */
8
+ export declare class EiuAppUserMenuModule {
9
+ static ɵfac: i0.ɵɵFactoryDeclaration<EiuAppUserMenuModule, never>;
10
+ static ɵmod: i0.ɵɵNgModuleDeclaration<EiuAppUserMenuModule, [typeof i1.EiuAppUserMenuComponent], [typeof i2.CommonModule], [typeof i1.EiuAppUserMenuComponent]>;
11
+ static ɵinj: i0.ɵɵInjectorDeclaration<EiuAppUserMenuModule>;
12
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Thông tin user hiển thị trên menu (avatar, tên, email).
3
+ * Host map từ token / API của ứng dụng.
4
+ */
5
+ export interface EiuUserMenuProfile {
6
+ /** URL ảnh đại diện (tuỳ chọn). */
7
+ picture?: string | null;
8
+ /** Họ tên hiển thị. */
9
+ fullName: string;
10
+ /** Email (tuỳ chọn). */
11
+ email?: string | null;
12
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eiu-app-kit",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Thư viện Angular dùng chung cho các SPA EIU: app launcher (header), tin Redmine / feature news.",
5
5
  "keywords": [
6
6
  "angular",
package/public-api.d.ts CHANGED
@@ -3,6 +3,9 @@ export * from './lib/app-launcher/eiu-app-launcher-menu.model';
3
3
  export * from './lib/app-launcher/eiu-app-launcher-menu.token';
4
4
  export * from './lib/app-launcher/eiu-app-launcher.component';
5
5
  export * from './lib/app-launcher/eiu-app-launcher.module';
6
+ export * from './lib/user-menu/eiu-user-menu.model';
7
+ export * from './lib/user-menu/eiu-app-user-menu.component';
8
+ export * from './lib/user-menu/eiu-app-user-menu.module';
6
9
  export * from './lib/sidebar-shared/sidebar-shared.model';
7
10
  export * from './lib/sidebar-shared/logo/eiu-sidebar-logo.component';
8
11
  export * from './lib/sidebar-shared/contact/eiu-contact-support.component';