@esfaenza/core 20.3.80 → 20.3.82
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,262 @@ 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
|
+
//Gli a capo finali (spesso \r\n) lascerebbero una riga vuota sotto ogni risposta
|
|
1663
|
+
text = text.replace(/\r\n?/g, "\n").replace(/\n+$/, "");
|
|
1664
|
+
this.Lines.update(l => [...l, { Kind: kind, Text: text }]);
|
|
1665
|
+
this.scrollToBottom();
|
|
1666
|
+
}
|
|
1667
|
+
error(text) {
|
|
1668
|
+
this.echo(text, "error");
|
|
1669
|
+
}
|
|
1670
|
+
clear() {
|
|
1671
|
+
this.Lines.set([]);
|
|
1672
|
+
}
|
|
1673
|
+
setPrompt(prompt) {
|
|
1674
|
+
this.CurrentPrompt.set(prompt ?? "");
|
|
1675
|
+
}
|
|
1676
|
+
focus() {
|
|
1677
|
+
this.input?.nativeElement.focus({ preventScroll: true });
|
|
1678
|
+
}
|
|
1679
|
+
/** Esegue un comando come se fosse stato digitato */
|
|
1680
|
+
exec(command) {
|
|
1681
|
+
this.queue.push(command);
|
|
1682
|
+
if (!this.Busy())
|
|
1683
|
+
this.runQueue();
|
|
1684
|
+
}
|
|
1685
|
+
//******************************************************************* Input
|
|
1686
|
+
onKeyDown(e) {
|
|
1687
|
+
if (this.Busy())
|
|
1688
|
+
return;
|
|
1689
|
+
switch (e.key) {
|
|
1690
|
+
case "Enter":
|
|
1691
|
+
e.preventDefault();
|
|
1692
|
+
let command = this.Command;
|
|
1693
|
+
this.Command = "";
|
|
1694
|
+
this.exec(command);
|
|
1695
|
+
return;
|
|
1696
|
+
case "ArrowUp":
|
|
1697
|
+
e.preventDefault();
|
|
1698
|
+
this.moveInHistory(-1);
|
|
1699
|
+
return;
|
|
1700
|
+
case "ArrowDown":
|
|
1701
|
+
e.preventDefault();
|
|
1702
|
+
this.moveInHistory(1);
|
|
1703
|
+
return;
|
|
1704
|
+
case "Tab":
|
|
1705
|
+
e.preventDefault();
|
|
1706
|
+
this.insertAtCursor(" ");
|
|
1707
|
+
return;
|
|
1708
|
+
}
|
|
1709
|
+
if (e.ctrlKey && !e.altKey && !e.metaKey) {
|
|
1710
|
+
let key = e.key.toLowerCase();
|
|
1711
|
+
//Ctrl+C copia se c'è testo selezionato, altrimenti annulla la riga come in una shell
|
|
1712
|
+
if (key == "c" && !this.hasSelection()) {
|
|
1713
|
+
e.preventDefault();
|
|
1714
|
+
this.Lines.update(l => [...l, { Kind: "command", Prompt: this.CurrentPrompt(), Text: this.Command + "^C" }]);
|
|
1715
|
+
this.Command = "";
|
|
1716
|
+
this.historyIndex = this.history.length;
|
|
1717
|
+
this.scrollToBottom();
|
|
1718
|
+
}
|
|
1719
|
+
else if (key == "l") {
|
|
1720
|
+
e.preventDefault();
|
|
1721
|
+
this.clear();
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
onPaste(e) {
|
|
1726
|
+
let text = e.clipboardData?.getData("text") ?? "";
|
|
1727
|
+
if (!/[\r\n]/.test(text))
|
|
1728
|
+
return;
|
|
1729
|
+
//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
|
|
1730
|
+
e.preventDefault();
|
|
1731
|
+
let lines = text.replace(/\r\n?/g, "\n").split("\n");
|
|
1732
|
+
let last = lines.pop();
|
|
1733
|
+
lines[0] = this.Command + lines[0];
|
|
1734
|
+
this.Command = last;
|
|
1735
|
+
lines.forEach(l => this.queue.push(l));
|
|
1736
|
+
if (!this.Busy())
|
|
1737
|
+
this.runQueue();
|
|
1738
|
+
}
|
|
1739
|
+
//Un clic sullo schermo porta il focus sull'input, a meno che non si stia selezionando del testo da copiare
|
|
1740
|
+
onScreenClick() {
|
|
1741
|
+
if (!this.hasSelection())
|
|
1742
|
+
this.focus();
|
|
1743
|
+
}
|
|
1744
|
+
//******************************************************************* Esecuzione
|
|
1745
|
+
async runQueue() {
|
|
1746
|
+
while (this.queue.length > 0) {
|
|
1747
|
+
let command = this.queue.shift();
|
|
1748
|
+
await this.run(command);
|
|
1749
|
+
}
|
|
1750
|
+
setTimeout(() => this.focus());
|
|
1751
|
+
}
|
|
1752
|
+
async run(command) {
|
|
1753
|
+
this.Lines.update(l => [...l, { Kind: "command", Prompt: this.CurrentPrompt(), Text: command }]);
|
|
1754
|
+
this.addToHistory(command);
|
|
1755
|
+
this.scrollToBottom();
|
|
1756
|
+
if (!this.Executor)
|
|
1757
|
+
return;
|
|
1758
|
+
this.Busy.set(true);
|
|
1759
|
+
try {
|
|
1760
|
+
let ret = this.Executor(command);
|
|
1761
|
+
let res = isObservable(ret) ? await firstValueFrom(ret, { defaultValue: null }) : await ret;
|
|
1762
|
+
if (res?.Output)
|
|
1763
|
+
this.echo(res.Output, "output");
|
|
1764
|
+
if (res?.Error)
|
|
1765
|
+
this.echo(res.Error, "error");
|
|
1766
|
+
if (res?.Prompt !== undefined && res?.Prompt !== null)
|
|
1767
|
+
this.CurrentPrompt.set(res.Prompt);
|
|
1768
|
+
}
|
|
1769
|
+
catch (ex) {
|
|
1770
|
+
//Un errore della chiamata non deve bloccare il terminale: lo mostro e si continua
|
|
1771
|
+
this.echo(ex?.message ?? ex?.toString() ?? "Errore", "error");
|
|
1772
|
+
}
|
|
1773
|
+
finally {
|
|
1774
|
+
this.Busy.set(false);
|
|
1775
|
+
this.scrollToBottom();
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
//******************************************************************* Cronologia
|
|
1779
|
+
addToHistory(command) {
|
|
1780
|
+
if (command.trim() && this.history[this.history.length - 1] !== command) {
|
|
1781
|
+
this.history.push(command);
|
|
1782
|
+
if (this.history.length > this.MaxHistory)
|
|
1783
|
+
this.history.splice(0, this.history.length - this.MaxHistory);
|
|
1784
|
+
this.saveHistory();
|
|
1785
|
+
}
|
|
1786
|
+
this.historyIndex = this.history.length;
|
|
1787
|
+
this.draft = "";
|
|
1788
|
+
}
|
|
1789
|
+
moveInHistory(step) {
|
|
1790
|
+
let next = this.historyIndex + step;
|
|
1791
|
+
if (next < 0 || next > this.history.length)
|
|
1792
|
+
return;
|
|
1793
|
+
//Uscendo dalla riga nuova ne tengo la bozza, per ritrovarla scendendo
|
|
1794
|
+
if (this.historyIndex == this.history.length)
|
|
1795
|
+
this.draft = this.Command;
|
|
1796
|
+
this.historyIndex = next;
|
|
1797
|
+
this.Command = next == this.history.length ? this.draft : this.history[next];
|
|
1798
|
+
//Cursore in fondo, come nelle shell
|
|
1799
|
+
setTimeout(() => {
|
|
1800
|
+
let el = this.input?.nativeElement;
|
|
1801
|
+
if (el)
|
|
1802
|
+
el.setSelectionRange(el.value.length, el.value.length);
|
|
1803
|
+
});
|
|
1804
|
+
}
|
|
1805
|
+
loadHistory() {
|
|
1806
|
+
if (!this.HistoryKey)
|
|
1807
|
+
return [];
|
|
1808
|
+
try {
|
|
1809
|
+
let saved = JSON.parse(localStorage.getItem(this.HistoryKey) ?? "[]");
|
|
1810
|
+
return Array.isArray(saved) ? saved.filter(t => typeof t === "string") : [];
|
|
1811
|
+
}
|
|
1812
|
+
catch {
|
|
1813
|
+
return [];
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
saveHistory() {
|
|
1817
|
+
if (!this.HistoryKey)
|
|
1818
|
+
return;
|
|
1819
|
+
try {
|
|
1820
|
+
localStorage.setItem(this.HistoryKey, JSON.stringify(this.history));
|
|
1821
|
+
}
|
|
1822
|
+
catch { }
|
|
1823
|
+
}
|
|
1824
|
+
//******************************************************************* Utilità
|
|
1825
|
+
insertAtCursor(text) {
|
|
1826
|
+
let el = this.input?.nativeElement;
|
|
1827
|
+
if (!el)
|
|
1828
|
+
return;
|
|
1829
|
+
let start = el.selectionStart ?? this.Command.length;
|
|
1830
|
+
let end = el.selectionEnd ?? start;
|
|
1831
|
+
this.Command = this.Command.substring(0, start) + text + this.Command.substring(end);
|
|
1832
|
+
setTimeout(() => el.setSelectionRange(start + text.length, start + text.length));
|
|
1833
|
+
}
|
|
1834
|
+
//Testo selezionato sullo schermo o dentro l'input (la selezione di un input non compare in window.getSelection)
|
|
1835
|
+
hasSelection() {
|
|
1836
|
+
let el = this.input?.nativeElement;
|
|
1837
|
+
if (el && document.activeElement === el && el.selectionStart !== el.selectionEnd)
|
|
1838
|
+
return true;
|
|
1839
|
+
let sel = window.getSelection();
|
|
1840
|
+
return !!sel && !sel.isCollapsed && sel.toString().length > 0;
|
|
1841
|
+
}
|
|
1842
|
+
scrollToBottom() {
|
|
1843
|
+
setTimeout(() => {
|
|
1844
|
+
let el = this.screen?.nativeElement;
|
|
1845
|
+
if (el)
|
|
1846
|
+
el.scrollTop = el.scrollHeight;
|
|
1847
|
+
});
|
|
1848
|
+
}
|
|
1849
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: EsTerminalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1850
|
+
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 }); }
|
|
1851
|
+
}
|
|
1852
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: EsTerminalComponent, decorators: [{
|
|
1853
|
+
type: Component,
|
|
1854
|
+
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"] }]
|
|
1855
|
+
}], propDecorators: { Greetings: [{
|
|
1856
|
+
type: Input
|
|
1857
|
+
}], Prompt: [{
|
|
1858
|
+
type: Input
|
|
1859
|
+
}], Executor: [{
|
|
1860
|
+
type: Input
|
|
1861
|
+
}], HistoryKey: [{
|
|
1862
|
+
type: Input
|
|
1863
|
+
}], MaxHistory: [{
|
|
1864
|
+
type: Input
|
|
1865
|
+
}], AutoFocus: [{
|
|
1866
|
+
type: Input
|
|
1867
|
+
}], screen: [{
|
|
1868
|
+
type: ViewChild,
|
|
1869
|
+
args: ["screen", { static: true }]
|
|
1870
|
+
}], input: [{
|
|
1871
|
+
type: ViewChild,
|
|
1872
|
+
args: ["input", { static: false }]
|
|
1873
|
+
}] } });
|
|
1874
|
+
|
|
1619
1875
|
// Angular
|
|
1620
1876
|
const COMPONENTS = [
|
|
1621
1877
|
BackTop,
|
|
@@ -1634,7 +1890,8 @@ const COMPONENTS = [
|
|
|
1634
1890
|
EsImageCropperComponent,
|
|
1635
1891
|
FormSelectorComponent,
|
|
1636
1892
|
FormSelectorDialogComponent,
|
|
1637
|
-
EntityFeedsWidgetComponent
|
|
1893
|
+
EntityFeedsWidgetComponent,
|
|
1894
|
+
EsTerminalComponent
|
|
1638
1895
|
];
|
|
1639
1896
|
class ComponentsModule {
|
|
1640
1897
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: ComponentsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
@@ -1654,7 +1911,8 @@ class ComponentsModule {
|
|
|
1654
1911
|
EsImageCropperComponent,
|
|
1655
1912
|
FormSelectorComponent,
|
|
1656
1913
|
FormSelectorDialogComponent,
|
|
1657
|
-
EntityFeedsWidgetComponent
|
|
1914
|
+
EntityFeedsWidgetComponent,
|
|
1915
|
+
EsTerminalComponent], exports: [BackTop,
|
|
1658
1916
|
Breadcrumb,
|
|
1659
1917
|
ErrorPageComponent,
|
|
1660
1918
|
PagesComponent,
|
|
@@ -1670,7 +1928,8 @@ class ComponentsModule {
|
|
|
1670
1928
|
EsImageCropperComponent,
|
|
1671
1929
|
FormSelectorComponent,
|
|
1672
1930
|
FormSelectorDialogComponent,
|
|
1673
|
-
EntityFeedsWidgetComponent
|
|
1931
|
+
EntityFeedsWidgetComponent,
|
|
1932
|
+
EsTerminalComponent] }); }
|
|
1674
1933
|
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
1934
|
PagesComponent,
|
|
1676
1935
|
Navbar,
|
|
@@ -1678,7 +1937,8 @@ class ComponentsModule {
|
|
|
1678
1937
|
EsImageCropperComponent,
|
|
1679
1938
|
FormSelectorComponent,
|
|
1680
1939
|
FormSelectorDialogComponent,
|
|
1681
|
-
EntityFeedsWidgetComponent
|
|
1940
|
+
EntityFeedsWidgetComponent,
|
|
1941
|
+
EsTerminalComponent] }); }
|
|
1682
1942
|
}
|
|
1683
1943
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImport: i0, type: ComponentsModule, decorators: [{
|
|
1684
1944
|
type: NgModule,
|
|
@@ -2460,5 +2720,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.34", ngImpo
|
|
|
2460
2720
|
* Generated bundle index. Do not edit.
|
|
2461
2721
|
*/
|
|
2462
2722
|
|
|
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 };
|
|
2723
|
+
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
2724
|
//# sourceMappingURL=esfaenza-core-components.mjs.map
|