@chrysb/alphaclaw 0.7.0-beta.0 → 0.7.0-beta.1
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/lib/public/css/cron.css
CHANGED
|
@@ -344,7 +344,6 @@
|
|
|
344
344
|
.cron-calendar-legend-pill {
|
|
345
345
|
font-size: 10px;
|
|
346
346
|
line-height: 1;
|
|
347
|
-
border: 1px solid transparent;
|
|
348
347
|
border-radius: 999px;
|
|
349
348
|
padding: 4px 7px;
|
|
350
349
|
}
|
|
@@ -353,13 +352,13 @@
|
|
|
353
352
|
border: 1px solid var(--border);
|
|
354
353
|
border-radius: 10px;
|
|
355
354
|
overflow: auto;
|
|
356
|
-
background:
|
|
355
|
+
background: var(--bg-surface);
|
|
357
356
|
}
|
|
358
357
|
|
|
359
358
|
.cron-calendar-grid-header,
|
|
360
359
|
.cron-calendar-grid-row {
|
|
361
360
|
display: grid;
|
|
362
|
-
grid-template-columns:
|
|
361
|
+
grid-template-columns: 72px repeat(7, minmax(80px, 1fr));
|
|
363
362
|
}
|
|
364
363
|
|
|
365
364
|
.cron-calendar-day-header {
|
|
@@ -395,10 +394,67 @@
|
|
|
395
394
|
z-index: 3;
|
|
396
395
|
}
|
|
397
396
|
|
|
397
|
+
.cron-calendar-grid-corner {
|
|
398
|
+
display: flex;
|
|
399
|
+
align-items: center;
|
|
400
|
+
justify-content: center;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.cron-calendar-expand-btn {
|
|
404
|
+
width: 22px;
|
|
405
|
+
height: 22px;
|
|
406
|
+
border-radius: 6px;
|
|
407
|
+
border: 1px solid var(--border);
|
|
408
|
+
background: rgba(255, 255, 255, 0.03);
|
|
409
|
+
color: var(--text-dim);
|
|
410
|
+
display: inline-flex;
|
|
411
|
+
align-items: center;
|
|
412
|
+
justify-content: center;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.cron-calendar-expand-btn:hover {
|
|
416
|
+
color: var(--text);
|
|
417
|
+
border-color: rgba(148, 163, 184, 0.5);
|
|
418
|
+
}
|
|
419
|
+
|
|
398
420
|
.cron-calendar-grid-wrap {
|
|
399
421
|
position: relative;
|
|
400
422
|
}
|
|
401
423
|
|
|
424
|
+
.cron-calendar-lightbox-panel {
|
|
425
|
+
width: min(96vw, 1200px);
|
|
426
|
+
max-height: 88vh;
|
|
427
|
+
display: flex;
|
|
428
|
+
flex-direction: column;
|
|
429
|
+
gap: 10px;
|
|
430
|
+
padding: 16px;
|
|
431
|
+
border: 1px solid var(--border);
|
|
432
|
+
border-radius: 12px;
|
|
433
|
+
background: var(--bg-sidebar);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.cron-calendar-lightbox-close {
|
|
437
|
+
width: 26px;
|
|
438
|
+
height: 26px;
|
|
439
|
+
border-radius: 8px;
|
|
440
|
+
border: 1px solid var(--border);
|
|
441
|
+
background: rgba(255, 255, 255, 0.03);
|
|
442
|
+
color: var(--text-dim);
|
|
443
|
+
display: inline-flex;
|
|
444
|
+
align-items: center;
|
|
445
|
+
justify-content: center;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
.cron-calendar-lightbox-close:hover {
|
|
449
|
+
color: var(--text);
|
|
450
|
+
border-color: rgba(148, 163, 184, 0.5);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
.cron-calendar-lightbox-body {
|
|
454
|
+
min-height: 0;
|
|
455
|
+
overflow: auto;
|
|
456
|
+
}
|
|
457
|
+
|
|
402
458
|
.cron-calendar-grid-row .cron-calendar-hour-cell {
|
|
403
459
|
box-shadow: 1px 0 0 var(--border);
|
|
404
460
|
}
|
|
@@ -493,31 +549,50 @@
|
|
|
493
549
|
box-shadow: inset 0 0 0 1px rgba(250, 204, 21, 0.45);
|
|
494
550
|
}
|
|
495
551
|
|
|
496
|
-
.cron-calendar-compact-
|
|
552
|
+
.cron-calendar-compact-list {
|
|
497
553
|
display: flex;
|
|
498
|
-
flex-
|
|
554
|
+
flex-direction: column;
|
|
499
555
|
gap: 6px;
|
|
500
|
-
align-items: center;
|
|
501
556
|
}
|
|
502
557
|
|
|
503
|
-
.cron-calendar-compact-
|
|
558
|
+
.cron-calendar-compact-row {
|
|
559
|
+
width: 100%;
|
|
560
|
+
display: flex;
|
|
561
|
+
align-items: center;
|
|
562
|
+
justify-content: space-between;
|
|
563
|
+
gap: 10px;
|
|
564
|
+
border: 1px solid rgba(148, 163, 184, 0.32);
|
|
565
|
+
border-radius: 8px;
|
|
566
|
+
padding: 7px 9px;
|
|
567
|
+
text-align: left;
|
|
504
568
|
font-size: 11px;
|
|
505
569
|
line-height: 1.2;
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
.cron-calendar-compact-main {
|
|
573
|
+
min-width: 0;
|
|
509
574
|
display: inline-flex;
|
|
510
575
|
align-items: center;
|
|
511
|
-
gap:
|
|
512
|
-
max-width: 260px;
|
|
513
|
-
cursor: pointer;
|
|
576
|
+
gap: 8px;
|
|
514
577
|
}
|
|
515
578
|
|
|
516
579
|
.cron-calendar-compact-time {
|
|
517
580
|
font-size: 10px;
|
|
518
581
|
font-family: var(--font-mono, monospace);
|
|
519
|
-
opacity: 0.
|
|
582
|
+
opacity: 0.72;
|
|
583
|
+
white-space: nowrap;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
.cron-calendar-compact-name {
|
|
587
|
+
color: var(--text);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
.cron-calendar-compact-estimate {
|
|
591
|
+
font-size: 10px;
|
|
592
|
+
color: var(--text);
|
|
593
|
+
font-weight: 500;
|
|
520
594
|
white-space: nowrap;
|
|
595
|
+
text-align: right;
|
|
521
596
|
}
|
|
522
597
|
|
|
523
598
|
.cron-runs-trend-bars {
|
|
@@ -6,8 +6,9 @@ import {
|
|
|
6
6
|
useState,
|
|
7
7
|
} from "https://esm.sh/preact/hooks";
|
|
8
8
|
import htm from "https://esm.sh/htm";
|
|
9
|
-
import { SegmentedControl } from "../segmented-control.js";
|
|
10
9
|
import { Tooltip } from "../tooltip.js";
|
|
10
|
+
import { ModalShell } from "../modal-shell.js";
|
|
11
|
+
import { CloseIcon, FullscreenLineIcon } from "../icons.js";
|
|
11
12
|
import {
|
|
12
13
|
formatCost,
|
|
13
14
|
formatCronScheduleLabel,
|
|
@@ -15,7 +16,6 @@ import {
|
|
|
15
16
|
getCronRunEstimatedCost,
|
|
16
17
|
getCronRunTotalTokens,
|
|
17
18
|
} from "./cron-helpers.js";
|
|
18
|
-
import { readUiSettings, updateUiSettings } from "../../lib/ui-settings.js";
|
|
19
19
|
import {
|
|
20
20
|
classifyRepeatingJobs,
|
|
21
21
|
expandJobsToRollingSlots,
|
|
@@ -70,9 +70,6 @@ const slotStateClassName = ({
|
|
|
70
70
|
const renderLegend = () => html`
|
|
71
71
|
<div class="cron-calendar-legend">
|
|
72
72
|
<span class="cron-calendar-legend-label">Token intensity</span>
|
|
73
|
-
<span class="cron-calendar-legend-pill cron-calendar-slot-tier-unknown"
|
|
74
|
-
>No usage</span
|
|
75
|
-
>
|
|
76
73
|
<span class="cron-calendar-legend-pill cron-calendar-slot-tier-low"
|
|
77
74
|
>Low</span
|
|
78
75
|
>
|
|
@@ -89,14 +86,6 @@ const renderLegend = () => html`
|
|
|
89
86
|
`;
|
|
90
87
|
|
|
91
88
|
const kNowRefreshMs = 60 * 1000;
|
|
92
|
-
const kCalendarExpandedUiSettingKey = "cronCalendarExpanded";
|
|
93
|
-
const kCalendarViewUiSettingKey = "cronCalendarView";
|
|
94
|
-
const kCalendarViewUpcoming = "upcoming";
|
|
95
|
-
const kCalendarViewCalendar = "calendar";
|
|
96
|
-
const kCalendarViewOptions = [
|
|
97
|
-
{ label: "Up next", value: kCalendarViewUpcoming },
|
|
98
|
-
{ label: "Calendar", value: kCalendarViewCalendar },
|
|
99
|
-
];
|
|
100
89
|
const kRunWindow7dMs = 7 * 24 * 60 * 60 * 1000;
|
|
101
90
|
const kSlotRunToleranceMs = 45 * 60 * 1000;
|
|
102
91
|
const kUnknownTier = "unknown";
|
|
@@ -304,30 +293,8 @@ export const CronCalendar = ({
|
|
|
304
293
|
runsByJobId = {},
|
|
305
294
|
onSelectJob = () => {},
|
|
306
295
|
}) => {
|
|
307
|
-
const [
|
|
308
|
-
|
|
309
|
-
const savedView = String(
|
|
310
|
-
settings?.[kCalendarViewUiSettingKey] || "",
|
|
311
|
-
).trim();
|
|
312
|
-
if (savedView === kCalendarViewCalendar) return kCalendarViewCalendar;
|
|
313
|
-
if (savedView === kCalendarViewUpcoming) return kCalendarViewUpcoming;
|
|
314
|
-
return settings[kCalendarExpandedUiSettingKey] === true
|
|
315
|
-
? kCalendarViewCalendar
|
|
316
|
-
: kCalendarViewUpcoming;
|
|
317
|
-
});
|
|
318
|
-
const isCalendarView = calendarView === kCalendarViewCalendar;
|
|
319
|
-
const onChangeCalendarView = useCallback((nextValue) => {
|
|
320
|
-
const nextView =
|
|
321
|
-
nextValue === kCalendarViewCalendar
|
|
322
|
-
? kCalendarViewCalendar
|
|
323
|
-
: kCalendarViewUpcoming;
|
|
324
|
-
setCalendarView(nextView);
|
|
325
|
-
updateUiSettings((settings) => ({
|
|
326
|
-
...settings,
|
|
327
|
-
[kCalendarViewUiSettingKey]: nextView,
|
|
328
|
-
[kCalendarExpandedUiSettingKey]: nextView === kCalendarViewCalendar,
|
|
329
|
-
}));
|
|
330
|
-
}, []);
|
|
296
|
+
const [calendarLightboxOpen, setCalendarLightboxOpen] = useState(false);
|
|
297
|
+
const [showNoisyUpcoming, setShowNoisyUpcoming] = useState(false);
|
|
331
298
|
|
|
332
299
|
const [nowMs, setNowMs] = useState(() => Date.now());
|
|
333
300
|
useEffect(() => {
|
|
@@ -463,10 +430,34 @@ export const CronCalendar = ({
|
|
|
463
430
|
[jobById, runSummary7dByJobId, slotTierThresholds],
|
|
464
431
|
);
|
|
465
432
|
|
|
466
|
-
const
|
|
433
|
+
const upcomingSlotsPreview = useMemo(
|
|
467
434
|
() => getUpcomingSlots({ slots: timeline.slots, nowMs, limit: 3 }),
|
|
468
435
|
[timeline.slots, nowMs],
|
|
469
436
|
);
|
|
437
|
+
const noisyUpcomingItems = useMemo(() => {
|
|
438
|
+
const windowEndMs = nowMs + 24 * 60 * 60 * 1000;
|
|
439
|
+
return repeatingJobs
|
|
440
|
+
.map((job) => {
|
|
441
|
+
const jobId = String(job?.id || "");
|
|
442
|
+
const nextRunAtMs = Number(job?.state?.nextRunAtMs || 0);
|
|
443
|
+
if (!jobId || !Number.isFinite(nextRunAtMs) || nextRunAtMs <= nowMs) return null;
|
|
444
|
+
if (nextRunAtMs > windowEndMs) return null;
|
|
445
|
+
return {
|
|
446
|
+
key: `noisy:${jobId}:${nextRunAtMs}`,
|
|
447
|
+
jobId,
|
|
448
|
+
jobName: String(job?.name || jobId),
|
|
449
|
+
scheduledAtMs: nextRunAtMs,
|
|
450
|
+
};
|
|
451
|
+
})
|
|
452
|
+
.filter(Boolean)
|
|
453
|
+
.sort((left, right) => left.scheduledAtMs - right.scheduledAtMs);
|
|
454
|
+
}, [repeatingJobs, nowMs]);
|
|
455
|
+
const displayedUpcomingItems = useMemo(() => {
|
|
456
|
+
if (!showNoisyUpcoming) return upcomingSlotsPreview;
|
|
457
|
+
return [...upcomingSlotsPreview, ...noisyUpcomingItems].sort(
|
|
458
|
+
(left, right) => Number(left?.scheduledAtMs || 0) - Number(right?.scheduledAtMs || 0),
|
|
459
|
+
);
|
|
460
|
+
}, [noisyUpcomingItems, showNoisyUpcoming, upcomingSlotsPreview]);
|
|
470
461
|
|
|
471
462
|
const hourRows = useMemo(() => {
|
|
472
463
|
const uniqueHours = new Set(timeline.slots.map((slot) => slot.hourOfDay));
|
|
@@ -485,77 +476,92 @@ export const CronCalendar = ({
|
|
|
485
476
|
[timeline.slots],
|
|
486
477
|
);
|
|
487
478
|
|
|
488
|
-
const totalUpcoming = useMemo(
|
|
489
|
-
() => timeline.slots.filter((slot) => slot.scheduledAtMs > nowMs).length,
|
|
490
|
-
[timeline.slots, nowMs],
|
|
491
|
-
);
|
|
492
|
-
|
|
493
479
|
const renderCompactStrip = () => {
|
|
494
480
|
return html`
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
if (event.key !== "Enter" && event.key !== " ") return;
|
|
526
|
-
event.preventDefault();
|
|
527
|
-
onSelectJob(slot.jobId);
|
|
528
|
-
}}
|
|
529
|
-
>
|
|
530
|
-
<span class="cron-calendar-compact-time">${formatUpcomingTime(slot.scheduledAtMs)}</span>
|
|
531
|
-
<span class="truncate">${slot.jobName}</span>
|
|
532
|
-
</div>
|
|
533
|
-
</${Tooltip}>
|
|
534
|
-
`;
|
|
535
|
-
})}
|
|
536
|
-
${Math.max(0, totalUpcoming - upcomingSlots.length) > 0
|
|
537
|
-
? html`
|
|
538
|
-
<button
|
|
539
|
-
class="text-[11px] text-gray-500 hover:text-gray-300 self-center transition-colors"
|
|
540
|
-
onClick=${() =>
|
|
541
|
-
onChangeCalendarView(kCalendarViewCalendar)}
|
|
481
|
+
<div class="space-y-2">
|
|
482
|
+
${displayedUpcomingItems.length === 0
|
|
483
|
+
? html`<div class="text-xs text-gray-500 py-1">
|
|
484
|
+
No upcoming jobs in the next 24 hours.
|
|
485
|
+
</div>`
|
|
486
|
+
: html`
|
|
487
|
+
<div class="cron-calendar-compact-list">
|
|
488
|
+
${displayedUpcomingItems.map((slot) => {
|
|
489
|
+
const summary7d = runSummary7dByJobId[slot.jobId] || {};
|
|
490
|
+
const avgTokensPerRun = Number(summary7d?.avgTokensPerRun || 0);
|
|
491
|
+
const avgCostPerRun = Number(summary7d?.avgCostPerRun || 0);
|
|
492
|
+
const estimateLabel =
|
|
493
|
+
avgTokensPerRun > 0 || avgCostPerRun > 0
|
|
494
|
+
? `Est. ${avgTokensPerRun > 0 ? `${formatTokenCount(avgTokensPerRun)} tk` : "— tk"} · ${avgCostPerRun > 0 ? formatCost(avgCostPerRun) : "—"}`
|
|
495
|
+
: "Est. —";
|
|
496
|
+
const tooltipText = buildJobTooltipText({
|
|
497
|
+
jobName: slot.jobName,
|
|
498
|
+
job: jobById[slot.jobId] || null,
|
|
499
|
+
runSummary7d: runSummary7dByJobId[slot.jobId] || {},
|
|
500
|
+
slotRun: runBySlotKey[slot.key] || null,
|
|
501
|
+
latestRun: latestRunByJobId[slot.jobId],
|
|
502
|
+
scheduledAtMs: slot.scheduledAtMs,
|
|
503
|
+
nowMs,
|
|
504
|
+
});
|
|
505
|
+
return html`
|
|
506
|
+
<${Tooltip}
|
|
507
|
+
text=${tooltipText}
|
|
508
|
+
widthClass="w-72"
|
|
509
|
+
tooltipClassName="whitespace-pre-line"
|
|
510
|
+
triggerClassName="block w-full"
|
|
542
511
|
>
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
512
|
+
<button
|
|
513
|
+
key=${slot.key}
|
|
514
|
+
type="button"
|
|
515
|
+
class=${`cron-calendar-compact-row ${slotStateClassName({
|
|
516
|
+
isPast: false,
|
|
517
|
+
mappedStatus: "",
|
|
518
|
+
tokenTier: getJobProjectedTier(slot.jobId),
|
|
519
|
+
})}`}
|
|
520
|
+
onClick=${() => onSelectJob(slot.jobId)}
|
|
521
|
+
>
|
|
522
|
+
<span class="cron-calendar-compact-main">
|
|
523
|
+
<span class="cron-calendar-compact-time"
|
|
524
|
+
>${formatUpcomingTime(slot.scheduledAtMs)}</span
|
|
525
|
+
>
|
|
526
|
+
<span class="cron-calendar-compact-name truncate"
|
|
527
|
+
>${slot.jobName}</span
|
|
528
|
+
>
|
|
529
|
+
</span>
|
|
530
|
+
<span class="cron-calendar-compact-estimate"
|
|
531
|
+
>${estimateLabel}</span
|
|
532
|
+
>
|
|
533
|
+
</button>
|
|
534
|
+
</${Tooltip}>
|
|
535
|
+
`;
|
|
536
|
+
})}
|
|
537
|
+
</div>
|
|
538
|
+
`}
|
|
539
|
+
<div class="flex items-center justify-between mt-2">
|
|
540
|
+
${
|
|
541
|
+
noisyUpcomingItems.length > 0
|
|
542
|
+
? html`
|
|
543
|
+
<button
|
|
544
|
+
type="button"
|
|
545
|
+
class="ac-btn-ghost text-xs px-2.5 py-1 rounded-lg"
|
|
546
|
+
onClick=${() => setShowNoisyUpcoming((value) => !value)}
|
|
547
|
+
>
|
|
548
|
+
${
|
|
549
|
+
showNoisyUpcoming
|
|
550
|
+
? "Show fewer"
|
|
551
|
+
: `+${noisyUpcomingItems.length} noisy runs`
|
|
552
|
+
}
|
|
553
|
+
</button>
|
|
554
|
+
`
|
|
555
|
+
: html`<span></span>`
|
|
556
|
+
}
|
|
557
|
+
<${renderLegend} />
|
|
558
|
+
</div>
|
|
559
|
+
</div>
|
|
550
560
|
`;
|
|
551
561
|
};
|
|
552
562
|
|
|
553
563
|
const renderFullGrid = () => html`
|
|
554
564
|
<div class="space-y-3">
|
|
555
|
-
<div class="flex justify-end">
|
|
556
|
-
<${renderLegend} />
|
|
557
|
-
</div>
|
|
558
|
-
|
|
559
565
|
${hourRows.length === 0
|
|
560
566
|
? html`<div class="text-sm text-gray-500">
|
|
561
567
|
No scheduled jobs in this rolling window.
|
|
@@ -563,7 +569,17 @@ export const CronCalendar = ({
|
|
|
563
569
|
: html`
|
|
564
570
|
<div class="cron-calendar-grid-wrap">
|
|
565
571
|
<div class="cron-calendar-grid-header">
|
|
566
|
-
<div class="cron-calendar-hour-cell"
|
|
572
|
+
<div class="cron-calendar-hour-cell cron-calendar-grid-corner">
|
|
573
|
+
<button
|
|
574
|
+
type="button"
|
|
575
|
+
class="cron-calendar-expand-btn"
|
|
576
|
+
title="Expand calendar"
|
|
577
|
+
aria-label="Expand calendar"
|
|
578
|
+
onClick=${() => setCalendarLightboxOpen(true)}
|
|
579
|
+
>
|
|
580
|
+
<${FullscreenLineIcon} className="w-3.5 h-3.5" />
|
|
581
|
+
</button>
|
|
582
|
+
</div>
|
|
567
583
|
${timeline.days.map(
|
|
568
584
|
(day) => html`
|
|
569
585
|
<div
|
|
@@ -725,15 +741,41 @@ export const CronCalendar = ({
|
|
|
725
741
|
|
|
726
742
|
return html`
|
|
727
743
|
<section class="bg-surface border border-border rounded-xl p-4 space-y-3">
|
|
728
|
-
<div class="flex items-center gap-2">
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
744
|
+
<div class="flex items-center justify-between gap-2">
|
|
745
|
+
<h3 class="card-label card-label-bright">Up next</h3>
|
|
746
|
+
<button
|
|
747
|
+
type="button"
|
|
748
|
+
class="ac-btn-secondary text-xs px-3 py-1.5 rounded-lg"
|
|
749
|
+
onClick=${() => setCalendarLightboxOpen(true)}
|
|
750
|
+
>
|
|
751
|
+
Open calendar
|
|
752
|
+
</button>
|
|
734
753
|
</div>
|
|
735
754
|
|
|
736
|
-
${
|
|
755
|
+
${renderCompactStrip()}
|
|
737
756
|
</section>
|
|
757
|
+
<${ModalShell}
|
|
758
|
+
visible=${calendarLightboxOpen}
|
|
759
|
+
onClose=${() => setCalendarLightboxOpen(false)}
|
|
760
|
+
panelClassName="cron-calendar-lightbox-panel"
|
|
761
|
+
>
|
|
762
|
+
<div class="flex items-center justify-between gap-2">
|
|
763
|
+
<h3 class="card-label cron-calendar-title">Calendar</h3>
|
|
764
|
+
<button
|
|
765
|
+
type="button"
|
|
766
|
+
class="cron-calendar-lightbox-close"
|
|
767
|
+
onClick=${() => setCalendarLightboxOpen(false)}
|
|
768
|
+
aria-label="Close expanded calendar"
|
|
769
|
+
>
|
|
770
|
+
<${CloseIcon} className="w-4 h-4" />
|
|
771
|
+
</button>
|
|
772
|
+
</div>
|
|
773
|
+
<div class="flex items-center justify-center">
|
|
774
|
+
<${renderLegend} />
|
|
775
|
+
</div>
|
|
776
|
+
<div class="cron-calendar-lightbox-body">
|
|
777
|
+
${renderFullGrid()}
|
|
778
|
+
</div>
|
|
779
|
+
</${ModalShell}>
|
|
738
780
|
`;
|
|
739
781
|
};
|
|
@@ -428,3 +428,14 @@ export const ErrorWarningLineIcon = ({ className = "" }) => html`
|
|
|
428
428
|
/>
|
|
429
429
|
</svg>
|
|
430
430
|
`;
|
|
431
|
+
|
|
432
|
+
export const FullscreenLineIcon = ({ className = "" }) => html`
|
|
433
|
+
<svg
|
|
434
|
+
class=${className}
|
|
435
|
+
viewBox="0 0 24 24"
|
|
436
|
+
fill="currentColor"
|
|
437
|
+
aria-hidden="true"
|
|
438
|
+
>
|
|
439
|
+
<path d="M8 3V5H4V9H2V3H8ZM2 21V15H4V19H8V21H2ZM22 21H16V19H20V15H22V21ZM22 9H20V5H16V3H22V9Z" />
|
|
440
|
+
</svg>
|
|
441
|
+
`;
|