@design.estate/dees-catalog 3.49.2 → 3.50.2
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/dist_bundle/bundle.js +360 -56
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/00group-chart/dees-chart-area/component.js +24 -9
- package/dist_ts_web/elements/00group-chart/dees-chart-area/demo.js +22 -44
- package/dist_ts_web/elements/00group-chart/dees-chart-log/dees-chart-log.demo.js +2 -2
- package/dist_ts_web/elements/00group-layout/dees-dashboardgrid/dees-dashboardgrid.demo.js +3 -3
- package/dist_ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.d.ts +25 -0
- package/dist_ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.demo.js +39 -1
- package/dist_ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.js +284 -6
- package/dist_ts_web/elements/00group-workspace/dees-workspace-terminal/dees-workspace-terminal.d.ts +1 -1
- package/dist_ts_web/elements/00group-workspace/dees-workspace-terminal/dees-workspace-terminal.js +4 -4
- package/dist_watch/bundle.js +358 -54
- package/dist_watch/bundle.js.map +3 -3
- package/package.json +1 -1
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/00group-chart/dees-chart-area/component.ts +29 -13
- package/ts_web/elements/00group-chart/dees-chart-area/demo.ts +22 -44
- package/ts_web/elements/00group-chart/dees-chart-log/dees-chart-log.demo.ts +1 -1
- package/ts_web/elements/00group-layout/dees-dashboardgrid/dees-dashboardgrid.demo.ts +2 -2
- package/ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.demo.ts +39 -1
- package/ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.ts +296 -3
- package/ts_web/elements/00group-workspace/dees-workspace-terminal/dees-workspace-terminal.ts +4 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@design.estate/dees-catalog",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.50.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.",
|
|
6
6
|
"main": "dist_ts_web/index.js",
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@design.estate/dees-catalog',
|
|
6
|
-
version: '3.
|
|
6
|
+
version: '3.50.2',
|
|
7
7
|
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
|
|
8
8
|
}
|
|
@@ -468,16 +468,16 @@ export class DeesChartArea extends DeesElement {
|
|
|
468
468
|
if (!this.chart) {
|
|
469
469
|
return;
|
|
470
470
|
}
|
|
471
|
-
|
|
471
|
+
|
|
472
472
|
try {
|
|
473
473
|
// Store the new data first
|
|
474
474
|
this.internalChartData = newSeries;
|
|
475
|
-
|
|
475
|
+
|
|
476
476
|
// Handle rolling window if enabled
|
|
477
477
|
if (this.rollingWindow > 0 && this.realtimeMode) {
|
|
478
478
|
const now = Date.now();
|
|
479
479
|
const cutoffTime = now - this.rollingWindow;
|
|
480
|
-
|
|
480
|
+
|
|
481
481
|
// Filter data to only include points within the rolling window
|
|
482
482
|
const filteredSeries = newSeries.map(series => ({
|
|
483
483
|
name: series.name,
|
|
@@ -488,25 +488,41 @@ export class DeesChartArea extends DeesElement {
|
|
|
488
488
|
return false;
|
|
489
489
|
})
|
|
490
490
|
}));
|
|
491
|
-
|
|
491
|
+
|
|
492
492
|
// Only update if we have data
|
|
493
493
|
if (filteredSeries.some(s => s.data.length > 0)) {
|
|
494
|
-
//
|
|
494
|
+
// Build a single options update with series, x-axis window, and y-axis
|
|
495
|
+
const isDark = !this.goBright;
|
|
496
|
+
const options: ApexCharts.ApexOptions = {
|
|
497
|
+
series: filteredSeries,
|
|
498
|
+
xaxis: {
|
|
499
|
+
min: cutoffTime,
|
|
500
|
+
max: now,
|
|
501
|
+
labels: {
|
|
502
|
+
format: 'HH:mm:ss',
|
|
503
|
+
datetimeUTC: false,
|
|
504
|
+
style: {
|
|
505
|
+
colors: [isDark ? 'hsl(0 0% 63.9%)' : 'hsl(0 0% 20%)'],
|
|
506
|
+
fontSize: '12px',
|
|
507
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
508
|
+
fontWeight: '400',
|
|
509
|
+
},
|
|
510
|
+
},
|
|
511
|
+
tickAmount: 6,
|
|
512
|
+
},
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
// Handle y-axis scaling
|
|
495
516
|
if (this.yAxisScaling === 'dynamic') {
|
|
496
517
|
const allValues = filteredSeries.flatMap(s => (s.data as any[]).map(d => d.y));
|
|
497
518
|
if (allValues.length > 0) {
|
|
498
519
|
const maxValue = Math.max(...allValues);
|
|
499
520
|
const dynamicMax = Math.ceil(maxValue * 1.1);
|
|
500
|
-
|
|
501
|
-
yaxis: {
|
|
502
|
-
min: 0,
|
|
503
|
-
max: dynamicMax
|
|
504
|
-
}
|
|
505
|
-
}, false, false);
|
|
521
|
+
options.yaxis = { min: 0, max: dynamicMax };
|
|
506
522
|
}
|
|
507
523
|
}
|
|
508
|
-
|
|
509
|
-
await this.chart.
|
|
524
|
+
|
|
525
|
+
await this.chart.updateOptions(options, false, false);
|
|
510
526
|
}
|
|
511
527
|
} else {
|
|
512
528
|
await this.chart.updateSeries(newSeries, animate);
|
|
@@ -310,16 +310,31 @@ export const demoFunc = () => {
|
|
|
310
310
|
connectionsLastUpdate = 0;
|
|
311
311
|
};
|
|
312
312
|
|
|
313
|
+
// Update button states based on current dataset
|
|
314
|
+
const updateButtonStates = () => {
|
|
315
|
+
const allButtons = elementArg.querySelectorAll('dees-button');
|
|
316
|
+
allButtons.forEach((button: any) => {
|
|
317
|
+
const text = button.text?.trim();
|
|
318
|
+
if (text === 'System Usage') {
|
|
319
|
+
button.type = currentDataset === 'system' ? 'highlighted' : 'normal';
|
|
320
|
+
} else if (text === 'Network Traffic') {
|
|
321
|
+
button.type = currentDataset === 'network' ? 'highlighted' : 'normal';
|
|
322
|
+
} else if (text === 'Sales Data') {
|
|
323
|
+
button.type = currentDataset === 'sales' ? 'highlighted' : 'normal';
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
};
|
|
327
|
+
|
|
313
328
|
// Wire up button click handlers
|
|
314
329
|
const buttons = elementArg.querySelectorAll('dees-button');
|
|
315
|
-
buttons.forEach(button => {
|
|
316
|
-
const text = button.
|
|
330
|
+
buttons.forEach((button: any) => {
|
|
331
|
+
const text = button.text?.trim();
|
|
317
332
|
if (text === 'System Usage') {
|
|
318
|
-
button.addEventListener('click', () => switchDataset('system'));
|
|
333
|
+
button.addEventListener('click', () => { switchDataset('system'); updateButtonStates(); });
|
|
319
334
|
} else if (text === 'Network Traffic') {
|
|
320
|
-
button.addEventListener('click', () => switchDataset('network'));
|
|
335
|
+
button.addEventListener('click', () => { switchDataset('network'); updateButtonStates(); });
|
|
321
336
|
} else if (text === 'Sales Data') {
|
|
322
|
-
button.addEventListener('click', () => switchDataset('sales'));
|
|
337
|
+
button.addEventListener('click', () => { switchDataset('sales'); updateButtonStates(); });
|
|
323
338
|
} else if (text === 'Start Live') {
|
|
324
339
|
button.addEventListener('click', () => startRealtime());
|
|
325
340
|
} else if (text === 'Stop Live') {
|
|
@@ -328,56 +343,19 @@ export const demoFunc = () => {
|
|
|
328
343
|
button.addEventListener('click', () => randomizeData());
|
|
329
344
|
}
|
|
330
345
|
});
|
|
331
|
-
|
|
332
|
-
// Update button states based on current dataset
|
|
333
|
-
const updateButtonStates = () => {
|
|
334
|
-
const buttons = elementArg.querySelectorAll('dees-button');
|
|
335
|
-
buttons.forEach(button => {
|
|
336
|
-
const text = button.textContent?.trim();
|
|
337
|
-
if (text === 'System Usage') {
|
|
338
|
-
button.type = currentDataset === 'system' ? 'highlighted' : 'normal';
|
|
339
|
-
} else if (text === 'Network Traffic') {
|
|
340
|
-
button.type = currentDataset === 'network' ? 'highlighted' : 'normal';
|
|
341
|
-
} else if (text === 'Sales Data') {
|
|
342
|
-
button.type = currentDataset === 'sales' ? 'highlighted' : 'normal';
|
|
343
|
-
}
|
|
344
|
-
});
|
|
345
|
-
};
|
|
346
|
-
|
|
346
|
+
|
|
347
347
|
// Configure main chart with rolling window
|
|
348
348
|
chartElement.rollingWindow = TIME_WINDOW;
|
|
349
349
|
chartElement.realtimeMode = false; // Will be enabled when starting live updates
|
|
350
350
|
chartElement.yAxisScaling = 'percentage'; // Initial system dataset uses percentage
|
|
351
351
|
chartElement.yAxisMax = 100;
|
|
352
352
|
chartElement.autoScrollInterval = 1000; // Auto-scroll every second
|
|
353
|
-
|
|
353
|
+
|
|
354
354
|
// Set initial time window
|
|
355
355
|
setTimeout(() => {
|
|
356
356
|
chartElement.updateTimeWindow();
|
|
357
357
|
}, 100);
|
|
358
358
|
|
|
359
|
-
// Update button states when dataset changes
|
|
360
|
-
const originalSwitchDataset = switchDataset;
|
|
361
|
-
const switchDatasetWithButtonUpdate = (name: string) => {
|
|
362
|
-
originalSwitchDataset(name);
|
|
363
|
-
updateButtonStates();
|
|
364
|
-
};
|
|
365
|
-
|
|
366
|
-
// Replace switchDataset with the one that updates buttons
|
|
367
|
-
buttons.forEach(button => {
|
|
368
|
-
const text = button.textContent?.trim();
|
|
369
|
-
if (text === 'System Usage') {
|
|
370
|
-
button.removeEventListener('click', () => switchDataset('system'));
|
|
371
|
-
button.addEventListener('click', () => switchDatasetWithButtonUpdate('system'));
|
|
372
|
-
} else if (text === 'Network Traffic') {
|
|
373
|
-
button.removeEventListener('click', () => switchDataset('network'));
|
|
374
|
-
button.addEventListener('click', () => switchDatasetWithButtonUpdate('network'));
|
|
375
|
-
} else if (text === 'Sales Data') {
|
|
376
|
-
button.removeEventListener('click', () => switchDataset('sales'));
|
|
377
|
-
button.addEventListener('click', () => switchDatasetWithButtonUpdate('sales'));
|
|
378
|
-
}
|
|
379
|
-
});
|
|
380
|
-
|
|
381
359
|
// Initialize connections chart with data
|
|
382
360
|
if (connectionsChartElement) {
|
|
383
361
|
const initialConnectionsData = generateInitialData(previousValues.connections, 30, UPDATE_INTERVAL);
|
|
@@ -174,7 +174,7 @@ export const demoFunc = () => {
|
|
|
174
174
|
// Wire up button click handlers
|
|
175
175
|
const buttons = elementArg.querySelectorAll('dees-button');
|
|
176
176
|
buttons.forEach(button => {
|
|
177
|
-
const text = button.
|
|
177
|
+
const text = (button as any).text?.trim();
|
|
178
178
|
switch (text) {
|
|
179
179
|
case 'Add Structured Log':
|
|
180
180
|
button.addEventListener('click', () => generateRandomLog());
|
|
@@ -103,7 +103,7 @@ export const demoFunc = () => {
|
|
|
103
103
|
|
|
104
104
|
const buttons = elementArg.querySelectorAll('dees-button');
|
|
105
105
|
buttons.forEach(button => {
|
|
106
|
-
const text = button.
|
|
106
|
+
const text = (button as any).text?.trim();
|
|
107
107
|
|
|
108
108
|
switch (text) {
|
|
109
109
|
case 'Toggle Animation':
|
|
@@ -147,7 +147,7 @@ export const demoFunc = () => {
|
|
|
147
147
|
case 'Toggle Edit Mode':
|
|
148
148
|
button.addEventListener('click', () => {
|
|
149
149
|
grid.editable = !grid.editable;
|
|
150
|
-
button.
|
|
150
|
+
(button as any).text = grid.editable ? 'Lock Grid' : 'Unlock Grid';
|
|
151
151
|
});
|
|
152
152
|
break;
|
|
153
153
|
case 'Reset Layout':
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { html, DeesElement, customElement, css, cssManager } from '@design.estate/dees-element';
|
|
2
|
-
import type { IView } from './dees-simple-appdash.js';
|
|
2
|
+
import type { IView, IGlobalMessage } from './dees-simple-appdash.js';
|
|
3
3
|
import '../../00group-form/dees-form/dees-form.js';
|
|
4
4
|
import '../../00group-input/dees-input-text/dees-input-text.js';
|
|
5
5
|
import '../../00group-input/dees-input-checkbox/dees-input-checkbox.js';
|
|
@@ -263,6 +263,44 @@ export const demoFunc = () => html`
|
|
|
263
263
|
<dees-simple-appdash
|
|
264
264
|
name="My Application"
|
|
265
265
|
terminalSetupCommand="echo 'Welcome to the terminal!'"
|
|
266
|
+
.globalMessages=${[
|
|
267
|
+
{
|
|
268
|
+
id: 'update',
|
|
269
|
+
type: 'info',
|
|
270
|
+
message: 'A new version (v3.50.0) is available with performance improvements and bug fixes.',
|
|
271
|
+
dismissible: true,
|
|
272
|
+
actions: [
|
|
273
|
+
{
|
|
274
|
+
name: 'Update Now',
|
|
275
|
+
iconName: 'lucide:download',
|
|
276
|
+
action: () => alert('Updating...'),
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
name: 'Release Notes',
|
|
280
|
+
action: () => alert('Opening release notes...'),
|
|
281
|
+
},
|
|
282
|
+
],
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
id: 'maintenance',
|
|
286
|
+
type: 'warning',
|
|
287
|
+
message: 'Scheduled maintenance window: April 5, 2026 02:00–06:00 UTC. Some services may be temporarily unavailable.',
|
|
288
|
+
dismissible: true,
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
id: 'critical',
|
|
292
|
+
type: 'error',
|
|
293
|
+
message: 'Your SSL certificate expires in 3 days. Renew now to avoid service disruption.',
|
|
294
|
+
dismissible: false,
|
|
295
|
+
actions: [
|
|
296
|
+
{
|
|
297
|
+
name: 'Renew Certificate',
|
|
298
|
+
iconName: 'lucide:shieldCheck',
|
|
299
|
+
action: () => alert('Renewing certificate...'),
|
|
300
|
+
},
|
|
301
|
+
],
|
|
302
|
+
},
|
|
303
|
+
] as IGlobalMessage[]}
|
|
266
304
|
.viewTabs=${[
|
|
267
305
|
{
|
|
268
306
|
name: 'Dashboard',
|
|
@@ -29,6 +29,23 @@ export interface IView {
|
|
|
29
29
|
element: DeesElement['constructor']['prototype'];
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
export type TGlobalMessageType = 'info' | 'success' | 'warning' | 'error';
|
|
33
|
+
|
|
34
|
+
export interface IGlobalMessageAction {
|
|
35
|
+
name: string;
|
|
36
|
+
iconName?: string;
|
|
37
|
+
action: () => void | Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface IGlobalMessage {
|
|
41
|
+
id: string;
|
|
42
|
+
type: TGlobalMessageType;
|
|
43
|
+
message: string;
|
|
44
|
+
dismissible?: boolean;
|
|
45
|
+
icon?: string;
|
|
46
|
+
actions?: IGlobalMessageAction[];
|
|
47
|
+
}
|
|
48
|
+
|
|
32
49
|
@customElement('dees-simple-appdash')
|
|
33
50
|
export class DeesSimpleAppDash extends DeesElement {
|
|
34
51
|
// STATIC
|
|
@@ -45,9 +62,15 @@ export class DeesSimpleAppDash extends DeesElement {
|
|
|
45
62
|
@property({ type: String })
|
|
46
63
|
accessor terminalSetupCommand: string = `echo "Terminal ready"`;
|
|
47
64
|
|
|
65
|
+
@property({ type: Array })
|
|
66
|
+
accessor globalMessages: IGlobalMessage[] = [];
|
|
67
|
+
|
|
48
68
|
@state()
|
|
49
69
|
accessor selectedView!: IView;
|
|
50
70
|
|
|
71
|
+
@state()
|
|
72
|
+
accessor _activeMessages: IGlobalMessage[] = [];
|
|
73
|
+
|
|
51
74
|
|
|
52
75
|
public static styles = [
|
|
53
76
|
themeDefaultStyles,
|
|
@@ -327,6 +350,170 @@ export class DeesSimpleAppDash extends DeesElement {
|
|
|
327
350
|
.control.status-terminal dees-icon {
|
|
328
351
|
color: hsl(45 90% 55%);
|
|
329
352
|
}
|
|
353
|
+
|
|
354
|
+
/* Global Message Banners */
|
|
355
|
+
.messageBannerArea {
|
|
356
|
+
position: absolute;
|
|
357
|
+
top: 0;
|
|
358
|
+
left: 240px;
|
|
359
|
+
right: 0;
|
|
360
|
+
z-index: 3;
|
|
361
|
+
display: flex;
|
|
362
|
+
flex-direction: column;
|
|
363
|
+
transition: height 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
.messageBanner {
|
|
367
|
+
display: flex;
|
|
368
|
+
align-items: center;
|
|
369
|
+
gap: 12px;
|
|
370
|
+
padding: 10px 16px;
|
|
371
|
+
font-size: 13px;
|
|
372
|
+
font-family: 'Geist Sans', sans-serif;
|
|
373
|
+
font-weight: 500;
|
|
374
|
+
border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 91%)', 'hsl(0 0% 13%)')};
|
|
375
|
+
animation: bannerSlideDown 0.25s cubic-bezier(0.4, 0, 0.2, 1) forwards;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
.messageBanner.dismissing {
|
|
379
|
+
animation: bannerSlideUp 0.2s cubic-bezier(0.4, 0, 0.2, 1) forwards;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
@keyframes bannerSlideDown {
|
|
383
|
+
from {
|
|
384
|
+
opacity: 0;
|
|
385
|
+
transform: translateY(-100%);
|
|
386
|
+
}
|
|
387
|
+
to {
|
|
388
|
+
opacity: 1;
|
|
389
|
+
transform: translateY(0);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
@keyframes bannerSlideUp {
|
|
394
|
+
from {
|
|
395
|
+
opacity: 1;
|
|
396
|
+
transform: translateY(0);
|
|
397
|
+
}
|
|
398
|
+
to {
|
|
399
|
+
opacity: 0;
|
|
400
|
+
transform: translateY(-100%);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.messageBanner dees-icon {
|
|
405
|
+
font-size: 16px;
|
|
406
|
+
flex-shrink: 0;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
.messageBanner-text {
|
|
410
|
+
flex: 1;
|
|
411
|
+
overflow: hidden;
|
|
412
|
+
text-overflow: ellipsis;
|
|
413
|
+
white-space: nowrap;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.messageBanner-actions {
|
|
417
|
+
display: flex;
|
|
418
|
+
align-items: center;
|
|
419
|
+
gap: 6px;
|
|
420
|
+
flex-shrink: 0;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.messageBanner-action {
|
|
424
|
+
display: flex;
|
|
425
|
+
align-items: center;
|
|
426
|
+
gap: 6px;
|
|
427
|
+
padding: 4px 12px;
|
|
428
|
+
border-radius: 4px;
|
|
429
|
+
cursor: default;
|
|
430
|
+
font-size: 12px;
|
|
431
|
+
font-weight: 600;
|
|
432
|
+
letter-spacing: 0.01em;
|
|
433
|
+
transition: all 0.15s ease;
|
|
434
|
+
white-space: nowrap;
|
|
435
|
+
background: ${cssManager.bdTheme('hsl(0 0% 0% / 0.08)', 'hsl(0 0% 100% / 0.1)')};
|
|
436
|
+
color: inherit;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
.messageBanner-action:hover {
|
|
440
|
+
background: ${cssManager.bdTheme('hsl(0 0% 0% / 0.15)', 'hsl(0 0% 100% / 0.18)')};
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
.messageBanner-action:active {
|
|
444
|
+
transform: scale(0.97);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
.messageBanner-action dees-icon {
|
|
448
|
+
font-size: 13px;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.messageBanner-dismiss {
|
|
452
|
+
flex-shrink: 0;
|
|
453
|
+
display: flex;
|
|
454
|
+
align-items: center;
|
|
455
|
+
justify-content: center;
|
|
456
|
+
width: 24px;
|
|
457
|
+
height: 24px;
|
|
458
|
+
border-radius: 4px;
|
|
459
|
+
cursor: default;
|
|
460
|
+
opacity: 0.5;
|
|
461
|
+
transition: all 0.15s ease;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
.messageBanner-dismiss:hover {
|
|
465
|
+
opacity: 1;
|
|
466
|
+
background: hsl(0 0% 0% / 0.1);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/* Message type: info */
|
|
470
|
+
.messageBanner-info {
|
|
471
|
+
background: ${cssManager.bdTheme('hsl(210 100% 97%)', 'hsl(210 50% 10%)')};
|
|
472
|
+
color: ${cssManager.bdTheme('hsl(210 70% 30%)', 'hsl(210 70% 80%)')};
|
|
473
|
+
border-left: 3px solid #0084ff;
|
|
474
|
+
}
|
|
475
|
+
.messageBanner-info dees-icon {
|
|
476
|
+
color: #0084ff;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/* Message type: success */
|
|
480
|
+
.messageBanner-success {
|
|
481
|
+
background: ${cssManager.bdTheme('hsl(142 70% 97%)', 'hsl(142 30% 10%)')};
|
|
482
|
+
color: ${cssManager.bdTheme('hsl(142 50% 25%)', 'hsl(142 50% 80%)')};
|
|
483
|
+
border-left: 3px solid #22c55e;
|
|
484
|
+
}
|
|
485
|
+
.messageBanner-success dees-icon {
|
|
486
|
+
color: #22c55e;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/* Message type: warning */
|
|
490
|
+
.messageBanner-warning {
|
|
491
|
+
background: ${cssManager.bdTheme('hsl(38 90% 97%)', 'hsl(38 40% 10%)')};
|
|
492
|
+
color: ${cssManager.bdTheme('hsl(38 60% 25%)', 'hsl(38 60% 80%)')};
|
|
493
|
+
border-left: 3px solid #f59e0b;
|
|
494
|
+
}
|
|
495
|
+
.messageBanner-warning dees-icon {
|
|
496
|
+
color: #f59e0b;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/* Message type: error */
|
|
500
|
+
.messageBanner-error {
|
|
501
|
+
background: ${cssManager.bdTheme('hsl(0 70% 97%)', 'hsl(0 40% 10%)')};
|
|
502
|
+
color: ${cssManager.bdTheme('hsl(0 60% 30%)', 'hsl(0 60% 80%)')};
|
|
503
|
+
border-left: 3px solid #ef4444;
|
|
504
|
+
}
|
|
505
|
+
.messageBanner-error dees-icon {
|
|
506
|
+
color: #ef4444;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
.messageBanner-dismiss:hover {
|
|
510
|
+
background: ${cssManager.bdTheme('hsl(0 0% 0% / 0.08)', 'hsl(0 0% 100% / 0.1)')};
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
.appcontent {
|
|
514
|
+
top: var(--banner-area-height, 0px);
|
|
515
|
+
height: calc(100% - 24px - var(--banner-area-height, 0px));
|
|
516
|
+
}
|
|
330
517
|
`,
|
|
331
518
|
];
|
|
332
519
|
|
|
@@ -369,6 +556,34 @@ export class DeesSimpleAppDash extends DeesElement {
|
|
|
369
556
|
</div>
|
|
370
557
|
</div>
|
|
371
558
|
</div>
|
|
559
|
+
${this._activeMessages.length > 0 ? html`
|
|
560
|
+
<div class="messageBannerArea">
|
|
561
|
+
${this._activeMessages.map(msg => html`
|
|
562
|
+
<div
|
|
563
|
+
class="messageBanner messageBanner-${msg.type}"
|
|
564
|
+
data-message-id="${msg.id}"
|
|
565
|
+
>
|
|
566
|
+
<dees-icon .icon="${this.getMessageIcon(msg)}"></dees-icon>
|
|
567
|
+
<span class="messageBanner-text">${msg.message}</span>
|
|
568
|
+
${msg.actions?.length ? html`
|
|
569
|
+
<div class="messageBanner-actions">
|
|
570
|
+
${msg.actions.map(a => html`
|
|
571
|
+
<div class="messageBanner-action" @click=${() => a.action()}>
|
|
572
|
+
${a.iconName ? html`<dees-icon .icon="${a.iconName.includes(':') ? a.iconName : `lucide:${a.iconName}`}"></dees-icon>` : ''}
|
|
573
|
+
<span>${a.name}</span>
|
|
574
|
+
</div>
|
|
575
|
+
`)}
|
|
576
|
+
</div>
|
|
577
|
+
` : ''}
|
|
578
|
+
${msg.dismissible !== false ? html`
|
|
579
|
+
<div class="messageBanner-dismiss" @click=${() => this.removeMessage(msg.id)}>
|
|
580
|
+
<dees-icon .icon="${'lucide:x'}"></dees-icon>
|
|
581
|
+
</div>
|
|
582
|
+
` : ''}
|
|
583
|
+
</div>
|
|
584
|
+
`)}
|
|
585
|
+
</div>
|
|
586
|
+
` : ''}
|
|
372
587
|
<div class="appcontent">
|
|
373
588
|
<!-- Content goes here -->
|
|
374
589
|
</div>
|
|
@@ -394,6 +609,86 @@ export class DeesSimpleAppDash extends DeesElement {
|
|
|
394
609
|
await this.loadView(viewToLoad);
|
|
395
610
|
}
|
|
396
611
|
}
|
|
612
|
+
|
|
613
|
+
public willUpdate(changedProperties: Map<string, unknown>) {
|
|
614
|
+
if (changedProperties.has('globalMessages')) {
|
|
615
|
+
// Sync globalMessages property into _activeMessages
|
|
616
|
+
// Keep any messages added via addMessage() that aren't in globalMessages
|
|
617
|
+
const propertyIds = new Set(this.globalMessages.map(m => m.id));
|
|
618
|
+
const existingIds = new Set(this._activeMessages.map(m => m.id));
|
|
619
|
+
|
|
620
|
+
// Add new messages from property that aren't already active
|
|
621
|
+
const newMessages = this.globalMessages.filter(m => !existingIds.has(m.id));
|
|
622
|
+
|
|
623
|
+
// Keep messages added via API (those not in globalMessages are kept as-is)
|
|
624
|
+
// Remove messages that were in the previous globalMessages but are no longer
|
|
625
|
+
const previousGlobalMessages = (changedProperties.get('globalMessages') as IGlobalMessage[]) || [];
|
|
626
|
+
const previousIds = new Set(previousGlobalMessages.map(m => m.id));
|
|
627
|
+
const removedIds = new Set([...previousIds].filter(id => !propertyIds.has(id)));
|
|
628
|
+
|
|
629
|
+
this._activeMessages = [
|
|
630
|
+
...this._activeMessages.filter(m => !removedIds.has(m.id)),
|
|
631
|
+
...newMessages,
|
|
632
|
+
];
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
public updated(changedProperties: Map<string, unknown>) {
|
|
637
|
+
super.updated(changedProperties);
|
|
638
|
+
this.updateBannerOffset();
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
private updateBannerOffset() {
|
|
642
|
+
requestAnimationFrame(() => {
|
|
643
|
+
const bannerArea = this.shadowRoot?.querySelector('.messageBannerArea') as HTMLElement;
|
|
644
|
+
const maincontainer = this.shadowRoot?.querySelector('.maincontainer') as HTMLElement;
|
|
645
|
+
const height = bannerArea ? bannerArea.offsetHeight : 0;
|
|
646
|
+
maincontainer?.style.setProperty('--banner-area-height', `${height}px`);
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
private getMessageIcon(msg: IGlobalMessage): string {
|
|
651
|
+
if (msg.icon) return msg.icon;
|
|
652
|
+
const defaults: Record<TGlobalMessageType, string> = {
|
|
653
|
+
info: 'lucide:info',
|
|
654
|
+
success: 'lucide:circleCheck',
|
|
655
|
+
warning: 'lucide:triangleAlert',
|
|
656
|
+
error: 'lucide:circleX',
|
|
657
|
+
};
|
|
658
|
+
return defaults[msg.type];
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
public addMessage(message: Omit<IGlobalMessage, 'id'> & { id?: string }): string {
|
|
662
|
+
const id = message.id || `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
663
|
+
const fullMessage: IGlobalMessage = {
|
|
664
|
+
dismissible: true,
|
|
665
|
+
...message,
|
|
666
|
+
id,
|
|
667
|
+
};
|
|
668
|
+
this._activeMessages = [...this._activeMessages, fullMessage];
|
|
669
|
+
return id;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
public removeMessage(id: string): void {
|
|
673
|
+
const bannerEl = this.shadowRoot?.querySelector(`[data-message-id="${id}"]`) as HTMLElement;
|
|
674
|
+
if (bannerEl) {
|
|
675
|
+
bannerEl.classList.add('dismissing');
|
|
676
|
+
bannerEl.addEventListener('animationend', () => {
|
|
677
|
+
this._activeMessages = this._activeMessages.filter(m => m.id !== id);
|
|
678
|
+
this.dispatchEvent(new CustomEvent('message-dismiss', {
|
|
679
|
+
detail: { id },
|
|
680
|
+
bubbles: true,
|
|
681
|
+
composed: true,
|
|
682
|
+
}));
|
|
683
|
+
}, { once: true });
|
|
684
|
+
} else {
|
|
685
|
+
this._activeMessages = this._activeMessages.filter(m => m.id !== id);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
public clearMessages(): void {
|
|
690
|
+
this._activeMessages = [];
|
|
691
|
+
}
|
|
397
692
|
|
|
398
693
|
public currentTerminal: DeesWorkspaceTerminal | null = null;
|
|
399
694
|
public async launchTerminal() {
|
|
@@ -412,7 +707,7 @@ export class DeesSimpleAppDash extends DeesElement {
|
|
|
412
707
|
maincontainer.appendChild(terminal);
|
|
413
708
|
terminal.style.position = 'absolute';
|
|
414
709
|
terminal.style.zIndex = '10';
|
|
415
|
-
terminal.style.top = '0px';
|
|
710
|
+
terminal.style.top = 'var(--banner-area-height, 0px)';
|
|
416
711
|
terminal.style.left = '240px';
|
|
417
712
|
terminal.style.right = '0px';
|
|
418
713
|
terminal.style.bottom = '24px';
|
|
@@ -420,8 +715,6 @@ export class DeesSimpleAppDash extends DeesElement {
|
|
|
420
715
|
terminal.style.transform = 'translateY(8px) scale(0.99)';
|
|
421
716
|
terminal.style.transition = 'all 0.25s cubic-bezier(0.4, 0, 0.2, 1)';
|
|
422
717
|
terminal.style.boxShadow = '0 25px 50px -12px rgb(0 0 0 / 0.5), 0 0 0 1px rgb(255 255 255 / 0.05)';
|
|
423
|
-
terminal.style.maxWidth = `calc(${maincontainer.clientWidth}px -240px)`;
|
|
424
|
-
terminal.style.maxHeight = `calc(${maincontainer.clientHeight}px - 24px)`;
|
|
425
718
|
|
|
426
719
|
// Add close button to terminal
|
|
427
720
|
terminal.addEventListener('close', () => this.closeTerminal());
|
package/ts_web/elements/00group-workspace/dees-workspace-terminal/dees-workspace-terminal.ts
CHANGED
|
@@ -106,11 +106,11 @@ export class DeesWorkspaceTerminal extends DeesElement {
|
|
|
106
106
|
css`
|
|
107
107
|
:host {
|
|
108
108
|
background: ${cssManager.bdTheme('#ffffff', '#000000')};
|
|
109
|
-
position: absolute;
|
|
110
|
-
height: 100%;
|
|
111
|
-
width: 100%;
|
|
112
109
|
display: flex;
|
|
113
110
|
flex-direction: row;
|
|
111
|
+
box-sizing: border-box;
|
|
112
|
+
height: 100%;
|
|
113
|
+
width: 100%;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
* {
|
|
@@ -596,7 +596,7 @@ export class DeesWorkspaceTerminal extends DeesElement {
|
|
|
596
596
|
tab.terminal.focus();
|
|
597
597
|
}
|
|
598
598
|
|
|
599
|
-
|
|
599
|
+
public handleResize(): void {
|
|
600
600
|
if (this.activeTabId) {
|
|
601
601
|
const tab = this.tabManager.getTab(this.activeTabId);
|
|
602
602
|
if (tab) {
|