@esfaenza/core 20.3.80 → 20.3.81
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/components/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { PreferencesService, CacheService } from '@esfaenza/preferences';
|
|
|
14
14
|
import * as i5 from '@esfaenza/localizations';
|
|
15
15
|
import { LocalizationService } from '@esfaenza/localizations';
|
|
16
16
|
import { JaceIdentity, ApplicationJob, ApplicationMenu, SearchResult, SearchResultContainer, ActiveModuleView, EntityFeedsWidgetConfiguration, Feed, CreateUpdateFeedDto, UserAccount, UpdatePasswordDto } from '@esfaenza/core/domain';
|
|
17
|
-
import { Subscription, ReplaySubject, Subject } from 'rxjs';
|
|
17
|
+
import { Subscription, ReplaySubject, Subject, Observable } from 'rxjs';
|
|
18
18
|
import * as i3 from '@angular/forms';
|
|
19
19
|
import { NgForm, NgModel } from '@angular/forms';
|
|
20
20
|
import * as i4 from '@esfaenza/core/directives';
|
|
@@ -473,9 +473,77 @@ declare class EntityFeedsWidgetComponent {
|
|
|
473
473
|
static ɵcmp: i0.ɵɵComponentDeclaration<EntityFeedsWidgetComponent, "entity-feeds-widget", never, { "EntityType": { "alias": "EntityType"; "required": false; }; "EntityId": { "alias": "EntityId"; "required": false; }; "RefreshSubject": { "alias": "RefreshSubject"; "required": false; }; "GetFeedsAPI": { "alias": "GetFeedsAPI"; "required": false; }; "CreateFeedAPI": { "alias": "CreateFeedAPI"; "required": false; }; "UpdateFeedAPI": { "alias": "UpdateFeedAPI"; "required": false; }; "DeleteFeedAPI": { "alias": "DeleteFeedAPI"; "required": false; }; "ReactToFeedAPI": { "alias": "ReactToFeedAPI"; "required": false; }; "GetUserTagsAPI": { "alias": "GetUserTagsAPI"; "required": false; }; "GetFeedAttachmentAPI": { "alias": "GetFeedAttachmentAPI"; "required": false; }; "WidgetTitle": { "alias": "WidgetTitle"; "required": false; }; "MaxHeight": { "alias": "MaxHeight"; "required": false; }; "Readonly": { "alias": "Readonly"; "required": false; }; "AllowUserTags": { "alias": "AllowUserTags"; "required": false; }; "AllowReactions": { "alias": "AllowReactions"; "required": false; }; "AllowAttachments": { "alias": "AllowAttachments"; "required": false; }; "AllowComments": { "alias": "AllowComments"; "required": false; }; "AllowReplies": { "alias": "AllowReplies"; "required": false; }; "DebugMode": { "alias": "DebugMode"; "required": false; }; "ModuleConfig": { "alias": "ModuleConfig"; "required": false; }; }, {}, never, never, true, never>;
|
|
474
474
|
}
|
|
475
475
|
|
|
476
|
+
/** Risposta a un comando: testo prodotto, eventuale errore e il prompt da mostrare da lì in avanti */
|
|
477
|
+
interface EsTerminalResult {
|
|
478
|
+
Output?: string;
|
|
479
|
+
Error?: string;
|
|
480
|
+
Prompt?: string;
|
|
481
|
+
}
|
|
482
|
+
/** Esegue un comando: la riga digitata arriva così com'è, anche vuota (serve agli interpreti con prompt di continuazione) */
|
|
483
|
+
type EsTerminalExecutor = (command: string) => Observable<EsTerminalResult> | Promise<EsTerminalResult> | EsTerminalResult;
|
|
484
|
+
type EsTerminalLineKind = "greeting" | "command" | "output" | "error" | "info";
|
|
485
|
+
interface EsTerminalLine {
|
|
486
|
+
Kind: EsTerminalLineKind;
|
|
487
|
+
Text: string;
|
|
488
|
+
Prompt?: string;
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Terminale testuale senza dipendenze: storico delle righe, prompt, cronologia dei comandi (frecce su/giù),
|
|
492
|
+
* incolla di più righe eseguite in sequenza. Ogni comando passa all'Executor; finché non risponde l'input è sospeso.
|
|
493
|
+
*
|
|
494
|
+
* Tasti: Invio esegue, ↑/↓ cronologia, Tab inserisce 4 spazi, Ctrl+C (senza testo selezionato) annulla la riga, Ctrl+L pulisce.
|
|
495
|
+
* Colori e font si cambiano con le variabili CSS --es-terminal-* sull'elemento.
|
|
496
|
+
*/
|
|
497
|
+
declare class EsTerminalComponent {
|
|
498
|
+
/** Testo mostrato all'apertura */
|
|
499
|
+
Greetings: string;
|
|
500
|
+
/** Prompt iniziale; l'Executor può cambiarlo con ogni risposta */
|
|
501
|
+
set Prompt(value: string);
|
|
502
|
+
Executor: EsTerminalExecutor;
|
|
503
|
+
/** Chiave in localStorage per conservare la cronologia dei comandi fra una sessione e l'altra; senza chiave resta in memoria */
|
|
504
|
+
HistoryKey: string;
|
|
505
|
+
MaxHistory: number;
|
|
506
|
+
/** Prende il focus all'apertura */
|
|
507
|
+
AutoFocus: boolean;
|
|
508
|
+
private screen;
|
|
509
|
+
private input;
|
|
510
|
+
Lines: i0.WritableSignal<EsTerminalLine[]>;
|
|
511
|
+
CurrentPrompt: i0.WritableSignal<string>;
|
|
512
|
+
Busy: i0.WritableSignal<boolean>;
|
|
513
|
+
Command: string;
|
|
514
|
+
private history;
|
|
515
|
+
private historyIndex;
|
|
516
|
+
private draft;
|
|
517
|
+
private queue;
|
|
518
|
+
ngOnInit(): void;
|
|
519
|
+
ngAfterViewInit(): void;
|
|
520
|
+
/** Aggiunge del testo allo schermo */
|
|
521
|
+
echo(text: string, kind?: EsTerminalLineKind): void;
|
|
522
|
+
error(text: string): void;
|
|
523
|
+
clear(): void;
|
|
524
|
+
setPrompt(prompt: string): void;
|
|
525
|
+
focus(): void;
|
|
526
|
+
/** Esegue un comando come se fosse stato digitato */
|
|
527
|
+
exec(command: string): void;
|
|
528
|
+
onKeyDown(e: KeyboardEvent): void;
|
|
529
|
+
onPaste(e: ClipboardEvent): void;
|
|
530
|
+
onScreenClick(): void;
|
|
531
|
+
private runQueue;
|
|
532
|
+
private run;
|
|
533
|
+
private addToHistory;
|
|
534
|
+
private moveInHistory;
|
|
535
|
+
private loadHistory;
|
|
536
|
+
private saveHistory;
|
|
537
|
+
private insertAtCursor;
|
|
538
|
+
private hasSelection;
|
|
539
|
+
private scrollToBottom;
|
|
540
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<EsTerminalComponent, never>;
|
|
541
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<EsTerminalComponent, "es-terminal", never, { "Greetings": { "alias": "Greetings"; "required": false; }; "Prompt": { "alias": "Prompt"; "required": false; }; "Executor": { "alias": "Executor"; "required": false; }; "HistoryKey": { "alias": "HistoryKey"; "required": false; }; "MaxHistory": { "alias": "MaxHistory"; "required": false; }; "AutoFocus": { "alias": "AutoFocus"; "required": false; }; }, {}, never, never, true, never>;
|
|
542
|
+
}
|
|
543
|
+
|
|
476
544
|
declare class ComponentsModule {
|
|
477
545
|
static ɵfac: i0.ɵɵFactoryDeclaration<ComponentsModule, never>;
|
|
478
|
-
static ɵmod: i0.ɵɵNgModuleDeclaration<ComponentsModule, never, [typeof i1.CommonModule, typeof i2.RouterModule, typeof i3.FormsModule, typeof i4.DirectivesModule, typeof i5.LocalizationModule, typeof i6.ProgressbarModule, typeof i7.BsDropdownModule, typeof i8.ModalModule, typeof i9.EsTableModule, typeof BackTop, typeof Breadcrumb, typeof ErrorPageComponent, typeof PagesComponent, typeof ExternalPagesComponent, typeof JaceLoginComponent, typeof Navbar, typeof RedirecterComponent, typeof Sidebar, typeof JaceResourceComponent, typeof EsModalComponent, typeof EsModalHeadComponent, typeof LabeledSpanComponent, typeof EsImageCropperComponent, typeof FormSelectorComponent, typeof FormSelectorDialogComponent, typeof EntityFeedsWidgetComponent], [typeof BackTop, typeof Breadcrumb, typeof ErrorPageComponent, typeof PagesComponent, typeof ExternalPagesComponent, typeof JaceLoginComponent, typeof Navbar, typeof RedirecterComponent, typeof Sidebar, typeof JaceResourceComponent, typeof EsModalComponent, typeof EsModalHeadComponent, typeof LabeledSpanComponent, typeof EsImageCropperComponent, typeof FormSelectorComponent, typeof FormSelectorDialogComponent, typeof EntityFeedsWidgetComponent]>;
|
|
546
|
+
static ɵmod: i0.ɵɵNgModuleDeclaration<ComponentsModule, never, [typeof i1.CommonModule, typeof i2.RouterModule, typeof i3.FormsModule, typeof i4.DirectivesModule, typeof i5.LocalizationModule, typeof i6.ProgressbarModule, typeof i7.BsDropdownModule, typeof i8.ModalModule, typeof i9.EsTableModule, typeof BackTop, typeof Breadcrumb, typeof ErrorPageComponent, typeof PagesComponent, typeof ExternalPagesComponent, typeof JaceLoginComponent, typeof Navbar, typeof RedirecterComponent, typeof Sidebar, typeof JaceResourceComponent, typeof EsModalComponent, typeof EsModalHeadComponent, typeof LabeledSpanComponent, typeof EsImageCropperComponent, typeof FormSelectorComponent, typeof FormSelectorDialogComponent, typeof EntityFeedsWidgetComponent, typeof EsTerminalComponent], [typeof BackTop, typeof Breadcrumb, typeof ErrorPageComponent, typeof PagesComponent, typeof ExternalPagesComponent, typeof JaceLoginComponent, typeof Navbar, typeof RedirecterComponent, typeof Sidebar, typeof JaceResourceComponent, typeof EsModalComponent, typeof EsModalHeadComponent, typeof LabeledSpanComponent, typeof EsImageCropperComponent, typeof FormSelectorComponent, typeof FormSelectorDialogComponent, typeof EntityFeedsWidgetComponent, typeof EsTerminalComponent]>;
|
|
479
547
|
static ɵinj: i0.ɵɵInjectorDeclaration<ComponentsModule>;
|
|
480
548
|
}
|
|
481
549
|
|
|
@@ -695,4 +763,5 @@ declare abstract class BaseSearchComponent<TSearch extends AppSearch<TItem>, TIt
|
|
|
695
763
|
static ɵcmp: i0.ɵɵComponentDeclaration<BaseSearchComponent<any, any>, "ng-component", never, {}, {}, never, never, true, never>;
|
|
696
764
|
}
|
|
697
765
|
|
|
698
|
-
export { BackTop, BaseComponent, BaseSearchComponent, BaseSelectorComponent, BaseSelectorInitialization, Breadcrumb, BreadcrumbItem, ComponentsModule, EmbeddingComponent, EntityFeedsWidgetComponent, ErrorPageComponent, EsImageCropperComponent, EsModalComponent, EsModalHeadComponent, ExternalPagesComponent, FormSelectorComponent, FormSelectorDialogComponent, JaceLoginComponent, JaceResourceComponent, LabeledSpanComponent, Navbar, PagesComponent, ReactiveComponent, RedirecterComponent, Sidebar, UserInfosComponent };
|
|
766
|
+
export { BackTop, BaseComponent, BaseSearchComponent, BaseSelectorComponent, BaseSelectorInitialization, Breadcrumb, BreadcrumbItem, ComponentsModule, EmbeddingComponent, EntityFeedsWidgetComponent, ErrorPageComponent, EsImageCropperComponent, EsModalComponent, EsModalHeadComponent, EsTerminalComponent, ExternalPagesComponent, FormSelectorComponent, FormSelectorDialogComponent, JaceLoginComponent, JaceResourceComponent, LabeledSpanComponent, Navbar, PagesComponent, ReactiveComponent, RedirecterComponent, Sidebar, UserInfosComponent };
|
|
767
|
+
export type { EsTerminalExecutor, EsTerminalLine, EsTerminalLineKind, EsTerminalResult };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { HostListener, ViewChild, Input, ViewEncapsulation, Component, EventEmitter, Output, Inject, Injectable, Optional, ChangeDetectionStrategy, input, model, NgModule, viewChild, contentChild } from '@angular/core';
|
|
2
|
+
import { HostListener, ViewChild, Input, ViewEncapsulation, Component, EventEmitter, Output, Inject, Injectable, Optional, ChangeDetectionStrategy, input, model, signal, NgModule, viewChild, contentChild } from '@angular/core';
|
|
3
3
|
import * as i2 from '@angular/router';
|
|
4
4
|
import { NavigationEnd, RouterLink, RouterLinkActive, RouterOutlet, ActivatedRoute, Router, RouterModule } from '@angular/router';
|
|
5
5
|
import * as i4 from '@angular/common';
|
|
6
6
|
import { NgIf, NgFor, NgTemplateOutlet, NgClass, CommonModule, AsyncPipe, Location } from '@angular/common';
|
|
7
7
|
import { filter, map, mergeMap, takeUntil } from 'rxjs/operators';
|
|
8
|
-
import { Subject, combineLatest, of, firstValueFrom, ReplaySubject, interval, startWith, takeUntil as takeUntil$1, takeWhile, take, map as map$1 } from 'rxjs';
|
|
8
|
+
import { Subject, combineLatest, of, firstValueFrom, ReplaySubject, interval, startWith, takeUntil as takeUntil$1, takeWhile, isObservable, take, map as map$1 } from 'rxjs';
|
|
9
9
|
import * as i1 from '@esfaenza/core/services';
|
|
10
10
|
import { AppState } from '@esfaenza/core/services';
|
|
11
11
|
import * as i3 from '@angular/platform-browser';
|
|
@@ -1616,6 +1616,260 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImpo
|
|
|
1616
1616
|
args: ["dlgFeedContent"]
|
|
1617
1617
|
}] } });
|
|
1618
1618
|
|
|
1619
|
+
// Angular
|
|
1620
|
+
/**
|
|
1621
|
+
* Terminale testuale senza dipendenze: storico delle righe, prompt, cronologia dei comandi (frecce su/giù),
|
|
1622
|
+
* incolla di più righe eseguite in sequenza. Ogni comando passa all'Executor; finché non risponde l'input è sospeso.
|
|
1623
|
+
*
|
|
1624
|
+
* Tasti: Invio esegue, ↑/↓ cronologia, Tab inserisce 4 spazi, Ctrl+C (senza testo selezionato) annulla la riga, Ctrl+L pulisce.
|
|
1625
|
+
* Colori e font si cambiano con le variabili CSS --es-terminal-* sull'elemento.
|
|
1626
|
+
*/
|
|
1627
|
+
class EsTerminalComponent {
|
|
1628
|
+
constructor() {
|
|
1629
|
+
/** Testo mostrato all'apertura */
|
|
1630
|
+
this.Greetings = "";
|
|
1631
|
+
this.MaxHistory = 200;
|
|
1632
|
+
/** Prende il focus all'apertura */
|
|
1633
|
+
this.AutoFocus = true;
|
|
1634
|
+
this.Lines = signal([], ...(ngDevMode ? [{ debugName: "Lines" }] : []));
|
|
1635
|
+
this.CurrentPrompt = signal(">", ...(ngDevMode ? [{ debugName: "CurrentPrompt" }] : []));
|
|
1636
|
+
this.Busy = signal(false, ...(ngDevMode ? [{ debugName: "Busy" }] : []));
|
|
1637
|
+
this.Command = "";
|
|
1638
|
+
this.history = [];
|
|
1639
|
+
//Posizione nella cronologia mentre si scorre con le frecce: history.length vuol dire "riga nuova", con la bozza salvata a parte
|
|
1640
|
+
this.historyIndex = 0;
|
|
1641
|
+
this.draft = "";
|
|
1642
|
+
//Righe incollate in attesa di essere eseguite, una alla volta
|
|
1643
|
+
this.queue = [];
|
|
1644
|
+
}
|
|
1645
|
+
/** Prompt iniziale; l'Executor può cambiarlo con ogni risposta */
|
|
1646
|
+
set Prompt(value) { this.CurrentPrompt.set(value ?? ""); }
|
|
1647
|
+
ngOnInit() {
|
|
1648
|
+
this.history = this.loadHistory();
|
|
1649
|
+
this.historyIndex = this.history.length;
|
|
1650
|
+
if (this.Greetings)
|
|
1651
|
+
this.Lines.set([{ Kind: "greeting", Text: this.Greetings }]);
|
|
1652
|
+
}
|
|
1653
|
+
ngAfterViewInit() {
|
|
1654
|
+
if (this.AutoFocus)
|
|
1655
|
+
setTimeout(() => this.focus());
|
|
1656
|
+
}
|
|
1657
|
+
//******************************************************************* API pubblica
|
|
1658
|
+
/** Aggiunge del testo allo schermo */
|
|
1659
|
+
echo(text, kind = "output") {
|
|
1660
|
+
if (text === null || text === undefined)
|
|
1661
|
+
return;
|
|
1662
|
+
this.Lines.update(l => [...l, { Kind: kind, Text: text }]);
|
|
1663
|
+
this.scrollToBottom();
|
|
1664
|
+
}
|
|
1665
|
+
error(text) {
|
|
1666
|
+
this.echo(text, "error");
|
|
1667
|
+
}
|
|
1668
|
+
clear() {
|
|
1669
|
+
this.Lines.set([]);
|
|
1670
|
+
}
|
|
1671
|
+
setPrompt(prompt) {
|
|
1672
|
+
this.CurrentPrompt.set(prompt ?? "");
|
|
1673
|
+
}
|
|
1674
|
+
focus() {
|
|
1675
|
+
this.input?.nativeElement.focus({ preventScroll: true });
|
|
1676
|
+
}
|
|
1677
|
+
/** Esegue un comando come se fosse stato digitato */
|
|
1678
|
+
exec(command) {
|
|
1679
|
+
this.queue.push(command);
|
|
1680
|
+
if (!this.Busy())
|
|
1681
|
+
this.runQueue();
|
|
1682
|
+
}
|
|
1683
|
+
//******************************************************************* Input
|
|
1684
|
+
onKeyDown(e) {
|
|
1685
|
+
if (this.Busy())
|
|
1686
|
+
return;
|
|
1687
|
+
switch (e.key) {
|
|
1688
|
+
case "Enter":
|
|
1689
|
+
e.preventDefault();
|
|
1690
|
+
let command = this.Command;
|
|
1691
|
+
this.Command = "";
|
|
1692
|
+
this.exec(command);
|
|
1693
|
+
return;
|
|
1694
|
+
case "ArrowUp":
|
|
1695
|
+
e.preventDefault();
|
|
1696
|
+
this.moveInHistory(-1);
|
|
1697
|
+
return;
|
|
1698
|
+
case "ArrowDown":
|
|
1699
|
+
e.preventDefault();
|
|
1700
|
+
this.moveInHistory(1);
|
|
1701
|
+
return;
|
|
1702
|
+
case "Tab":
|
|
1703
|
+
e.preventDefault();
|
|
1704
|
+
this.insertAtCursor(" ");
|
|
1705
|
+
return;
|
|
1706
|
+
}
|
|
1707
|
+
if (e.ctrlKey && !e.altKey && !e.metaKey) {
|
|
1708
|
+
let key = e.key.toLowerCase();
|
|
1709
|
+
//Ctrl+C copia se c'è testo selezionato, altrimenti annulla la riga come in una shell
|
|
1710
|
+
if (key == "c" && !this.hasSelection()) {
|
|
1711
|
+
e.preventDefault();
|
|
1712
|
+
this.Lines.update(l => [...l, { Kind: "command", Prompt: this.CurrentPrompt(), Text: this.Command + "^C" }]);
|
|
1713
|
+
this.Command = "";
|
|
1714
|
+
this.historyIndex = this.history.length;
|
|
1715
|
+
this.scrollToBottom();
|
|
1716
|
+
}
|
|
1717
|
+
else if (key == "l") {
|
|
1718
|
+
e.preventDefault();
|
|
1719
|
+
this.clear();
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
onPaste(e) {
|
|
1724
|
+
let text = e.clipboardData?.getData("text") ?? "";
|
|
1725
|
+
if (!/[\r\n]/.test(text))
|
|
1726
|
+
return;
|
|
1727
|
+
//Più righe: la prima completa quella in corso, le altre vengono eseguite in fila; l'ultima, se non chiusa da un a capo, resta da completare
|
|
1728
|
+
e.preventDefault();
|
|
1729
|
+
let lines = text.replace(/\r\n?/g, "\n").split("\n");
|
|
1730
|
+
let last = lines.pop();
|
|
1731
|
+
lines[0] = this.Command + lines[0];
|
|
1732
|
+
this.Command = last;
|
|
1733
|
+
lines.forEach(l => this.queue.push(l));
|
|
1734
|
+
if (!this.Busy())
|
|
1735
|
+
this.runQueue();
|
|
1736
|
+
}
|
|
1737
|
+
//Un clic sullo schermo porta il focus sull'input, a meno che non si stia selezionando del testo da copiare
|
|
1738
|
+
onScreenClick() {
|
|
1739
|
+
if (!this.hasSelection())
|
|
1740
|
+
this.focus();
|
|
1741
|
+
}
|
|
1742
|
+
//******************************************************************* Esecuzione
|
|
1743
|
+
async runQueue() {
|
|
1744
|
+
while (this.queue.length > 0) {
|
|
1745
|
+
let command = this.queue.shift();
|
|
1746
|
+
await this.run(command);
|
|
1747
|
+
}
|
|
1748
|
+
setTimeout(() => this.focus());
|
|
1749
|
+
}
|
|
1750
|
+
async run(command) {
|
|
1751
|
+
this.Lines.update(l => [...l, { Kind: "command", Prompt: this.CurrentPrompt(), Text: command }]);
|
|
1752
|
+
this.addToHistory(command);
|
|
1753
|
+
this.scrollToBottom();
|
|
1754
|
+
if (!this.Executor)
|
|
1755
|
+
return;
|
|
1756
|
+
this.Busy.set(true);
|
|
1757
|
+
try {
|
|
1758
|
+
let ret = this.Executor(command);
|
|
1759
|
+
let res = isObservable(ret) ? await firstValueFrom(ret, { defaultValue: null }) : await ret;
|
|
1760
|
+
if (res?.Output)
|
|
1761
|
+
this.echo(res.Output, "output");
|
|
1762
|
+
if (res?.Error)
|
|
1763
|
+
this.echo(res.Error, "error");
|
|
1764
|
+
if (res?.Prompt !== undefined && res?.Prompt !== null)
|
|
1765
|
+
this.CurrentPrompt.set(res.Prompt);
|
|
1766
|
+
}
|
|
1767
|
+
catch (ex) {
|
|
1768
|
+
//Un errore della chiamata non deve bloccare il terminale: lo mostro e si continua
|
|
1769
|
+
this.echo(ex?.message ?? ex?.toString() ?? "Errore", "error");
|
|
1770
|
+
}
|
|
1771
|
+
finally {
|
|
1772
|
+
this.Busy.set(false);
|
|
1773
|
+
this.scrollToBottom();
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
//******************************************************************* Cronologia
|
|
1777
|
+
addToHistory(command) {
|
|
1778
|
+
if (command.trim() && this.history[this.history.length - 1] !== command) {
|
|
1779
|
+
this.history.push(command);
|
|
1780
|
+
if (this.history.length > this.MaxHistory)
|
|
1781
|
+
this.history.splice(0, this.history.length - this.MaxHistory);
|
|
1782
|
+
this.saveHistory();
|
|
1783
|
+
}
|
|
1784
|
+
this.historyIndex = this.history.length;
|
|
1785
|
+
this.draft = "";
|
|
1786
|
+
}
|
|
1787
|
+
moveInHistory(step) {
|
|
1788
|
+
let next = this.historyIndex + step;
|
|
1789
|
+
if (next < 0 || next > this.history.length)
|
|
1790
|
+
return;
|
|
1791
|
+
//Uscendo dalla riga nuova ne tengo la bozza, per ritrovarla scendendo
|
|
1792
|
+
if (this.historyIndex == this.history.length)
|
|
1793
|
+
this.draft = this.Command;
|
|
1794
|
+
this.historyIndex = next;
|
|
1795
|
+
this.Command = next == this.history.length ? this.draft : this.history[next];
|
|
1796
|
+
//Cursore in fondo, come nelle shell
|
|
1797
|
+
setTimeout(() => {
|
|
1798
|
+
let el = this.input?.nativeElement;
|
|
1799
|
+
if (el)
|
|
1800
|
+
el.setSelectionRange(el.value.length, el.value.length);
|
|
1801
|
+
});
|
|
1802
|
+
}
|
|
1803
|
+
loadHistory() {
|
|
1804
|
+
if (!this.HistoryKey)
|
|
1805
|
+
return [];
|
|
1806
|
+
try {
|
|
1807
|
+
let saved = JSON.parse(localStorage.getItem(this.HistoryKey) ?? "[]");
|
|
1808
|
+
return Array.isArray(saved) ? saved.filter(t => typeof t === "string") : [];
|
|
1809
|
+
}
|
|
1810
|
+
catch {
|
|
1811
|
+
return [];
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
saveHistory() {
|
|
1815
|
+
if (!this.HistoryKey)
|
|
1816
|
+
return;
|
|
1817
|
+
try {
|
|
1818
|
+
localStorage.setItem(this.HistoryKey, JSON.stringify(this.history));
|
|
1819
|
+
}
|
|
1820
|
+
catch { }
|
|
1821
|
+
}
|
|
1822
|
+
//******************************************************************* Utilità
|
|
1823
|
+
insertAtCursor(text) {
|
|
1824
|
+
let el = this.input?.nativeElement;
|
|
1825
|
+
if (!el)
|
|
1826
|
+
return;
|
|
1827
|
+
let start = el.selectionStart ?? this.Command.length;
|
|
1828
|
+
let end = el.selectionEnd ?? start;
|
|
1829
|
+
this.Command = this.Command.substring(0, start) + text + this.Command.substring(end);
|
|
1830
|
+
setTimeout(() => el.setSelectionRange(start + text.length, start + text.length));
|
|
1831
|
+
}
|
|
1832
|
+
//Testo selezionato sullo schermo o dentro l'input (la selezione di un input non compare in window.getSelection)
|
|
1833
|
+
hasSelection() {
|
|
1834
|
+
let el = this.input?.nativeElement;
|
|
1835
|
+
if (el && document.activeElement === el && el.selectionStart !== el.selectionEnd)
|
|
1836
|
+
return true;
|
|
1837
|
+
let sel = window.getSelection();
|
|
1838
|
+
return !!sel && !sel.isCollapsed && sel.toString().length > 0;
|
|
1839
|
+
}
|
|
1840
|
+
scrollToBottom() {
|
|
1841
|
+
setTimeout(() => {
|
|
1842
|
+
let el = this.screen?.nativeElement;
|
|
1843
|
+
if (el)
|
|
1844
|
+
el.scrollTop = el.scrollHeight;
|
|
1845
|
+
});
|
|
1846
|
+
}
|
|
1847
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: EsTerminalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1848
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.34", type: EsTerminalComponent, isStandalone: true, selector: "es-terminal", inputs: { Greetings: "Greetings", Prompt: "Prompt", Executor: "Executor", HistoryKey: "HistoryKey", MaxHistory: "MaxHistory", AutoFocus: "AutoFocus" }, viewQueries: [{ propertyName: "screen", first: true, predicate: ["screen"], descendants: true, static: true }, { propertyName: "input", first: true, predicate: ["input"], descendants: true }], ngImport: i0, template: "<div class=\"es-terminal\" #screen (click)=\"onScreenClick()\">\n @for (line of Lines(); track $index) {\n @if (line.Kind == 'command') {\n <div class=\"es-terminal-line es-terminal-command\"><span class=\"es-terminal-prompt\">{{line.Prompt}}</span>{{line.Text}}</div>\n } @else {\n <div class=\"es-terminal-line\" [class]=\"'es-terminal-' + line.Kind\">{{line.Text}}</div>\n }\n }\n\n <div class=\"es-terminal-line es-terminal-input-line\" [class.es-terminal-busy]=\"Busy()\">\n @if (Busy()) {\n <span class=\"es-terminal-spinner\"></span>\n } @else {\n <span class=\"es-terminal-prompt\">{{CurrentPrompt()}}</span>\n }\n <input #input class=\"es-terminal-input\" type=\"text\" autocomplete=\"off\" autocapitalize=\"off\" spellcheck=\"false\"\n aria-label=\"Comando\" [readonly]=\"Busy()\" [(ngModel)]=\"Command\" (keydown)=\"onKeyDown($event)\" (paste)=\"onPaste($event)\" />\n </div>\n</div>\n", styles: ["es-terminal{--es-terminal-background: #1e1e1e;--es-terminal-color: #d4d4d4;--es-terminal-command-color: #ffffff;--es-terminal-prompt-color: #4ec9b0;--es-terminal-greeting-color: #569cd6;--es-terminal-info-color: #9a9a9a;--es-terminal-error-color: #f48771;--es-terminal-selection: rgba(255, 255, 255, .25);--es-terminal-font: Consolas, \"Cascadia Mono\", \"DejaVu Sans Mono\", \"Courier New\", monospace;--es-terminal-font-size: 13px;--es-terminal-line-height: 1.45;display:block;height:100%;min-height:0}.es-terminal{height:100%;overflow-y:auto;overflow-x:hidden;padding:10px 12px;box-sizing:border-box;background:var(--es-terminal-background);color:var(--es-terminal-color);font-family:var(--es-terminal-font);font-size:var(--es-terminal-font-size);line-height:var(--es-terminal-line-height);cursor:text}.es-terminal ::selection{background:var(--es-terminal-selection)}.es-terminal-line{white-space:pre-wrap;overflow-wrap:anywhere;min-height:calc(var(--es-terminal-font-size) * var(--es-terminal-line-height))}.es-terminal-command{color:var(--es-terminal-command-color)}.es-terminal-greeting{color:var(--es-terminal-greeting-color);margin-bottom:4px}.es-terminal-info{color:var(--es-terminal-info-color)}.es-terminal-error{color:var(--es-terminal-error-color)}.es-terminal-prompt{color:var(--es-terminal-prompt-color);white-space:pre;margin-right:.5ch;-webkit-user-select:none;user-select:none}.es-terminal-input-line{display:flex;align-items:baseline}.es-terminal-input{flex:1 1 auto;min-width:0;padding:0;margin:0;border:none;outline:none;background:transparent;color:var(--es-terminal-command-color);caret-color:var(--es-terminal-command-color);font:inherit;line-height:inherit}.es-terminal-busy .es-terminal-input{color:transparent;caret-color:transparent}.es-terminal-spinner{display:inline-block;width:1ch;margin-right:.5ch;color:var(--es-terminal-prompt-color)}.es-terminal-spinner:after{content:\"|\";animation:es-terminal-spin .6s steps(4) infinite}@keyframes es-terminal-spin{0%{content:\"|\"}25%{content:\"/\"}50%{content:\"-\"}75%{content:\"\\\\\"}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
1849
|
+
}
|
|
1850
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: EsTerminalComponent, decorators: [{
|
|
1851
|
+
type: Component,
|
|
1852
|
+
args: [{ selector: "es-terminal", encapsulation: ViewEncapsulation.None, imports: [FormsModule], template: "<div class=\"es-terminal\" #screen (click)=\"onScreenClick()\">\n @for (line of Lines(); track $index) {\n @if (line.Kind == 'command') {\n <div class=\"es-terminal-line es-terminal-command\"><span class=\"es-terminal-prompt\">{{line.Prompt}}</span>{{line.Text}}</div>\n } @else {\n <div class=\"es-terminal-line\" [class]=\"'es-terminal-' + line.Kind\">{{line.Text}}</div>\n }\n }\n\n <div class=\"es-terminal-line es-terminal-input-line\" [class.es-terminal-busy]=\"Busy()\">\n @if (Busy()) {\n <span class=\"es-terminal-spinner\"></span>\n } @else {\n <span class=\"es-terminal-prompt\">{{CurrentPrompt()}}</span>\n }\n <input #input class=\"es-terminal-input\" type=\"text\" autocomplete=\"off\" autocapitalize=\"off\" spellcheck=\"false\"\n aria-label=\"Comando\" [readonly]=\"Busy()\" [(ngModel)]=\"Command\" (keydown)=\"onKeyDown($event)\" (paste)=\"onPaste($event)\" />\n </div>\n</div>\n", styles: ["es-terminal{--es-terminal-background: #1e1e1e;--es-terminal-color: #d4d4d4;--es-terminal-command-color: #ffffff;--es-terminal-prompt-color: #4ec9b0;--es-terminal-greeting-color: #569cd6;--es-terminal-info-color: #9a9a9a;--es-terminal-error-color: #f48771;--es-terminal-selection: rgba(255, 255, 255, .25);--es-terminal-font: Consolas, \"Cascadia Mono\", \"DejaVu Sans Mono\", \"Courier New\", monospace;--es-terminal-font-size: 13px;--es-terminal-line-height: 1.45;display:block;height:100%;min-height:0}.es-terminal{height:100%;overflow-y:auto;overflow-x:hidden;padding:10px 12px;box-sizing:border-box;background:var(--es-terminal-background);color:var(--es-terminal-color);font-family:var(--es-terminal-font);font-size:var(--es-terminal-font-size);line-height:var(--es-terminal-line-height);cursor:text}.es-terminal ::selection{background:var(--es-terminal-selection)}.es-terminal-line{white-space:pre-wrap;overflow-wrap:anywhere;min-height:calc(var(--es-terminal-font-size) * var(--es-terminal-line-height))}.es-terminal-command{color:var(--es-terminal-command-color)}.es-terminal-greeting{color:var(--es-terminal-greeting-color);margin-bottom:4px}.es-terminal-info{color:var(--es-terminal-info-color)}.es-terminal-error{color:var(--es-terminal-error-color)}.es-terminal-prompt{color:var(--es-terminal-prompt-color);white-space:pre;margin-right:.5ch;-webkit-user-select:none;user-select:none}.es-terminal-input-line{display:flex;align-items:baseline}.es-terminal-input{flex:1 1 auto;min-width:0;padding:0;margin:0;border:none;outline:none;background:transparent;color:var(--es-terminal-command-color);caret-color:var(--es-terminal-command-color);font:inherit;line-height:inherit}.es-terminal-busy .es-terminal-input{color:transparent;caret-color:transparent}.es-terminal-spinner{display:inline-block;width:1ch;margin-right:.5ch;color:var(--es-terminal-prompt-color)}.es-terminal-spinner:after{content:\"|\";animation:es-terminal-spin .6s steps(4) infinite}@keyframes es-terminal-spin{0%{content:\"|\"}25%{content:\"/\"}50%{content:\"-\"}75%{content:\"\\\\\"}}\n"] }]
|
|
1853
|
+
}], propDecorators: { Greetings: [{
|
|
1854
|
+
type: Input
|
|
1855
|
+
}], Prompt: [{
|
|
1856
|
+
type: Input
|
|
1857
|
+
}], Executor: [{
|
|
1858
|
+
type: Input
|
|
1859
|
+
}], HistoryKey: [{
|
|
1860
|
+
type: Input
|
|
1861
|
+
}], MaxHistory: [{
|
|
1862
|
+
type: Input
|
|
1863
|
+
}], AutoFocus: [{
|
|
1864
|
+
type: Input
|
|
1865
|
+
}], screen: [{
|
|
1866
|
+
type: ViewChild,
|
|
1867
|
+
args: ["screen", { static: true }]
|
|
1868
|
+
}], input: [{
|
|
1869
|
+
type: ViewChild,
|
|
1870
|
+
args: ["input", { static: false }]
|
|
1871
|
+
}] } });
|
|
1872
|
+
|
|
1619
1873
|
// Angular
|
|
1620
1874
|
const COMPONENTS = [
|
|
1621
1875
|
BackTop,
|
|
@@ -1634,7 +1888,8 @@ const COMPONENTS = [
|
|
|
1634
1888
|
EsImageCropperComponent,
|
|
1635
1889
|
FormSelectorComponent,
|
|
1636
1890
|
FormSelectorDialogComponent,
|
|
1637
|
-
EntityFeedsWidgetComponent
|
|
1891
|
+
EntityFeedsWidgetComponent,
|
|
1892
|
+
EsTerminalComponent
|
|
1638
1893
|
];
|
|
1639
1894
|
class ComponentsModule {
|
|
1640
1895
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: ComponentsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
@@ -1654,7 +1909,8 @@ class ComponentsModule {
|
|
|
1654
1909
|
EsImageCropperComponent,
|
|
1655
1910
|
FormSelectorComponent,
|
|
1656
1911
|
FormSelectorDialogComponent,
|
|
1657
|
-
EntityFeedsWidgetComponent
|
|
1912
|
+
EntityFeedsWidgetComponent,
|
|
1913
|
+
EsTerminalComponent], exports: [BackTop,
|
|
1658
1914
|
Breadcrumb,
|
|
1659
1915
|
ErrorPageComponent,
|
|
1660
1916
|
PagesComponent,
|
|
@@ -1670,7 +1926,8 @@ class ComponentsModule {
|
|
|
1670
1926
|
EsImageCropperComponent,
|
|
1671
1927
|
FormSelectorComponent,
|
|
1672
1928
|
FormSelectorDialogComponent,
|
|
1673
|
-
EntityFeedsWidgetComponent
|
|
1929
|
+
EntityFeedsWidgetComponent,
|
|
1930
|
+
EsTerminalComponent] }); }
|
|
1674
1931
|
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: ComponentsModule, imports: [CommonModule, RouterModule, FormsModule, DirectivesModule, LocalizationModule, ProgressbarModule, BsDropdownModule, ModalModule, EsTableModule, ErrorPageComponent,
|
|
1675
1932
|
PagesComponent,
|
|
1676
1933
|
Navbar,
|
|
@@ -1678,7 +1935,8 @@ class ComponentsModule {
|
|
|
1678
1935
|
EsImageCropperComponent,
|
|
1679
1936
|
FormSelectorComponent,
|
|
1680
1937
|
FormSelectorDialogComponent,
|
|
1681
|
-
EntityFeedsWidgetComponent
|
|
1938
|
+
EntityFeedsWidgetComponent,
|
|
1939
|
+
EsTerminalComponent] }); }
|
|
1682
1940
|
}
|
|
1683
1941
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: ComponentsModule, decorators: [{
|
|
1684
1942
|
type: NgModule,
|
|
@@ -2460,5 +2718,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImpo
|
|
|
2460
2718
|
* Generated bundle index. Do not edit.
|
|
2461
2719
|
*/
|
|
2462
2720
|
|
|
2463
|
-
export { BackTop, BaseComponent, BaseSearchComponent, BaseSelectorComponent, BaseSelectorInitialization, Breadcrumb, BreadcrumbItem, ComponentsModule, EmbeddingComponent, EntityFeedsWidgetComponent, ErrorPageComponent, EsImageCropperComponent, EsModalComponent, EsModalHeadComponent, ExternalPagesComponent, FormSelectorComponent, FormSelectorDialogComponent, JaceLoginComponent, JaceResourceComponent, LabeledSpanComponent, Navbar, PagesComponent, ReactiveComponent, RedirecterComponent, Sidebar, UserInfosComponent };
|
|
2721
|
+
export { BackTop, BaseComponent, BaseSearchComponent, BaseSelectorComponent, BaseSelectorInitialization, Breadcrumb, BreadcrumbItem, ComponentsModule, EmbeddingComponent, EntityFeedsWidgetComponent, ErrorPageComponent, EsImageCropperComponent, EsModalComponent, EsModalHeadComponent, EsTerminalComponent, ExternalPagesComponent, FormSelectorComponent, FormSelectorDialogComponent, JaceLoginComponent, JaceResourceComponent, LabeledSpanComponent, Navbar, PagesComponent, ReactiveComponent, RedirecterComponent, Sidebar, UserInfosComponent };
|
|
2464
2722
|
//# sourceMappingURL=esfaenza-core-components.mjs.map
|