cloud-ide-layout 1.0.22 → 1.0.24
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-G4z9orRq.mjs → cloud-ide-layout-cloud-ide-layout-RD9NYgsO.mjs} +663 -11
- package/fesm2022/cloud-ide-layout-cloud-ide-layout-RD9NYgsO.mjs.map +1 -0
- package/fesm2022/{cloud-ide-layout-drawer-theme.component-B-7FQRAk.mjs → cloud-ide-layout-drawer-theme.component-B4u9LnTe.mjs} +2 -2
- package/fesm2022/{cloud-ide-layout-drawer-theme.component-B-7FQRAk.mjs.map → cloud-ide-layout-drawer-theme.component-B4u9LnTe.mjs.map} +1 -1
- package/fesm2022/{cloud-ide-layout-home-wrapper.component-CRqB9B-k.mjs → cloud-ide-layout-home-wrapper.component-DEec7PZk.mjs} +2 -2
- package/fesm2022/{cloud-ide-layout-home-wrapper.component-CRqB9B-k.mjs.map → cloud-ide-layout-home-wrapper.component-DEec7PZk.mjs.map} +1 -1
- package/fesm2022/{cloud-ide-layout-sidedrawer-notes.component-C5cJd6Nf.mjs → cloud-ide-layout-sidedrawer-notes.component-GT7A-85i.mjs} +2 -2
- package/fesm2022/{cloud-ide-layout-sidedrawer-notes.component-C5cJd6Nf.mjs.map → cloud-ide-layout-sidedrawer-notes.component-GT7A-85i.mjs.map} +1 -1
- package/fesm2022/cloud-ide-layout.mjs +1 -1
- package/index.d.ts +215 -2
- package/package.json +1 -1
- package/fesm2022/cloud-ide-layout-cloud-ide-layout-G4z9orRq.mjs.map +0 -1
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, inject, signal, computed, effect, Component, ElementRef, HostListener, ViewContainerRef, ViewChild, ViewChildren, InjectionToken, PLATFORM_ID } from '@angular/core';
|
|
2
|
+
import { Injectable, inject, signal, computed, effect, Component, ElementRef, HostListener, ViewContainerRef, ViewChild, ViewChildren, InjectionToken, PLATFORM_ID, DestroyRef, Input, Directive } from '@angular/core';
|
|
3
3
|
import { HttpClient } from '@angular/common/http';
|
|
4
|
-
import { cidePath, hostManagerRoutesUrl, coreRoutesUrl, designConfigRoutesUrl } from 'cloud-ide-lms-model';
|
|
4
|
+
import { cidePath, hostManagerRoutesUrl, coreRoutesUrl, commonRoutesUrl, designConfigRoutesUrl } from 'cloud-ide-lms-model';
|
|
5
5
|
import { Observable, throwError, of, BehaviorSubject, interval, take as take$1 } from 'rxjs';
|
|
6
6
|
import { map, filter, tap, catchError, shareReplay, take, distinctUntilChanged } from 'rxjs/operators';
|
|
7
7
|
import * as i2 from '@angular/router';
|
|
8
8
|
import { Router, NavigationEnd, RouteReuseStrategy, RouterModule } from '@angular/router';
|
|
9
9
|
import { Title } from '@angular/platform-browser';
|
|
10
|
-
import { CideEleFileManagerService, CideElementsService, CideInputComponent, CideIconComponent, CideEleResizerDirective, TooltipDirective, CideSpinnerComponent, CideEleSkeletonLoaderComponent } from 'cloud-ide-element';
|
|
10
|
+
import { CideEleFileManagerService, CideElementsService, CideInputComponent, CideIconComponent, CideEleDropdownComponent, CideEleResizerDirective, TooltipDirective, CideSpinnerComponent, CideEleSkeletonLoaderComponent } from 'cloud-ide-element';
|
|
11
11
|
import * as i1 from '@angular/common';
|
|
12
12
|
import { CommonModule, NgClass, NgFor, NgIf, isPlatformBrowser } from '@angular/common';
|
|
13
|
+
import { CloudIdeAuthService, authGuard } from 'cloud-ide-auth';
|
|
13
14
|
import { trigger, state, transition, style, animate } from '@angular/animations';
|
|
14
15
|
import { merge } from 'lodash';
|
|
15
|
-
import {
|
|
16
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
16
17
|
|
|
17
18
|
class CloudIdeLayoutService {
|
|
18
19
|
constructor() { }
|
|
@@ -288,6 +289,7 @@ class AppStateService {
|
|
|
288
289
|
constructor() {
|
|
289
290
|
// Initialize file manager base URL on app startup
|
|
290
291
|
this.fileManagerService.setBaseUrl(cidePath.join([hostManagerRoutesUrl.cideSuiteHost, coreRoutesUrl?.module, coreRoutesUrl?.fileManager]));
|
|
292
|
+
this.fileManagerService.setObjectIdEndpoint(cidePath.join([hostManagerRoutesUrl.cideSuiteHost, commonRoutesUrl?.module, commonRoutesUrl?.generateObjectId]));
|
|
291
293
|
// Load initial state from localStorage
|
|
292
294
|
this.loadFromLocalStorage();
|
|
293
295
|
// Save to localStorage whenever state changes
|
|
@@ -1282,9 +1284,45 @@ class CideLytHeaderWrapperComponent extends CideLytSharedWrapperComponent {
|
|
|
1282
1284
|
sypg_page_code: "cide_lyt_header"
|
|
1283
1285
|
};
|
|
1284
1286
|
syen_photo = {};
|
|
1287
|
+
// More Options Dropdown Configuration
|
|
1288
|
+
moreOptionsItems = [
|
|
1289
|
+
{
|
|
1290
|
+
id: 'settings',
|
|
1291
|
+
label: 'Settings',
|
|
1292
|
+
icon: 'settings',
|
|
1293
|
+
iconColor: 'tw-text-gray-500'
|
|
1294
|
+
},
|
|
1295
|
+
{
|
|
1296
|
+
id: 'help',
|
|
1297
|
+
label: 'Help & Support',
|
|
1298
|
+
icon: 'help',
|
|
1299
|
+
iconColor: 'tw-text-gray-500'
|
|
1300
|
+
},
|
|
1301
|
+
{
|
|
1302
|
+
id: 'divider',
|
|
1303
|
+
label: '',
|
|
1304
|
+
divider: true
|
|
1305
|
+
},
|
|
1306
|
+
{
|
|
1307
|
+
id: 'logout',
|
|
1308
|
+
label: 'Logout',
|
|
1309
|
+
icon: 'logout',
|
|
1310
|
+
iconColor: 'tw-text-red-500',
|
|
1311
|
+
textColor: 'tw-text-red-600',
|
|
1312
|
+
hoverBgColor: 'hover:tw-bg-red-50'
|
|
1313
|
+
}
|
|
1314
|
+
];
|
|
1315
|
+
moreOptionsConfig = {
|
|
1316
|
+
triggerIcon: 'more_vert',
|
|
1317
|
+
triggerSize: 'sm',
|
|
1318
|
+
menuPosition: 'auto',
|
|
1319
|
+
menuWidth: 'tw-w-48',
|
|
1320
|
+
usePortal: true
|
|
1321
|
+
};
|
|
1285
1322
|
headerService = inject(CideLytHeaderService);
|
|
1286
1323
|
fileManagerService = inject(CideLytFileManagerService);
|
|
1287
1324
|
router = inject(Router);
|
|
1325
|
+
authService = inject(CloudIdeAuthService);
|
|
1288
1326
|
constructor() {
|
|
1289
1327
|
super();
|
|
1290
1328
|
}
|
|
@@ -1345,12 +1383,82 @@ class CideLytHeaderWrapperComponent extends CideLytSharedWrapperComponent {
|
|
|
1345
1383
|
}
|
|
1346
1384
|
}
|
|
1347
1385
|
}
|
|
1386
|
+
/**
|
|
1387
|
+
* Handle more options dropdown item clicks
|
|
1388
|
+
* @param item The clicked dropdown item
|
|
1389
|
+
*/
|
|
1390
|
+
onMoreOptionsClick(item) {
|
|
1391
|
+
console.log('🔍 [HeaderComponent] More options clicked:', item);
|
|
1392
|
+
switch (item.id) {
|
|
1393
|
+
case 'settings':
|
|
1394
|
+
this.navigateToSettings();
|
|
1395
|
+
break;
|
|
1396
|
+
case 'help':
|
|
1397
|
+
this.navigateToHelp();
|
|
1398
|
+
break;
|
|
1399
|
+
case 'logout':
|
|
1400
|
+
this.handleLogout();
|
|
1401
|
+
break;
|
|
1402
|
+
default:
|
|
1403
|
+
console.log('🔍 [HeaderComponent] Unknown option:', item.id);
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
/**
|
|
1407
|
+
* Navigate to settings page
|
|
1408
|
+
*/
|
|
1409
|
+
navigateToSettings() {
|
|
1410
|
+
console.log('🔍 [HeaderComponent] Navigating to settings...');
|
|
1411
|
+
// TODO: Implement settings navigation
|
|
1412
|
+
// this.router.navigate(['/settings']);
|
|
1413
|
+
}
|
|
1414
|
+
/**
|
|
1415
|
+
* Navigate to help and support page
|
|
1416
|
+
*/
|
|
1417
|
+
navigateToHelp() {
|
|
1418
|
+
console.log('🔍 [HeaderComponent] Navigating to help...');
|
|
1419
|
+
// TODO: Implement help navigation
|
|
1420
|
+
// this.router.navigate(['/help']);
|
|
1421
|
+
}
|
|
1422
|
+
/**
|
|
1423
|
+
* Handle user logout
|
|
1424
|
+
* Uses the auth service to sign out and navigate to login page
|
|
1425
|
+
*/
|
|
1426
|
+
handleLogout() {
|
|
1427
|
+
console.log('🔍 [HeaderComponent] Logging out user...');
|
|
1428
|
+
// Show confirmation dialog
|
|
1429
|
+
if (confirm('Are you sure you want to logout?')) {
|
|
1430
|
+
try {
|
|
1431
|
+
// Use the auth service to sign out
|
|
1432
|
+
this.authService.signOut();
|
|
1433
|
+
// Navigate to login page
|
|
1434
|
+
this.router.navigate(['/auth/sign-in']).then(success => {
|
|
1435
|
+
if (success) {
|
|
1436
|
+
console.log('✅ [HeaderComponent] Successfully logged out and navigated to login page');
|
|
1437
|
+
}
|
|
1438
|
+
else {
|
|
1439
|
+
console.error('❌ [HeaderComponent] Failed to navigate to login page');
|
|
1440
|
+
// Fallback: reload the page to force navigation
|
|
1441
|
+
window.location.href = '/auth/sign-in';
|
|
1442
|
+
}
|
|
1443
|
+
}).catch(error => {
|
|
1444
|
+
console.error('❌ [HeaderComponent] Navigation error:', error);
|
|
1445
|
+
// Fallback: reload the page to force navigation
|
|
1446
|
+
window.location.href = '/auth/sign-in';
|
|
1447
|
+
});
|
|
1448
|
+
}
|
|
1449
|
+
catch (error) {
|
|
1450
|
+
console.error('❌ [HeaderComponent] Logout error:', error);
|
|
1451
|
+
// Still try to navigate to login page even if logout fails
|
|
1452
|
+
this.router.navigate(['/auth/sign-in']);
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1348
1456
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytHeaderWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1349
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.7", type: CideLytHeaderWrapperComponent, isStandalone: true, selector: "cide-lyt-header-wrapper", usesInheritance: 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=\"header-logo-container tw-cursor-pointer\" \n (click)=\"onLogoClick()\" \n (keydown.enter)=\"onLogoClick()\" \n (keydown.space)=\"onLogoClick()\"\n tabindex=\"0\" \n role=\"button\"\n aria-label=\"Navigate to home\"\n title=\"Click to go to control panel home\">\n <img [src]=\"'data:image/png;base64,' + syen_photo.cyfm_file_base64\"\n [alt]=\"syen_photo.cyfm_alt_text ? syen_photo.cyfm_alt_text : 'Entity Logo'\">\n </div>\n <!-- Search Section -->\n <div class=\"header-search-container\">\n <cide-ele-input id=\"cide_lyt_header_search\" placeholder=\"Search...\" leadingIcon=\"search\" size=\"md\"></cide-ele-input>\n </div>\n \n <!-- Icons Section -->\n <div class=\"header-icons-container\">\n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>dashboard</cide-ele-icon>\n <div class=\"header-tooltip\">Dashboard</div>\n </div>\n \n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>notifications</cide-ele-icon>\n <div class=\"header-badge\">3</div>\n <div class=\"header-tooltip\">Notifications</div>\n </div>\n \n <div class=\"header-divider\"></div>\n \n <div class=\"header-icon user-profile\" (mouseenter)=\"updateTooltipPosition($event)\">\n <div class=\"profile-avatar\">AK</div>\n <div class=\"header-tooltip\">My Account</div>\n </div>\n \n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-
|
|
1457
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.7", type: CideLytHeaderWrapperComponent, isStandalone: true, selector: "cide-lyt-header-wrapper", usesInheritance: 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=\"header-logo-container tw-cursor-pointer\" \n (click)=\"onLogoClick()\" \n (keydown.enter)=\"onLogoClick()\" \n (keydown.space)=\"onLogoClick()\"\n tabindex=\"0\" \n role=\"button\"\n aria-label=\"Navigate to home\"\n title=\"Click to go to control panel home\">\n <img [src]=\"'data:image/png;base64,' + syen_photo.cyfm_file_base64\"\n [alt]=\"syen_photo.cyfm_alt_text ? syen_photo.cyfm_alt_text : 'Entity Logo'\">\n </div>\n <!-- Search Section -->\n <div class=\"header-search-container\">\n <cide-ele-input id=\"cide_lyt_header_search\" placeholder=\"Search...\" leadingIcon=\"search\" size=\"md\"></cide-ele-input>\n </div>\n \n <!-- Icons Section -->\n <div class=\"header-icons-container\">\n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>dashboard</cide-ele-icon>\n <div class=\"header-tooltip\">Dashboard</div>\n </div>\n \n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>notifications</cide-ele-icon>\n <div class=\"header-badge\">3</div>\n <div class=\"header-tooltip\">Notifications</div>\n </div>\n \n <div class=\"header-divider\"></div>\n \n <div class=\"header-icon user-profile\" (mouseenter)=\"updateTooltipPosition($event)\">\n <div class=\"profile-avatar\">AK</div>\n <div class=\"header-tooltip\">My Account</div>\n </div>\n \n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown\n [items]=\"moreOptionsItems\"\n [config]=\"moreOptionsConfig\"\n (itemClick)=\"onMoreOptionsClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">More Options</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-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}.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}.header-icon:hover .profile-avatar{transform:scale(1.08);box-shadow:0 3px 8px #2563eb4d}.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"] }] });
|
|
1350
1458
|
}
|
|
1351
1459
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytHeaderWrapperComponent, decorators: [{
|
|
1352
1460
|
type: Component,
|
|
1353
|
-
args: [{ selector: 'cide-lyt-header-wrapper', standalone: true, imports: [CideInputComponent, CommonModule, CideIconComponent], 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=\"header-logo-container tw-cursor-pointer\" \n (click)=\"onLogoClick()\" \n (keydown.enter)=\"onLogoClick()\" \n (keydown.space)=\"onLogoClick()\"\n tabindex=\"0\" \n role=\"button\"\n aria-label=\"Navigate to home\"\n title=\"Click to go to control panel home\">\n <img [src]=\"'data:image/png;base64,' + syen_photo.cyfm_file_base64\"\n [alt]=\"syen_photo.cyfm_alt_text ? syen_photo.cyfm_alt_text : 'Entity Logo'\">\n </div>\n <!-- Search Section -->\n <div class=\"header-search-container\">\n <cide-ele-input id=\"cide_lyt_header_search\" placeholder=\"Search...\" leadingIcon=\"search\" size=\"md\"></cide-ele-input>\n </div>\n \n <!-- Icons Section -->\n <div class=\"header-icons-container\">\n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>dashboard</cide-ele-icon>\n <div class=\"header-tooltip\">Dashboard</div>\n </div>\n \n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>notifications</cide-ele-icon>\n <div class=\"header-badge\">3</div>\n <div class=\"header-tooltip\">Notifications</div>\n </div>\n \n <div class=\"header-divider\"></div>\n \n <div class=\"header-icon user-profile\" (mouseenter)=\"updateTooltipPosition($event)\">\n <div class=\"profile-avatar\">AK</div>\n <div class=\"header-tooltip\">My Account</div>\n </div>\n \n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-
|
|
1461
|
+
args: [{ selector: 'cide-lyt-header-wrapper', standalone: true, imports: [CideInputComponent, CommonModule, CideIconComponent, CideEleDropdownComponent], 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=\"header-logo-container tw-cursor-pointer\" \n (click)=\"onLogoClick()\" \n (keydown.enter)=\"onLogoClick()\" \n (keydown.space)=\"onLogoClick()\"\n tabindex=\"0\" \n role=\"button\"\n aria-label=\"Navigate to home\"\n title=\"Click to go to control panel home\">\n <img [src]=\"'data:image/png;base64,' + syen_photo.cyfm_file_base64\"\n [alt]=\"syen_photo.cyfm_alt_text ? syen_photo.cyfm_alt_text : 'Entity Logo'\">\n </div>\n <!-- Search Section -->\n <div class=\"header-search-container\">\n <cide-ele-input id=\"cide_lyt_header_search\" placeholder=\"Search...\" leadingIcon=\"search\" size=\"md\"></cide-ele-input>\n </div>\n \n <!-- Icons Section -->\n <div class=\"header-icons-container\">\n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>dashboard</cide-ele-icon>\n <div class=\"header-tooltip\">Dashboard</div>\n </div>\n \n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>notifications</cide-ele-icon>\n <div class=\"header-badge\">3</div>\n <div class=\"header-tooltip\">Notifications</div>\n </div>\n \n <div class=\"header-divider\"></div>\n \n <div class=\"header-icon user-profile\" (mouseenter)=\"updateTooltipPosition($event)\">\n <div class=\"profile-avatar\">AK</div>\n <div class=\"header-tooltip\">My Account</div>\n </div>\n \n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown\n [items]=\"moreOptionsItems\"\n [config]=\"moreOptionsConfig\"\n (itemClick)=\"onMoreOptionsClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">More Options</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-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}.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}.header-icon:hover .profile-avatar{transform:scale(1.08);box-shadow:0 3px 8px #2563eb4d}.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"] }]
|
|
1354
1462
|
}], ctorParameters: () => [] });
|
|
1355
1463
|
|
|
1356
1464
|
class CideLytUserStatusService {
|
|
@@ -2544,8 +2652,8 @@ class CideLytSidedrawerWrapperComponent {
|
|
|
2544
2652
|
}
|
|
2545
2653
|
ngOnInit() {
|
|
2546
2654
|
// Initialize the component map (You'd likely populate this from a config or service)
|
|
2547
|
-
this.componentMap['drowar_notes'] = () => import('./cloud-ide-layout-sidedrawer-notes.component-
|
|
2548
|
-
this.componentMap['drawer_theme'] = () => import('./cloud-ide-layout-drawer-theme.component-
|
|
2655
|
+
this.componentMap['drowar_notes'] = () => import('./cloud-ide-layout-sidedrawer-notes.component-GT7A-85i.mjs').then(m => m.CideLytSidedrawerNotesComponent);
|
|
2656
|
+
this.componentMap['drawer_theme'] = () => import('./cloud-ide-layout-drawer-theme.component-B4u9LnTe.mjs').then(m => m.CideLytDrawerThemeComponent);
|
|
2549
2657
|
}
|
|
2550
2658
|
async loadComponent(configFor) {
|
|
2551
2659
|
console.log('🔍 SIDEDRAWER - Loading component:', configFor, 'Current tab:', this.currentTabId);
|
|
@@ -2917,7 +3025,7 @@ const layoutControlPannelChildRoutes = [{
|
|
|
2917
3025
|
},
|
|
2918
3026
|
{
|
|
2919
3027
|
path: "home",
|
|
2920
|
-
loadComponent: () => import('./cloud-ide-layout-home-wrapper.component-
|
|
3028
|
+
loadComponent: () => import('./cloud-ide-layout-home-wrapper.component-DEec7PZk.mjs').then(c => c.CideLytHomeWrapperComponent),
|
|
2921
3029
|
canActivate: [authGuard],
|
|
2922
3030
|
data: {
|
|
2923
3031
|
reuseTab: true, // For CustomRouteReuseStrategy
|
|
@@ -3174,6 +3282,550 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
3174
3282
|
}]
|
|
3175
3283
|
}] });
|
|
3176
3284
|
|
|
3285
|
+
class CideLytFloatingUploadService {
|
|
3286
|
+
destroyRef = inject(DestroyRef);
|
|
3287
|
+
// Private signals for state management
|
|
3288
|
+
_uploadQueue = signal([], ...(ngDevMode ? [{ debugName: "_uploadQueue" }] : []));
|
|
3289
|
+
_isUploading = signal(false, ...(ngDevMode ? [{ debugName: "_isUploading" }] : []));
|
|
3290
|
+
_uploadProgress = signal(0, ...(ngDevMode ? [{ debugName: "_uploadProgress" }] : []));
|
|
3291
|
+
_isVisible = signal(false, ...(ngDevMode ? [{ debugName: "_isVisible" }] : []));
|
|
3292
|
+
_currentUserId = signal('', ...(ngDevMode ? [{ debugName: "_currentUserId" }] : []));
|
|
3293
|
+
// Public readonly signals
|
|
3294
|
+
uploadQueue = this._uploadQueue.asReadonly();
|
|
3295
|
+
isUploading = this._isUploading.asReadonly();
|
|
3296
|
+
uploadProgress = this._uploadProgress.asReadonly();
|
|
3297
|
+
isVisible = this._isVisible.asReadonly();
|
|
3298
|
+
currentUserId = this._currentUserId.asReadonly();
|
|
3299
|
+
// Computed values
|
|
3300
|
+
hasUploads = computed(() => this._uploadQueue().length > 0, ...(ngDevMode ? [{ debugName: "hasUploads" }] : []));
|
|
3301
|
+
pendingUploads = computed(() => this._uploadQueue().filter(upload => upload.status === 'pending'), ...(ngDevMode ? [{ debugName: "pendingUploads" }] : []));
|
|
3302
|
+
activeUploads = computed(() => this._uploadQueue().filter(upload => upload.status === 'uploading'), ...(ngDevMode ? [{ debugName: "activeUploads" }] : []));
|
|
3303
|
+
completedUploads = computed(() => this._uploadQueue().filter(upload => upload.status === 'completed'), ...(ngDevMode ? [{ debugName: "completedUploads" }] : []));
|
|
3304
|
+
failedUploads = computed(() => this._uploadQueue().filter(upload => upload.status === 'error'), ...(ngDevMode ? [{ debugName: "failedUploads" }] : []));
|
|
3305
|
+
// BehaviorSubjects for external subscriptions
|
|
3306
|
+
uploadQueueSubject = new BehaviorSubject([]);
|
|
3307
|
+
isUploadingSubject = new BehaviorSubject(false);
|
|
3308
|
+
uploadProgressSubject = new BehaviorSubject(0);
|
|
3309
|
+
isVisibleSubject = new BehaviorSubject(false);
|
|
3310
|
+
currentUserIdSubject = new BehaviorSubject('');
|
|
3311
|
+
// Public observables
|
|
3312
|
+
uploadQueue$ = this.uploadQueueSubject.asObservable();
|
|
3313
|
+
isUploading$ = this.isUploadingSubject.asObservable();
|
|
3314
|
+
uploadProgress$ = this.uploadProgressSubject.asObservable();
|
|
3315
|
+
isVisible$ = this.isVisibleSubject.asObservable();
|
|
3316
|
+
currentUserId$ = this.currentUserIdSubject.asObservable();
|
|
3317
|
+
constructor() {
|
|
3318
|
+
console.log('🚀 [FloatingUploadService] Service initialized');
|
|
3319
|
+
}
|
|
3320
|
+
/**
|
|
3321
|
+
* Set the current user ID
|
|
3322
|
+
*/
|
|
3323
|
+
setCurrentUserId(userId) {
|
|
3324
|
+
console.log('👤 [FloatingUploadService] Setting user ID:', userId);
|
|
3325
|
+
this._currentUserId.set(userId);
|
|
3326
|
+
this.currentUserIdSubject.next(userId);
|
|
3327
|
+
}
|
|
3328
|
+
/**
|
|
3329
|
+
* Add files to upload queue
|
|
3330
|
+
*/
|
|
3331
|
+
addFilesToQueue(files) {
|
|
3332
|
+
console.log('📁 [FloatingUploadService] Adding files to queue:', files.length);
|
|
3333
|
+
const newUploads = files.map(file => ({
|
|
3334
|
+
fileId: this.generateFileId(),
|
|
3335
|
+
fileName: file.name,
|
|
3336
|
+
progress: 0,
|
|
3337
|
+
status: 'pending'
|
|
3338
|
+
}));
|
|
3339
|
+
const currentQueue = this._uploadQueue();
|
|
3340
|
+
const updatedQueue = [...currentQueue, ...newUploads];
|
|
3341
|
+
this._uploadQueue.set(updatedQueue);
|
|
3342
|
+
this.uploadQueueSubject.next(updatedQueue);
|
|
3343
|
+
this.updateVisibility();
|
|
3344
|
+
}
|
|
3345
|
+
/**
|
|
3346
|
+
* Update upload status
|
|
3347
|
+
*/
|
|
3348
|
+
updateUploadStatus(fileId, status, progress, error, uploadedFile) {
|
|
3349
|
+
console.log('🔄 [FloatingUploadService] Updating upload status:', fileId, status, progress);
|
|
3350
|
+
const currentQueue = this._uploadQueue();
|
|
3351
|
+
const updatedQueue = currentQueue.map(upload => upload.fileId === fileId
|
|
3352
|
+
? { ...upload, status, progress, error, uploadedFile }
|
|
3353
|
+
: upload);
|
|
3354
|
+
this._uploadQueue.set(updatedQueue);
|
|
3355
|
+
this.uploadQueueSubject.next(updatedQueue);
|
|
3356
|
+
this.updateUploadingState();
|
|
3357
|
+
this.updateVisibility();
|
|
3358
|
+
}
|
|
3359
|
+
/**
|
|
3360
|
+
* Cancel upload
|
|
3361
|
+
*/
|
|
3362
|
+
cancelUpload(fileId) {
|
|
3363
|
+
console.log('🚫 [FloatingUploadService] Cancelling upload:', fileId);
|
|
3364
|
+
this.updateUploadStatus(fileId, 'cancelled', 0);
|
|
3365
|
+
}
|
|
3366
|
+
/**
|
|
3367
|
+
* Remove upload from queue
|
|
3368
|
+
*/
|
|
3369
|
+
removeUpload(fileId) {
|
|
3370
|
+
console.log('🗑️ [FloatingUploadService] Removing upload:', fileId);
|
|
3371
|
+
const currentQueue = this._uploadQueue();
|
|
3372
|
+
const updatedQueue = currentQueue.filter(upload => upload.fileId !== fileId);
|
|
3373
|
+
this._uploadQueue.set(updatedQueue);
|
|
3374
|
+
this.uploadQueueSubject.next(updatedQueue);
|
|
3375
|
+
this.updateUploadingState();
|
|
3376
|
+
this.updateVisibility();
|
|
3377
|
+
}
|
|
3378
|
+
/**
|
|
3379
|
+
* Clear all uploads
|
|
3380
|
+
*/
|
|
3381
|
+
clearAllUploads() {
|
|
3382
|
+
console.log('🧹 [FloatingUploadService] Clearing all uploads');
|
|
3383
|
+
this._uploadQueue.set([]);
|
|
3384
|
+
this.uploadQueueSubject.next([]);
|
|
3385
|
+
this._isUploading.set(false);
|
|
3386
|
+
this.isUploadingSubject.next(false);
|
|
3387
|
+
this._uploadProgress.set(0);
|
|
3388
|
+
this.uploadProgressSubject.next(0);
|
|
3389
|
+
this._isVisible.set(false);
|
|
3390
|
+
this.isVisibleSubject.next(false);
|
|
3391
|
+
}
|
|
3392
|
+
/**
|
|
3393
|
+
* Clear completed uploads
|
|
3394
|
+
*/
|
|
3395
|
+
clearCompletedUploads() {
|
|
3396
|
+
console.log('✅ [FloatingUploadService] Clearing completed uploads');
|
|
3397
|
+
const currentQueue = this._uploadQueue();
|
|
3398
|
+
const updatedQueue = currentQueue.filter(upload => upload.status !== 'completed');
|
|
3399
|
+
this._uploadQueue.set(updatedQueue);
|
|
3400
|
+
this.uploadQueueSubject.next(updatedQueue);
|
|
3401
|
+
this.updateUploadingState();
|
|
3402
|
+
this.updateVisibility();
|
|
3403
|
+
}
|
|
3404
|
+
/**
|
|
3405
|
+
* Handle all uploads complete
|
|
3406
|
+
*/
|
|
3407
|
+
handleAllUploadsComplete(event) {
|
|
3408
|
+
console.log('🎉 [FloatingUploadService] All uploads complete:', event);
|
|
3409
|
+
// Update all pending/uploading files to completed
|
|
3410
|
+
const currentQueue = this._uploadQueue();
|
|
3411
|
+
const updatedQueue = currentQueue.map(upload => {
|
|
3412
|
+
if (upload.status === 'pending' || upload.status === 'uploading') {
|
|
3413
|
+
return { ...upload, status: 'completed', progress: 100 };
|
|
3414
|
+
}
|
|
3415
|
+
return upload;
|
|
3416
|
+
});
|
|
3417
|
+
this._uploadQueue.set(updatedQueue);
|
|
3418
|
+
this.uploadQueueSubject.next(updatedQueue);
|
|
3419
|
+
this.updateUploadingState();
|
|
3420
|
+
}
|
|
3421
|
+
/**
|
|
3422
|
+
* Show the floating uploader
|
|
3423
|
+
*/
|
|
3424
|
+
show() {
|
|
3425
|
+
console.log('👁️ [FloatingUploadService] Showing floating uploader');
|
|
3426
|
+
this._isVisible.set(true);
|
|
3427
|
+
this.isVisibleSubject.next(true);
|
|
3428
|
+
}
|
|
3429
|
+
/**
|
|
3430
|
+
* Hide the floating uploader
|
|
3431
|
+
*/
|
|
3432
|
+
hide() {
|
|
3433
|
+
console.log('🙈 [FloatingUploadService] Hiding floating uploader');
|
|
3434
|
+
this._isVisible.set(false);
|
|
3435
|
+
this.isVisibleSubject.next(false);
|
|
3436
|
+
}
|
|
3437
|
+
/**
|
|
3438
|
+
* Update uploading state based on queue
|
|
3439
|
+
*/
|
|
3440
|
+
updateUploadingState() {
|
|
3441
|
+
const activeUploads = this.activeUploads();
|
|
3442
|
+
const isUploading = activeUploads.length > 0;
|
|
3443
|
+
this._isUploading.set(isUploading);
|
|
3444
|
+
this.isUploadingSubject.next(isUploading);
|
|
3445
|
+
if (isUploading) {
|
|
3446
|
+
const totalProgress = activeUploads.reduce((sum, upload) => sum + upload.progress, 0);
|
|
3447
|
+
const averageProgress = Math.round(totalProgress / activeUploads.length);
|
|
3448
|
+
this._uploadProgress.set(averageProgress);
|
|
3449
|
+
this.uploadProgressSubject.next(averageProgress);
|
|
3450
|
+
}
|
|
3451
|
+
else {
|
|
3452
|
+
this._uploadProgress.set(0);
|
|
3453
|
+
this.uploadProgressSubject.next(0);
|
|
3454
|
+
}
|
|
3455
|
+
}
|
|
3456
|
+
/**
|
|
3457
|
+
* Update visibility based on upload state
|
|
3458
|
+
*/
|
|
3459
|
+
updateVisibility() {
|
|
3460
|
+
const hasActiveUploads = this.activeUploads().length > 0;
|
|
3461
|
+
const hasPendingUploads = this.pendingUploads().length > 0;
|
|
3462
|
+
const hasCompletedUploads = this.completedUploads().length > 0;
|
|
3463
|
+
const hasFailedUploads = this.failedUploads().length > 0;
|
|
3464
|
+
// Show if there are active, pending, or recent completed/failed uploads
|
|
3465
|
+
const shouldShow = hasActiveUploads || hasPendingUploads || hasCompletedUploads || hasFailedUploads;
|
|
3466
|
+
if (shouldShow && !this._isVisible()) {
|
|
3467
|
+
this.show();
|
|
3468
|
+
}
|
|
3469
|
+
else if (!shouldShow && this._isVisible()) {
|
|
3470
|
+
this.hide();
|
|
3471
|
+
}
|
|
3472
|
+
}
|
|
3473
|
+
/**
|
|
3474
|
+
* Generate unique file ID
|
|
3475
|
+
*/
|
|
3476
|
+
generateFileId() {
|
|
3477
|
+
return `upload_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
3478
|
+
}
|
|
3479
|
+
/**
|
|
3480
|
+
* Get upload by ID
|
|
3481
|
+
*/
|
|
3482
|
+
getUploadById(fileId) {
|
|
3483
|
+
return this._uploadQueue().find(upload => upload.fileId === fileId);
|
|
3484
|
+
}
|
|
3485
|
+
/**
|
|
3486
|
+
* Get upload statistics
|
|
3487
|
+
*/
|
|
3488
|
+
getUploadStats() {
|
|
3489
|
+
const queue = this._uploadQueue();
|
|
3490
|
+
return {
|
|
3491
|
+
total: queue.length,
|
|
3492
|
+
pending: queue.filter(u => u.status === 'pending').length,
|
|
3493
|
+
uploading: queue.filter(u => u.status === 'uploading').length,
|
|
3494
|
+
completed: queue.filter(u => u.status === 'completed').length,
|
|
3495
|
+
failed: queue.filter(u => u.status === 'error').length,
|
|
3496
|
+
cancelled: queue.filter(u => u.status === 'cancelled').length
|
|
3497
|
+
};
|
|
3498
|
+
}
|
|
3499
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytFloatingUploadService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3500
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytFloatingUploadService, providedIn: 'root' });
|
|
3501
|
+
}
|
|
3502
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytFloatingUploadService, decorators: [{
|
|
3503
|
+
type: Injectable,
|
|
3504
|
+
args: [{
|
|
3505
|
+
providedIn: 'root'
|
|
3506
|
+
}]
|
|
3507
|
+
}], ctorParameters: () => [] });
|
|
3508
|
+
|
|
3509
|
+
class CideLytFloatingFileUploaderComponent {
|
|
3510
|
+
destroyRef = inject(DestroyRef);
|
|
3511
|
+
floatingUploadService = inject(CideLytFloatingUploadService);
|
|
3512
|
+
// Signals for reactive state
|
|
3513
|
+
isVisible = signal(false, ...(ngDevMode ? [{ debugName: "isVisible" }] : []));
|
|
3514
|
+
isMinimized = signal(false, ...(ngDevMode ? [{ debugName: "isMinimized" }] : []));
|
|
3515
|
+
uploadQueue = signal([], ...(ngDevMode ? [{ debugName: "uploadQueue" }] : []));
|
|
3516
|
+
isUploading = signal(false, ...(ngDevMode ? [{ debugName: "isUploading" }] : []));
|
|
3517
|
+
uploadProgress = signal(0, ...(ngDevMode ? [{ debugName: "uploadProgress" }] : []));
|
|
3518
|
+
currentUserId = signal('', ...(ngDevMode ? [{ debugName: "currentUserId" }] : []));
|
|
3519
|
+
// Computed values
|
|
3520
|
+
hasUploads = computed(() => this.uploadQueue().length > 0, ...(ngDevMode ? [{ debugName: "hasUploads" }] : []));
|
|
3521
|
+
pendingUploads = computed(() => this.uploadQueue().filter(upload => upload.status === 'pending'), ...(ngDevMode ? [{ debugName: "pendingUploads" }] : []));
|
|
3522
|
+
activeUploads = computed(() => this.uploadQueue().filter(upload => upload.status === 'uploading'), ...(ngDevMode ? [{ debugName: "activeUploads" }] : []));
|
|
3523
|
+
completedUploads = computed(() => this.uploadQueue().filter(upload => upload.status === 'completed'), ...(ngDevMode ? [{ debugName: "completedUploads" }] : []));
|
|
3524
|
+
failedUploads = computed(() => this.uploadQueue().filter(upload => upload.status === 'error'), ...(ngDevMode ? [{ debugName: "failedUploads" }] : []));
|
|
3525
|
+
// Animation states
|
|
3526
|
+
isAnimating = signal(false, ...(ngDevMode ? [{ debugName: "isAnimating" }] : []));
|
|
3527
|
+
constructor() {
|
|
3528
|
+
console.log('🚀 [FloatingFileUploader] Component initialized');
|
|
3529
|
+
}
|
|
3530
|
+
ngOnInit() {
|
|
3531
|
+
// Subscribe to upload service state changes
|
|
3532
|
+
this.floatingUploadService.uploadQueue$
|
|
3533
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
3534
|
+
.subscribe(queue => {
|
|
3535
|
+
this.uploadQueue.set(queue);
|
|
3536
|
+
this.updateVisibility();
|
|
3537
|
+
});
|
|
3538
|
+
this.floatingUploadService.isUploading$
|
|
3539
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
3540
|
+
.subscribe(isUploading => {
|
|
3541
|
+
this.isUploading.set(isUploading);
|
|
3542
|
+
});
|
|
3543
|
+
this.floatingUploadService.uploadProgress$
|
|
3544
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
3545
|
+
.subscribe(progress => {
|
|
3546
|
+
this.uploadProgress.set(progress);
|
|
3547
|
+
});
|
|
3548
|
+
this.floatingUploadService.isVisible$
|
|
3549
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
3550
|
+
.subscribe(visible => {
|
|
3551
|
+
this.isVisible.set(visible);
|
|
3552
|
+
});
|
|
3553
|
+
this.floatingUploadService.currentUserId$
|
|
3554
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
3555
|
+
.subscribe(userId => {
|
|
3556
|
+
this.currentUserId.set(userId);
|
|
3557
|
+
});
|
|
3558
|
+
}
|
|
3559
|
+
ngOnDestroy() {
|
|
3560
|
+
console.log('🧹 [FloatingFileUploader] Component destroyed');
|
|
3561
|
+
}
|
|
3562
|
+
/**
|
|
3563
|
+
* Update visibility based on upload state
|
|
3564
|
+
*/
|
|
3565
|
+
updateVisibility() {
|
|
3566
|
+
const hasActiveUploads = this.activeUploads().length > 0;
|
|
3567
|
+
const hasPendingUploads = this.pendingUploads().length > 0;
|
|
3568
|
+
const hasCompletedUploads = this.completedUploads().length > 0;
|
|
3569
|
+
const hasFailedUploads = this.failedUploads().length > 0;
|
|
3570
|
+
// Show if there are active, pending, or recent completed/failed uploads
|
|
3571
|
+
const shouldShow = hasActiveUploads || hasPendingUploads || hasCompletedUploads || hasFailedUploads;
|
|
3572
|
+
if (shouldShow && !this.isVisible()) {
|
|
3573
|
+
this.showWithAnimation();
|
|
3574
|
+
}
|
|
3575
|
+
else if (!shouldShow && this.isVisible()) {
|
|
3576
|
+
this.hideWithAnimation();
|
|
3577
|
+
}
|
|
3578
|
+
}
|
|
3579
|
+
/**
|
|
3580
|
+
* Show with animation
|
|
3581
|
+
*/
|
|
3582
|
+
showWithAnimation() {
|
|
3583
|
+
this.isAnimating.set(true);
|
|
3584
|
+
this.isVisible.set(true);
|
|
3585
|
+
// Remove animation class after animation completes
|
|
3586
|
+
setTimeout(() => {
|
|
3587
|
+
this.isAnimating.set(false);
|
|
3588
|
+
}, 300);
|
|
3589
|
+
}
|
|
3590
|
+
/**
|
|
3591
|
+
* Hide with animation
|
|
3592
|
+
*/
|
|
3593
|
+
hideWithAnimation() {
|
|
3594
|
+
this.isAnimating.set(true);
|
|
3595
|
+
// Wait for animation to complete before hiding
|
|
3596
|
+
setTimeout(() => {
|
|
3597
|
+
this.isVisible.set(false);
|
|
3598
|
+
this.isAnimating.set(false);
|
|
3599
|
+
}, 300);
|
|
3600
|
+
}
|
|
3601
|
+
/**
|
|
3602
|
+
* Toggle minimize state
|
|
3603
|
+
*/
|
|
3604
|
+
toggleMinimize() {
|
|
3605
|
+
this.isMinimized.set(!this.isMinimized());
|
|
3606
|
+
}
|
|
3607
|
+
/**
|
|
3608
|
+
* Close the floating uploader
|
|
3609
|
+
*/
|
|
3610
|
+
close() {
|
|
3611
|
+
this.floatingUploadService.clearAllUploads();
|
|
3612
|
+
this.hideWithAnimation();
|
|
3613
|
+
}
|
|
3614
|
+
/**
|
|
3615
|
+
* Handle file upload completion
|
|
3616
|
+
*/
|
|
3617
|
+
onUploadComplete(event) {
|
|
3618
|
+
console.log('✅ [FloatingFileUploader] Upload completed:', event);
|
|
3619
|
+
this.floatingUploadService.updateUploadStatus(event.fileId, 'completed', 100, undefined, event.uploadedFile);
|
|
3620
|
+
}
|
|
3621
|
+
/**
|
|
3622
|
+
* Handle upload error
|
|
3623
|
+
*/
|
|
3624
|
+
onUploadError(event) {
|
|
3625
|
+
console.error('❌ [FloatingFileUploader] Upload error:', event);
|
|
3626
|
+
this.floatingUploadService.updateUploadStatus(event.fileId, 'error', 0, event.error);
|
|
3627
|
+
}
|
|
3628
|
+
/**
|
|
3629
|
+
* Handle upload cancellation
|
|
3630
|
+
*/
|
|
3631
|
+
onUploadCancelled(fileId) {
|
|
3632
|
+
console.log('🚫 [FloatingFileUploader] Upload cancelled:', fileId);
|
|
3633
|
+
this.floatingUploadService.cancelUpload(fileId);
|
|
3634
|
+
}
|
|
3635
|
+
/**
|
|
3636
|
+
* Handle all uploads complete
|
|
3637
|
+
*/
|
|
3638
|
+
onAllUploadsComplete(event) {
|
|
3639
|
+
console.log('🎉 [FloatingFileUploader] All uploads complete:', event);
|
|
3640
|
+
this.floatingUploadService.handleAllUploadsComplete(event);
|
|
3641
|
+
}
|
|
3642
|
+
/**
|
|
3643
|
+
* Get status icon
|
|
3644
|
+
*/
|
|
3645
|
+
getStatusIcon(status) {
|
|
3646
|
+
switch (status) {
|
|
3647
|
+
case 'pending': return 'schedule';
|
|
3648
|
+
case 'uploading': return 'cloud_upload';
|
|
3649
|
+
case 'completed': return 'check_circle';
|
|
3650
|
+
case 'error': return 'error';
|
|
3651
|
+
case 'cancelled': return 'cancel';
|
|
3652
|
+
default: return 'help';
|
|
3653
|
+
}
|
|
3654
|
+
}
|
|
3655
|
+
/**
|
|
3656
|
+
* Get status class
|
|
3657
|
+
*/
|
|
3658
|
+
getStatusClass(status) {
|
|
3659
|
+
switch (status) {
|
|
3660
|
+
case 'pending': return 'status-pending';
|
|
3661
|
+
case 'uploading': return 'status-uploading';
|
|
3662
|
+
case 'completed': return 'status-completed';
|
|
3663
|
+
case 'error': return 'status-error';
|
|
3664
|
+
case 'cancelled': return 'status-cancelled';
|
|
3665
|
+
default: return 'status-unknown';
|
|
3666
|
+
}
|
|
3667
|
+
}
|
|
3668
|
+
/**
|
|
3669
|
+
* Get file size display
|
|
3670
|
+
*/
|
|
3671
|
+
getFileSizeDisplay(size) {
|
|
3672
|
+
if (size === 0)
|
|
3673
|
+
return '0 Bytes';
|
|
3674
|
+
const k = 1024;
|
|
3675
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
3676
|
+
const i = Math.floor(Math.log(size) / Math.log(k));
|
|
3677
|
+
return parseFloat((size / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
3678
|
+
}
|
|
3679
|
+
/**
|
|
3680
|
+
* Get overall progress percentage
|
|
3681
|
+
*/
|
|
3682
|
+
getOverallProgress() {
|
|
3683
|
+
const uploads = this.uploadQueue();
|
|
3684
|
+
if (uploads.length === 0)
|
|
3685
|
+
return 0;
|
|
3686
|
+
const totalProgress = uploads.reduce((sum, upload) => sum + upload.progress, 0);
|
|
3687
|
+
return Math.round(totalProgress / uploads.length);
|
|
3688
|
+
}
|
|
3689
|
+
/**
|
|
3690
|
+
* Get upload summary text
|
|
3691
|
+
*/
|
|
3692
|
+
getUploadSummary() {
|
|
3693
|
+
const active = this.activeUploads().length;
|
|
3694
|
+
const completed = this.completedUploads().length;
|
|
3695
|
+
const failed = this.failedUploads().length;
|
|
3696
|
+
const pending = this.pendingUploads().length;
|
|
3697
|
+
if (active > 0) {
|
|
3698
|
+
return `${active} uploading`;
|
|
3699
|
+
}
|
|
3700
|
+
else if (completed > 0 && failed === 0) {
|
|
3701
|
+
return `${completed} completed`;
|
|
3702
|
+
}
|
|
3703
|
+
else if (failed > 0) {
|
|
3704
|
+
return `${completed} completed, ${failed} failed`;
|
|
3705
|
+
}
|
|
3706
|
+
else if (pending > 0) {
|
|
3707
|
+
return `${pending} pending`;
|
|
3708
|
+
}
|
|
3709
|
+
return 'No uploads';
|
|
3710
|
+
}
|
|
3711
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytFloatingFileUploaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3712
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideLytFloatingFileUploaderComponent, isStandalone: true, selector: "cide-layout-floating-file-uploader", ngImport: i0, template: "<!-- Floating File Uploader Container -->\n@if (isVisible()) {\n<div class=\"floating-uploader\" \n [class.minimized]=\"isMinimized()\" \n [class.animating]=\"isAnimating()\"\n [class.uploading]=\"isUploading()\">\n\n <!-- Header -->\n <div class=\"uploader-header\">\n <div class=\"header-left\">\n <div class=\"upload-icon\">\n <cide-ele-icon size=\"sm\">cloud_upload</cide-ele-icon>\n </div>\n <div class=\"upload-info\">\n <div class=\"upload-title\">File Upload</div>\n <div class=\"upload-summary\">{{ getUploadSummary() }}</div>\n </div>\n </div>\n \n <div class=\"header-actions\">\n <button class=\"action-btn minimize-btn\" (click)=\"toggleMinimize()\" [title]=\"isMinimized() ? 'Expand' : 'Minimize'\">\n <cide-ele-icon size=\"xs\">{{ isMinimized() ? 'expand_more' : 'expand_less' }}</cide-ele-icon>\n </button>\n <button class=\"action-btn close-btn\" (click)=\"close()\" title=\"Close\">\n <cide-ele-icon size=\"xs\">close</cide-ele-icon>\n </button>\n </div>\n </div>\n\n <!-- Content (hidden when minimized) -->\n @if (!isMinimized()) {\n <div class=\"uploader-content\">\n \n <!-- Overall Progress Bar -->\n @if (isUploading()) {\n <div class=\"overall-progress\">\n <div class=\"progress-bar\">\n <div class=\"progress-fill\" [style.width.%]=\"getOverallProgress()\"></div>\n </div>\n <div class=\"progress-text\">{{ getOverallProgress() }}%</div>\n </div>\n }\n\n <!-- Upload Queue -->\n @if (hasUploads()) {\n <div class=\"upload-queue\">\n @for (upload of uploadQueue(); track upload.fileId) {\n <div class=\"upload-item\" [class]=\"getStatusClass(upload.status)\">\n \n <!-- File Info -->\n <div class=\"file-info\">\n <cide-ele-icon class=\"status-icon\" size=\"xs\">{{ getStatusIcon(upload.status) }}</cide-ele-icon>\n <div class=\"file-details\">\n <div class=\"file-name\">{{ upload.fileName }}</div>\n <div class=\"file-status\">\n @switch (upload.status) {\n @case ('pending') {\n <span class=\"text-yellow-600\">Waiting...</span>\n }\n @case ('uploading') {\n <span class=\"text-blue-600\">Uploading...</span>\n }\n @case ('completed') {\n <span class=\"text-green-600\">Completed</span>\n }\n @case ('error') {\n <span class=\"text-red-600\">{{ upload.error || 'Failed' }}</span>\n }\n @case ('cancelled') {\n <span class=\"text-gray-600\">Cancelled</span>\n }\n }\n </div>\n </div>\n </div>\n\n <!-- Progress Bar (for uploading files) -->\n @if (upload.status === 'uploading') {\n <div class=\"file-progress\">\n <div class=\"progress-bar\">\n <div class=\"progress-fill\" [style.width.%]=\"upload.progress\"></div>\n </div>\n <span class=\"progress-text\">{{ upload.progress }}%</span>\n </div>\n }\n\n <!-- Actions -->\n <div class=\"upload-actions\">\n @switch (upload.status) {\n @case ('pending') {\n <button class=\"action-btn cancel-btn\" (click)=\"onUploadCancelled(upload.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('uploading') {\n <button class=\"action-btn cancel-btn\" (click)=\"onUploadCancelled(upload.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('completed') {\n <button class=\"action-btn success-btn\" title=\"Completed\">\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\n </button>\n }\n @case ('error') {\n <button class=\"action-btn retry-btn\" title=\"Retry\">\n <cide-ele-icon size=\"xs\">refresh</cide-ele-icon>\n </button>\n }\n }\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Hidden file input for drag & drop -->\n <div class=\"hidden-uploader\">\n <input type=\"file\" multiple style=\"display: none;\" id=\"floating-file-input\">\n </div>\n </div>\n }\n\n <!-- Footer (always visible) -->\n <div class=\"uploader-footer\">\n <div class=\"footer-stats\">\n @if (activeUploads().length > 0) {\n <span class=\"stat uploading\">\n <cide-ele-icon size=\"xs\">cloud_upload</cide-ele-icon>\n {{ activeUploads().length }} uploading\n </span>\n }\n @if (completedUploads().length > 0) {\n <span class=\"stat completed\">\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\n {{ completedUploads().length }} completed\n </span>\n }\n @if (failedUploads().length > 0) {\n <span class=\"stat failed\">\n <cide-ele-icon size=\"xs\">error</cide-ele-icon>\n {{ failedUploads().length }} failed\n </span>\n }\n </div>\n </div>\n</div>\n}\n", styles: [".floating-uploader{position:fixed;bottom:20px;right:20px;width:320px;max-height:500px;background:#fff;border-radius:12px;box-shadow:0 8px 32px #0000001f;border:1px solid rgba(0,0,0,.08);z-index:1000;overflow:hidden;transition:all .3s cubic-bezier(.4,0,.2,1);transform:translateY(0);opacity:1}.floating-uploader.animating{transition:all .3s cubic-bezier(.4,0,.2,1)}.floating-uploader.minimized .uploader-content{display:none}.floating-uploader.minimized .uploader-footer{border-top:none}.floating-uploader.uploading{border-color:#3b82f6;box-shadow:0 8px 32px #3b82f626}.floating-uploader .uploader-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:#f8fafc;border-bottom:1px solid #e2e8f0}.floating-uploader .uploader-header .header-left{display:flex;align-items:center;gap:8px}.floating-uploader .uploader-header .header-left .upload-icon{display:flex;align-items:center;justify-content:center;width:24px;height:24px;background:#3b82f6;border-radius:6px;color:#fff}.floating-uploader .uploader-header .header-left .upload-info .upload-title{font-size:14px;font-weight:600;color:#1e293b;margin:0}.floating-uploader .uploader-header .header-left .upload-info .upload-summary{font-size:12px;color:#64748b;margin:0}.floating-uploader .uploader-header .header-actions{display:flex;gap:4px}.floating-uploader .uploader-header .header-actions .action-btn{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:transparent;border-radius:4px;cursor:pointer;transition:background-color .2s;color:#64748b}.floating-uploader .uploader-header .header-actions .action-btn:hover{background:#e2e8f0;color:#1e293b}.floating-uploader .uploader-header .header-actions .action-btn.close-btn:hover{background:#fef2f2;color:#dc2626}.floating-uploader .uploader-content{max-height:400px;overflow-y:auto}.floating-uploader .uploader-content .overall-progress{padding:12px 16px;border-bottom:1px solid #e2e8f0}.floating-uploader .uploader-content .overall-progress .progress-bar{width:100%;height:4px;background:#e2e8f0;border-radius:2px;overflow:hidden;margin-bottom:4px}.floating-uploader .uploader-content .overall-progress .progress-bar .progress-fill{height:100%;background:#3b82f6;transition:width .3s ease}.floating-uploader .uploader-content .overall-progress .progress-text{font-size:12px;color:#64748b;text-align:center;display:block}.floating-uploader .uploader-content .upload-queue .upload-item{display:flex;align-items:center;padding:8px 16px;border-bottom:1px solid #f1f5f9;transition:background-color .2s}.floating-uploader .uploader-content .upload-queue .upload-item:last-child{border-bottom:none}.floating-uploader .uploader-content .upload-queue .upload-item.status-uploading{background:#f0f9ff}.floating-uploader .uploader-content .upload-queue .upload-item.status-completed{background:#f0fdf4}.floating-uploader .uploader-content .upload-queue .upload-item.status-error{background:#fef2f2}.floating-uploader .uploader-content .upload-queue .upload-item .file-info{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .status-icon{flex-shrink:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details{min-width:0;flex:1}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-name{font-size:13px;font-weight:500;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-status{font-size:11px;margin:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-status span{font-weight:500}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress{display:flex;align-items:center;gap:8px;margin:0 8px;min-width:80px}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar{flex:1;height:3px;background:#e2e8f0;border-radius:2px;overflow:hidden}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar .progress-fill{height:100%;background:#3b82f6;transition:width .3s ease}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-text{font-size:10px;color:#64748b;min-width:24px;text-align:right}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions{display:flex;gap:4px}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;border:none;background:transparent;border-radius:4px;cursor:pointer;transition:all .2s;color:#64748b}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn:hover{background:#e2e8f0}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.cancel-btn:hover{background:#fef2f2;color:#dc2626}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.retry-btn:hover{background:#f0f9ff;color:#3b82f6}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.success-btn{color:#16a34a}.floating-uploader .uploader-content .hidden-uploader{display:none}.floating-uploader .uploader-footer{padding:8px 16px;background:#f8fafc;border-top:1px solid #e2e8f0}.floating-uploader .uploader-footer .footer-stats{display:flex;gap:12px;font-size:11px}.floating-uploader .uploader-footer .footer-stats .stat{display:flex;align-items:center;gap:4px;color:#64748b}.floating-uploader .uploader-footer .footer-stats .stat.uploading{color:#3b82f6}.floating-uploader .uploader-footer .footer-stats .stat.completed{color:#16a34a}.floating-uploader .uploader-footer .footer-stats .stat.failed{color:#dc2626}@media (max-width: 640px){.floating-uploader{bottom:10px;right:10px;left:10px;width:auto;max-width:none}}@media (prefers-color-scheme: dark){.floating-uploader{background:#1e293b;border-color:#334155;box-shadow:0 8px 32px #0000004d}.floating-uploader.uploading{border-color:#3b82f6;box-shadow:0 8px 32px #3b82f633}.floating-uploader .uploader-header{background:#334155;border-bottom-color:#475569}.floating-uploader .uploader-header .header-left .upload-icon{background:#3b82f6}.floating-uploader .uploader-header .header-left .upload-info .upload-title{color:#f1f5f9}.floating-uploader .uploader-header .header-left .upload-info .upload-summary,.floating-uploader .uploader-header .header-actions .action-btn{color:#94a3b8}.floating-uploader .uploader-header .header-actions .action-btn:hover{background:#475569;color:#f1f5f9}.floating-uploader .uploader-header .header-actions .action-btn.close-btn:hover{background:#7f1d1d;color:#fca5a5}.floating-uploader .uploader-content .overall-progress{border-bottom-color:#475569}.floating-uploader .uploader-content .overall-progress .progress-bar{background:#475569}.floating-uploader .uploader-content .overall-progress .progress-bar .progress-fill{background:#3b82f6}.floating-uploader .uploader-content .overall-progress .progress-text{color:#94a3b8}.floating-uploader .uploader-content .upload-queue .upload-item{border-bottom-color:#334155}.floating-uploader .uploader-content .upload-queue .upload-item.status-uploading{background:#1e3a8a}.floating-uploader .uploader-content .upload-queue .upload-item.status-completed{background:#14532d}.floating-uploader .uploader-content .upload-queue .upload-item.status-error{background:#7f1d1d}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-name{color:#f1f5f9}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar{background:#475569}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar .progress-fill{background:#3b82f6}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-text,.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn{color:#94a3b8}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn:hover{background:#475569}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.cancel-btn:hover{background:#7f1d1d;color:#fca5a5}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.retry-btn:hover{background:#1e3a8a;color:#60a5fa}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.success-btn{color:#4ade80}.floating-uploader .uploader-footer{background:#334155;border-top-color:#475569}.floating-uploader .uploader-footer .footer-stats .stat{color:#94a3b8}.floating-uploader .uploader-footer .footer-stats .stat.uploading{color:#60a5fa}.floating-uploader .uploader-footer .footer-stats .stat.completed{color:#4ade80}.floating-uploader .uploader-footer .footer-stats .stat.failed{color:#fca5a5}}@keyframes slideInUp{0%{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes slideOutDown{0%{transform:translateY(0);opacity:1}to{transform:translateY(100%);opacity:0}}.floating-uploader.animating{animation:slideInUp .3s cubic-bezier(.4,0,.2,1)}.floating-uploader.animating.hiding{animation:slideOutDown .3s cubic-bezier(.4,0,.2,1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }] });
|
|
3713
|
+
}
|
|
3714
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytFloatingFileUploaderComponent, decorators: [{
|
|
3715
|
+
type: Component,
|
|
3716
|
+
args: [{ selector: 'cide-layout-floating-file-uploader', standalone: true, imports: [
|
|
3717
|
+
CommonModule,
|
|
3718
|
+
CideIconComponent
|
|
3719
|
+
], template: "<!-- Floating File Uploader Container -->\n@if (isVisible()) {\n<div class=\"floating-uploader\" \n [class.minimized]=\"isMinimized()\" \n [class.animating]=\"isAnimating()\"\n [class.uploading]=\"isUploading()\">\n\n <!-- Header -->\n <div class=\"uploader-header\">\n <div class=\"header-left\">\n <div class=\"upload-icon\">\n <cide-ele-icon size=\"sm\">cloud_upload</cide-ele-icon>\n </div>\n <div class=\"upload-info\">\n <div class=\"upload-title\">File Upload</div>\n <div class=\"upload-summary\">{{ getUploadSummary() }}</div>\n </div>\n </div>\n \n <div class=\"header-actions\">\n <button class=\"action-btn minimize-btn\" (click)=\"toggleMinimize()\" [title]=\"isMinimized() ? 'Expand' : 'Minimize'\">\n <cide-ele-icon size=\"xs\">{{ isMinimized() ? 'expand_more' : 'expand_less' }}</cide-ele-icon>\n </button>\n <button class=\"action-btn close-btn\" (click)=\"close()\" title=\"Close\">\n <cide-ele-icon size=\"xs\">close</cide-ele-icon>\n </button>\n </div>\n </div>\n\n <!-- Content (hidden when minimized) -->\n @if (!isMinimized()) {\n <div class=\"uploader-content\">\n \n <!-- Overall Progress Bar -->\n @if (isUploading()) {\n <div class=\"overall-progress\">\n <div class=\"progress-bar\">\n <div class=\"progress-fill\" [style.width.%]=\"getOverallProgress()\"></div>\n </div>\n <div class=\"progress-text\">{{ getOverallProgress() }}%</div>\n </div>\n }\n\n <!-- Upload Queue -->\n @if (hasUploads()) {\n <div class=\"upload-queue\">\n @for (upload of uploadQueue(); track upload.fileId) {\n <div class=\"upload-item\" [class]=\"getStatusClass(upload.status)\">\n \n <!-- File Info -->\n <div class=\"file-info\">\n <cide-ele-icon class=\"status-icon\" size=\"xs\">{{ getStatusIcon(upload.status) }}</cide-ele-icon>\n <div class=\"file-details\">\n <div class=\"file-name\">{{ upload.fileName }}</div>\n <div class=\"file-status\">\n @switch (upload.status) {\n @case ('pending') {\n <span class=\"text-yellow-600\">Waiting...</span>\n }\n @case ('uploading') {\n <span class=\"text-blue-600\">Uploading...</span>\n }\n @case ('completed') {\n <span class=\"text-green-600\">Completed</span>\n }\n @case ('error') {\n <span class=\"text-red-600\">{{ upload.error || 'Failed' }}</span>\n }\n @case ('cancelled') {\n <span class=\"text-gray-600\">Cancelled</span>\n }\n }\n </div>\n </div>\n </div>\n\n <!-- Progress Bar (for uploading files) -->\n @if (upload.status === 'uploading') {\n <div class=\"file-progress\">\n <div class=\"progress-bar\">\n <div class=\"progress-fill\" [style.width.%]=\"upload.progress\"></div>\n </div>\n <span class=\"progress-text\">{{ upload.progress }}%</span>\n </div>\n }\n\n <!-- Actions -->\n <div class=\"upload-actions\">\n @switch (upload.status) {\n @case ('pending') {\n <button class=\"action-btn cancel-btn\" (click)=\"onUploadCancelled(upload.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('uploading') {\n <button class=\"action-btn cancel-btn\" (click)=\"onUploadCancelled(upload.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('completed') {\n <button class=\"action-btn success-btn\" title=\"Completed\">\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\n </button>\n }\n @case ('error') {\n <button class=\"action-btn retry-btn\" title=\"Retry\">\n <cide-ele-icon size=\"xs\">refresh</cide-ele-icon>\n </button>\n }\n }\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Hidden file input for drag & drop -->\n <div class=\"hidden-uploader\">\n <input type=\"file\" multiple style=\"display: none;\" id=\"floating-file-input\">\n </div>\n </div>\n }\n\n <!-- Footer (always visible) -->\n <div class=\"uploader-footer\">\n <div class=\"footer-stats\">\n @if (activeUploads().length > 0) {\n <span class=\"stat uploading\">\n <cide-ele-icon size=\"xs\">cloud_upload</cide-ele-icon>\n {{ activeUploads().length }} uploading\n </span>\n }\n @if (completedUploads().length > 0) {\n <span class=\"stat completed\">\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\n {{ completedUploads().length }} completed\n </span>\n }\n @if (failedUploads().length > 0) {\n <span class=\"stat failed\">\n <cide-ele-icon size=\"xs\">error</cide-ele-icon>\n {{ failedUploads().length }} failed\n </span>\n }\n </div>\n </div>\n</div>\n}\n", styles: [".floating-uploader{position:fixed;bottom:20px;right:20px;width:320px;max-height:500px;background:#fff;border-radius:12px;box-shadow:0 8px 32px #0000001f;border:1px solid rgba(0,0,0,.08);z-index:1000;overflow:hidden;transition:all .3s cubic-bezier(.4,0,.2,1);transform:translateY(0);opacity:1}.floating-uploader.animating{transition:all .3s cubic-bezier(.4,0,.2,1)}.floating-uploader.minimized .uploader-content{display:none}.floating-uploader.minimized .uploader-footer{border-top:none}.floating-uploader.uploading{border-color:#3b82f6;box-shadow:0 8px 32px #3b82f626}.floating-uploader .uploader-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:#f8fafc;border-bottom:1px solid #e2e8f0}.floating-uploader .uploader-header .header-left{display:flex;align-items:center;gap:8px}.floating-uploader .uploader-header .header-left .upload-icon{display:flex;align-items:center;justify-content:center;width:24px;height:24px;background:#3b82f6;border-radius:6px;color:#fff}.floating-uploader .uploader-header .header-left .upload-info .upload-title{font-size:14px;font-weight:600;color:#1e293b;margin:0}.floating-uploader .uploader-header .header-left .upload-info .upload-summary{font-size:12px;color:#64748b;margin:0}.floating-uploader .uploader-header .header-actions{display:flex;gap:4px}.floating-uploader .uploader-header .header-actions .action-btn{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:transparent;border-radius:4px;cursor:pointer;transition:background-color .2s;color:#64748b}.floating-uploader .uploader-header .header-actions .action-btn:hover{background:#e2e8f0;color:#1e293b}.floating-uploader .uploader-header .header-actions .action-btn.close-btn:hover{background:#fef2f2;color:#dc2626}.floating-uploader .uploader-content{max-height:400px;overflow-y:auto}.floating-uploader .uploader-content .overall-progress{padding:12px 16px;border-bottom:1px solid #e2e8f0}.floating-uploader .uploader-content .overall-progress .progress-bar{width:100%;height:4px;background:#e2e8f0;border-radius:2px;overflow:hidden;margin-bottom:4px}.floating-uploader .uploader-content .overall-progress .progress-bar .progress-fill{height:100%;background:#3b82f6;transition:width .3s ease}.floating-uploader .uploader-content .overall-progress .progress-text{font-size:12px;color:#64748b;text-align:center;display:block}.floating-uploader .uploader-content .upload-queue .upload-item{display:flex;align-items:center;padding:8px 16px;border-bottom:1px solid #f1f5f9;transition:background-color .2s}.floating-uploader .uploader-content .upload-queue .upload-item:last-child{border-bottom:none}.floating-uploader .uploader-content .upload-queue .upload-item.status-uploading{background:#f0f9ff}.floating-uploader .uploader-content .upload-queue .upload-item.status-completed{background:#f0fdf4}.floating-uploader .uploader-content .upload-queue .upload-item.status-error{background:#fef2f2}.floating-uploader .uploader-content .upload-queue .upload-item .file-info{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .status-icon{flex-shrink:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details{min-width:0;flex:1}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-name{font-size:13px;font-weight:500;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-status{font-size:11px;margin:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-status span{font-weight:500}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress{display:flex;align-items:center;gap:8px;margin:0 8px;min-width:80px}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar{flex:1;height:3px;background:#e2e8f0;border-radius:2px;overflow:hidden}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar .progress-fill{height:100%;background:#3b82f6;transition:width .3s ease}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-text{font-size:10px;color:#64748b;min-width:24px;text-align:right}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions{display:flex;gap:4px}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;border:none;background:transparent;border-radius:4px;cursor:pointer;transition:all .2s;color:#64748b}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn:hover{background:#e2e8f0}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.cancel-btn:hover{background:#fef2f2;color:#dc2626}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.retry-btn:hover{background:#f0f9ff;color:#3b82f6}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.success-btn{color:#16a34a}.floating-uploader .uploader-content .hidden-uploader{display:none}.floating-uploader .uploader-footer{padding:8px 16px;background:#f8fafc;border-top:1px solid #e2e8f0}.floating-uploader .uploader-footer .footer-stats{display:flex;gap:12px;font-size:11px}.floating-uploader .uploader-footer .footer-stats .stat{display:flex;align-items:center;gap:4px;color:#64748b}.floating-uploader .uploader-footer .footer-stats .stat.uploading{color:#3b82f6}.floating-uploader .uploader-footer .footer-stats .stat.completed{color:#16a34a}.floating-uploader .uploader-footer .footer-stats .stat.failed{color:#dc2626}@media (max-width: 640px){.floating-uploader{bottom:10px;right:10px;left:10px;width:auto;max-width:none}}@media (prefers-color-scheme: dark){.floating-uploader{background:#1e293b;border-color:#334155;box-shadow:0 8px 32px #0000004d}.floating-uploader.uploading{border-color:#3b82f6;box-shadow:0 8px 32px #3b82f633}.floating-uploader .uploader-header{background:#334155;border-bottom-color:#475569}.floating-uploader .uploader-header .header-left .upload-icon{background:#3b82f6}.floating-uploader .uploader-header .header-left .upload-info .upload-title{color:#f1f5f9}.floating-uploader .uploader-header .header-left .upload-info .upload-summary,.floating-uploader .uploader-header .header-actions .action-btn{color:#94a3b8}.floating-uploader .uploader-header .header-actions .action-btn:hover{background:#475569;color:#f1f5f9}.floating-uploader .uploader-header .header-actions .action-btn.close-btn:hover{background:#7f1d1d;color:#fca5a5}.floating-uploader .uploader-content .overall-progress{border-bottom-color:#475569}.floating-uploader .uploader-content .overall-progress .progress-bar{background:#475569}.floating-uploader .uploader-content .overall-progress .progress-bar .progress-fill{background:#3b82f6}.floating-uploader .uploader-content .overall-progress .progress-text{color:#94a3b8}.floating-uploader .uploader-content .upload-queue .upload-item{border-bottom-color:#334155}.floating-uploader .uploader-content .upload-queue .upload-item.status-uploading{background:#1e3a8a}.floating-uploader .uploader-content .upload-queue .upload-item.status-completed{background:#14532d}.floating-uploader .uploader-content .upload-queue .upload-item.status-error{background:#7f1d1d}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-name{color:#f1f5f9}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar{background:#475569}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar .progress-fill{background:#3b82f6}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-text,.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn{color:#94a3b8}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn:hover{background:#475569}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.cancel-btn:hover{background:#7f1d1d;color:#fca5a5}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.retry-btn:hover{background:#1e3a8a;color:#60a5fa}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.success-btn{color:#4ade80}.floating-uploader .uploader-footer{background:#334155;border-top-color:#475569}.floating-uploader .uploader-footer .footer-stats .stat{color:#94a3b8}.floating-uploader .uploader-footer .footer-stats .stat.uploading{color:#60a5fa}.floating-uploader .uploader-footer .footer-stats .stat.completed{color:#4ade80}.floating-uploader .uploader-footer .footer-stats .stat.failed{color:#fca5a5}}@keyframes slideInUp{0%{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes slideOutDown{0%{transform:translateY(0);opacity:1}to{transform:translateY(100%);opacity:0}}.floating-uploader.animating{animation:slideInUp .3s cubic-bezier(.4,0,.2,1)}.floating-uploader.animating.hiding{animation:slideOutDown .3s cubic-bezier(.4,0,.2,1)}\n"] }]
|
|
3720
|
+
}], ctorParameters: () => [] });
|
|
3721
|
+
|
|
3722
|
+
class CideLytLayoutWithFloatingUploaderComponent {
|
|
3723
|
+
destroyRef = inject(DestroyRef);
|
|
3724
|
+
floatingUploadService = inject(CideLytFloatingUploadService);
|
|
3725
|
+
// Signals for reactive state
|
|
3726
|
+
isVisible = signal(false, ...(ngDevMode ? [{ debugName: "isVisible" }] : []));
|
|
3727
|
+
uploadCount = signal(0, ...(ngDevMode ? [{ debugName: "uploadCount" }] : []));
|
|
3728
|
+
// Computed values
|
|
3729
|
+
hasUploads = computed(() => this.uploadCount() > 0, ...(ngDevMode ? [{ debugName: "hasUploads" }] : []));
|
|
3730
|
+
constructor() {
|
|
3731
|
+
console.log('🚀 [LayoutWithFloatingUploader] Component initialized');
|
|
3732
|
+
}
|
|
3733
|
+
ngOnInit() {
|
|
3734
|
+
// Subscribe to floating upload service state
|
|
3735
|
+
this.floatingUploadService.isVisible$
|
|
3736
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
3737
|
+
.subscribe(visible => {
|
|
3738
|
+
this.isVisible.set(visible);
|
|
3739
|
+
});
|
|
3740
|
+
this.floatingUploadService.uploadQueue$
|
|
3741
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
3742
|
+
.subscribe(queue => {
|
|
3743
|
+
this.uploadCount.set(queue.length);
|
|
3744
|
+
});
|
|
3745
|
+
}
|
|
3746
|
+
ngOnDestroy() {
|
|
3747
|
+
console.log('🧹 [LayoutWithFloatingUploader] Component destroyed');
|
|
3748
|
+
}
|
|
3749
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytLayoutWithFloatingUploaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3750
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.7", type: CideLytLayoutWithFloatingUploaderComponent, isStandalone: true, selector: "cide-layout-with-floating-uploader", ngImport: i0, template: "<!-- Layout with Floating Uploader -->\r\n<div class=\"layout-container\">\r\n <!-- Main Content Slot -->\r\n <ng-content></ng-content>\r\n \r\n <!-- Floating File Uploader -->\r\n <cide-layout-floating-file-uploader></cide-layout-floating-file-uploader>\r\n</div>\r\n\r\n", styles: [".layout-container{position:relative;width:100%;height:100%;min-height:100vh}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: CideLytFloatingFileUploaderComponent, selector: "cide-layout-floating-file-uploader" }] });
|
|
3751
|
+
}
|
|
3752
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytLayoutWithFloatingUploaderComponent, decorators: [{
|
|
3753
|
+
type: Component,
|
|
3754
|
+
args: [{ selector: 'cide-layout-with-floating-uploader', standalone: true, imports: [
|
|
3755
|
+
CommonModule,
|
|
3756
|
+
CideLytFloatingFileUploaderComponent
|
|
3757
|
+
], template: "<!-- Layout with Floating Uploader -->\r\n<div class=\"layout-container\">\r\n <!-- Main Content Slot -->\r\n <ng-content></ng-content>\r\n \r\n <!-- Floating File Uploader -->\r\n <cide-layout-floating-file-uploader></cide-layout-floating-file-uploader>\r\n</div>\r\n\r\n", styles: [".layout-container{position:relative;width:100%;height:100%;min-height:100vh}\n"] }]
|
|
3758
|
+
}], ctorParameters: () => [] });
|
|
3759
|
+
|
|
3760
|
+
class CideLytFloatingUploadTriggerDirective {
|
|
3761
|
+
elementRef = inject(ElementRef);
|
|
3762
|
+
floatingUploadService = inject(CideLytFloatingUploadService);
|
|
3763
|
+
userId = '';
|
|
3764
|
+
constructor() {
|
|
3765
|
+
console.log('🎯 [FloatingUploadTrigger] Directive initialized');
|
|
3766
|
+
}
|
|
3767
|
+
onFileChange(event) {
|
|
3768
|
+
const input = event.target;
|
|
3769
|
+
const files = input.files;
|
|
3770
|
+
if (files && files.length > 0) {
|
|
3771
|
+
console.log('📁 [FloatingUploadTrigger] Files selected:', files.length);
|
|
3772
|
+
// Set user ID if provided
|
|
3773
|
+
if (this.userId) {
|
|
3774
|
+
this.floatingUploadService.setCurrentUserId(this.userId);
|
|
3775
|
+
}
|
|
3776
|
+
// Add files to floating uploader queue
|
|
3777
|
+
this.floatingUploadService.addFilesToQueue(Array.from(files));
|
|
3778
|
+
// Reset the input to allow selecting the same files again
|
|
3779
|
+
input.value = '';
|
|
3780
|
+
}
|
|
3781
|
+
}
|
|
3782
|
+
onDragOver(event) {
|
|
3783
|
+
event.preventDefault();
|
|
3784
|
+
event.stopPropagation();
|
|
3785
|
+
}
|
|
3786
|
+
onDragEnter(event) {
|
|
3787
|
+
event.preventDefault();
|
|
3788
|
+
event.stopPropagation();
|
|
3789
|
+
}
|
|
3790
|
+
onDrop(event) {
|
|
3791
|
+
event.preventDefault();
|
|
3792
|
+
event.stopPropagation();
|
|
3793
|
+
const files = event.dataTransfer?.files;
|
|
3794
|
+
if (files && files.length > 0) {
|
|
3795
|
+
console.log('📁 [FloatingUploadTrigger] Files dropped:', files.length);
|
|
3796
|
+
// Set user ID if provided
|
|
3797
|
+
if (this.userId) {
|
|
3798
|
+
this.floatingUploadService.setCurrentUserId(this.userId);
|
|
3799
|
+
}
|
|
3800
|
+
// Add files to floating uploader queue
|
|
3801
|
+
this.floatingUploadService.addFilesToQueue(Array.from(files));
|
|
3802
|
+
}
|
|
3803
|
+
}
|
|
3804
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytFloatingUploadTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
3805
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.7", type: CideLytFloatingUploadTriggerDirective, isStandalone: true, selector: "[cideFloatingUploadTrigger]", inputs: { userId: "userId" }, host: { listeners: { "change": "onFileChange($event)", "dragover": "onDragOver($event)", "dragenter": "onDragEnter($event)", "drop": "onDrop($event)" } }, ngImport: i0 });
|
|
3806
|
+
}
|
|
3807
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytFloatingUploadTriggerDirective, decorators: [{
|
|
3808
|
+
type: Directive,
|
|
3809
|
+
args: [{
|
|
3810
|
+
selector: '[cideFloatingUploadTrigger]',
|
|
3811
|
+
standalone: true
|
|
3812
|
+
}]
|
|
3813
|
+
}], ctorParameters: () => [], propDecorators: { userId: [{
|
|
3814
|
+
type: Input
|
|
3815
|
+
}], onFileChange: [{
|
|
3816
|
+
type: HostListener,
|
|
3817
|
+
args: ['change', ['$event']]
|
|
3818
|
+
}], onDragOver: [{
|
|
3819
|
+
type: HostListener,
|
|
3820
|
+
args: ['dragover', ['$event']]
|
|
3821
|
+
}], onDragEnter: [{
|
|
3822
|
+
type: HostListener,
|
|
3823
|
+
args: ['dragenter', ['$event']]
|
|
3824
|
+
}], onDrop: [{
|
|
3825
|
+
type: HostListener,
|
|
3826
|
+
args: ['drop', ['$event']]
|
|
3827
|
+
}] } });
|
|
3828
|
+
|
|
3177
3829
|
/*
|
|
3178
3830
|
* Public API Surface of cloud-ide-layout
|
|
3179
3831
|
*/
|
|
@@ -3182,5 +3834,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
3182
3834
|
* Generated bundle index. Do not edit.
|
|
3183
3835
|
*/
|
|
3184
3836
|
|
|
3185
|
-
export { AppStateHelperService as A, CideLytSharedWrapperComponent as C, ENVIRONMENT_CONFIG as E, CideLytSidebarService as a, CideLytRequestService as b, CideLytSidedrawerService as c, CideLytThemeService as d, CloudIdeLayoutService as e, CloudIdeLayoutComponent as f, CideLytSharedService as g, layoutControlPannelChildRoutes as h, CustomRouteReuseStrategy as i, AppStateService as j, CideLytUserStatusService as k, layoutRoutes as l, CacheManagerService as m, CideLytFileManagerService as n, processThemeVariable as p, setCSSVariable as s, themeFactory as t };
|
|
3186
|
-
//# sourceMappingURL=cloud-ide-layout-cloud-ide-layout-
|
|
3837
|
+
export { AppStateHelperService as A, CideLytSharedWrapperComponent as C, ENVIRONMENT_CONFIG as E, CideLytSidebarService as a, CideLytRequestService as b, CideLytSidedrawerService as c, CideLytThemeService as d, CloudIdeLayoutService as e, CloudIdeLayoutComponent as f, CideLytSharedService as g, layoutControlPannelChildRoutes as h, CustomRouteReuseStrategy as i, AppStateService as j, CideLytUserStatusService as k, layoutRoutes as l, CacheManagerService as m, CideLytFileManagerService as n, CideLytFloatingFileUploaderComponent as o, processThemeVariable as p, CideLytLayoutWithFloatingUploaderComponent as q, CideLytFloatingUploadService as r, setCSSVariable as s, themeFactory as t, CideLytFloatingUploadTriggerDirective as u };
|
|
3838
|
+
//# sourceMappingURL=cloud-ide-layout-cloud-ide-layout-RD9NYgsO.mjs.map
|