@firestitch/system 18.0.43 → 18.0.45

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.
@@ -9,7 +9,7 @@ import { MatButton, MatButtonModule, MatIconButton } from '@angular/material/but
9
9
  import * as i1$3 from '@angular/material/dialog';
10
10
  import { MatDialogRef, MAT_DIALOG_DATA, MatDialogTitle, MatDialogContent, MatDialogActions, MatDialogClose, MatDialog, MatDialogModule } from '@angular/material/dialog';
11
11
  import { MatAccordion, MatExpansionPanel, MatExpansionPanelHeader, MatExpansionPanelTitle, MatExpansionModule } from '@angular/material/expansion';
12
- import { MatFormField, MatLabel, MatHint, MatFormFieldModule } from '@angular/material/form-field';
12
+ import { MatFormField, MatLabel, MatHint, MatSuffix, MatFormFieldModule } from '@angular/material/form-field';
13
13
  import { MatIcon, MatIconModule } from '@angular/material/icon';
14
14
  import { MatInput, MatInputModule } from '@angular/material/input';
15
15
  import { MatProgressSpinner, MatProgressSpinnerModule } from '@angular/material/progress-spinner';
@@ -56,6 +56,7 @@ import { index, FsCommonModule } from '@firestitch/common';
56
56
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
57
57
  import * as i3$4 from '@firestitch/clipboard';
58
58
  import { FsClipboard, FsClipboardModule } from '@firestitch/clipboard';
59
+ import { FsMarkdownRendererComponent } from '@firestitch/markdown-editor';
59
60
  import { MatOption } from '@angular/material/core';
60
61
  import { DomSanitizer } from '@angular/platform-browser';
61
62
  import * as i2$5 from '@firestitch/form';
@@ -849,6 +850,12 @@ class DashboardComponent {
849
850
  _cdRef = inject(ChangeDetectorRef);
850
851
  _buildService = inject(FsBuildService);
851
852
  _process = inject(FsProcess);
853
+ _api = inject(FsApi);
854
+ /**
855
+ * All three are optional. Left unset, the component reads the standard system
856
+ * endpoints itself — the paths every application using this library already
857
+ * serves. One is supplied only to point the component somewhere else.
858
+ */
852
859
  init;
853
860
  upgrade;
854
861
  load;
@@ -882,7 +889,7 @@ class DashboardComponent {
882
889
  action.click();
883
890
  }
884
891
  initClick() {
885
- this.init()
892
+ this._init()
886
893
  .subscribe(() => {
887
894
  this._message.success('Successfully initialized the system');
888
895
  });
@@ -902,7 +909,7 @@ class DashboardComponent {
902
909
  * is what every application had before this.
903
910
  */
904
911
  upgradeClick() {
905
- const process = this._process.run('System upgrade', this.upgrade()
912
+ const process = this._process.run('System upgrade', this._upgrade()
906
913
  .pipe(map((event) => this._upgradeLine(event)), filter((line) => line !== null)));
907
914
  // The pending-upgrade count on this screen is the thing the button was
908
915
  // pressed to change, so it is re-read when the run settles — including when
@@ -958,8 +965,29 @@ class DashboardComponent {
958
965
  return data.message || null;
959
966
  }
960
967
  }
968
+ _dashboardGet() {
969
+ return this.load
970
+ ? this.load()
971
+ : this._api.get('system/dashboard', {}, { key: 'dashboard' });
972
+ }
973
+ _init() {
974
+ return this.init
975
+ ? this.init()
976
+ : this._api.get('system/init', {}, { key: '' });
977
+ }
978
+ /**
979
+ * The upgrade endpoint is read as a stream by default, which is what fills the
980
+ * process log line by line while the run is still going. An application that
981
+ * supplies its own `upgrade` decides for itself — a plain request emits once,
982
+ * produces no lines, and the process is a labelled spinner.
983
+ */
984
+ _upgrade() {
985
+ return this.upgrade
986
+ ? this.upgrade()
987
+ : this._api.stream('GET', 'system/upgrade', { stream: true }, { key: '' });
988
+ }
961
989
  _load() {
962
- this.load()
990
+ this._dashboardGet()
963
991
  .subscribe((dashboard) => {
964
992
  this.dashboard = dashboard;
965
993
  this.dashboard.cronRanAttention = !dashboard.cronRan ||
@@ -1567,6 +1595,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
1567
1595
  type: Output
1568
1596
  }] } });
1569
1597
 
1598
+ class SettingInstructionsComponent {
1599
+ _data = inject(MAT_DIALOG_DATA);
1600
+ setting = this._data.setting;
1601
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: SettingInstructionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1602
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: SettingInstructionsComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<fs-dialog>\n <fs-dialog-title [close]=\"true\">\n {{ setting.label }}\n </fs-dialog-title>\n <mat-dialog-content>\n <fs-markdown-renderer [markdown]=\"setting.instructions\"></fs-markdown-renderer>\n </mat-dialog-content>\n</fs-dialog>\n", styles: ["fs-markdown-renderer{display:block;max-width:700px}:host ::ng-deep fs-markdown-renderer .markdown-renderer-container{overflow-x:auto;overflow-y:hidden}\n"], dependencies: [{ kind: "ngmodule", type: FsDialogModule }, { kind: "component", type: i2.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout"] }, { kind: "component", type: i2.FsDialogTitleComponent, selector: "fs-dialog-title", inputs: ["close", "dockToggle", "back"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: FsMarkdownRendererComponent, selector: "fs-markdown-renderer", inputs: ["config", "markdown"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1603
+ }
1604
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: SettingInstructionsComponent, decorators: [{
1605
+ type: Component,
1606
+ args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
1607
+ FsDialogModule,
1608
+ CdkScrollable,
1609
+ MatDialogContent,
1610
+ FsMarkdownRendererComponent,
1611
+ ], template: "<fs-dialog>\n <fs-dialog-title [close]=\"true\">\n {{ setting.label }}\n </fs-dialog-title>\n <mat-dialog-content>\n <fs-markdown-renderer [markdown]=\"setting.instructions\"></fs-markdown-renderer>\n </mat-dialog-content>\n</fs-dialog>\n", styles: ["fs-markdown-renderer{display:block;max-width:700px}:host ::ng-deep fs-markdown-renderer .markdown-renderer-container{overflow-x:auto;overflow-y:hidden}\n"] }]
1612
+ }] });
1613
+
1570
1614
  class KeyNameValuePipe {
1571
1615
  transform(values) {
1572
1616
  return Object.keys(values).map((key) => {
@@ -1635,6 +1679,7 @@ class SettingsComponent {
1635
1679
  _message = inject(FsMessage);
1636
1680
  _clipboard = inject(FsClipboard);
1637
1681
  _prompt = inject(FsPrompt);
1682
+ _dialog = inject(MatDialog);
1638
1683
  _cdRef = inject(ChangeDetectorRef);
1639
1684
  loadSettings;
1640
1685
  save;
@@ -1719,6 +1764,21 @@ class SettingsComponent {
1719
1764
  }
1720
1765
  });
1721
1766
  }
1767
+ /**
1768
+ * Opens the long-form setup steps for settings that carry them. The inline hint
1769
+ * covers what the field is; this covers work that has to happen elsewhere before
1770
+ * a value can even be obtained.
1771
+ */
1772
+ openInstructions(setting) {
1773
+ this._dialog.open(SettingInstructionsComponent, {
1774
+ // Sized by its content rather than fixed: instructions run from a couple of
1775
+ // sentences to a dozen steps, and a fixed height leaves the short ones mostly
1776
+ // empty. The caps stop a long one from filling the screen edge to edge.
1777
+ maxWidth: '80vw',
1778
+ maxHeight: '80vh',
1779
+ data: { setting },
1780
+ });
1781
+ }
1722
1782
  saveGroup(group) {
1723
1783
  const settings = this.groupedSettings[group];
1724
1784
  const values = settings.reduce((result, value) => {
@@ -1730,7 +1790,7 @@ class SettingsComponent {
1730
1790
  });
1731
1791
  }
1732
1792
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: SettingsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1733
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: SettingsComponent, isStandalone: true, selector: "fs-system-settings", inputs: { loadSettings: "loadSettings", save: "save" }, outputs: { fileRemove: "fileRemove", fileSelect: "fileSelect" }, ngImport: i0, template: "<mat-accordion>\n @for (group of groups; track group) {\n <mat-expansion-panel\n hideToggle\n >\n <mat-expansion-panel-header>\n <mat-panel-title>\n <div class=\"title-row\">\n <div class=\"title\">\n {{ group || 'General' }}\n </div>\n <div class=\"actions\">\n <button\n type=\"button\"\n [matTooltip]=\"'Export ' + (group || 'General') + ' Settings'\"\n mat-icon-button\n (click)=\"export($event, groupedSettings[group])\">\n <mat-icon>\n cloud_download\n </mat-icon>\n </button>\n <button\n type=\"button\"\n [matTooltip]=\"'Import ' + (group || 'General') + ' Settings'\"\n mat-icon-button\n (click)=\"import($event, group)\">\n <mat-icon>\n cloud_upload\n </mat-icon>\n </button>\n </div>\n </div>\n </mat-panel-title>\n </mat-expansion-panel-header>\n @for (setting of groupedSettings[group]; track setting) {\n <div\n hideToggle\n class=\"setting\"\n [ngClass]=\"{ 'has-instruction': !! setting.instruction }\">\n @if (setting.interfaceType===SettingInterfaceType.InputBox) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Textarea) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <textarea\n matInput\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n </textarea>\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Select || setting.interfaceType===SettingInterfaceType.SelectMultiple) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <mat-select\n [(ngModel)]=\"setting.value\"\n [multiple]=\"setting.interfaceType===SettingInterfaceType.SelectMultiple\"\n [name]=\"'setting' + setting.id\">\n @for (item of setting.values | keyNameValue; track item) {\n <mat-option\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Date) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Color) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsColorPicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Time) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsTimePicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.File) {\n <fs-file-picker\n [allowRemove]=\"true\"\n [allowDownload]=\"true\"\n (select)=\"fileSelect.emit({ setting: setting, file: $event.file })\"\n (remove)=\"fileRemove.emit(setting)\"\n [url]=\"setting.value\">\n <div fsFileLabel>\n {{ setting.label }}\n </div>\n <div\n fsFileHint\n [innerHTML]=\"setting.instruction | linkify\">\n </div>\n </fs-file-picker>\n }\n </div>\n }\n <button\n mat-stroked-button\n color=\"primary\"\n type=\"button\"\n (click)=\"saveGroup(group)\">\n Save\n </button>\n </mat-expansion-panel>\n }\n</mat-accordion>", styles: [".mat-expansion-panel-header{font-size:19px}.full-width{width:100%}.title-row{flex-direction:row;box-sizing:border-box;display:flex;place-content:center flex-start;align-items:center;width:100%}.title-row .title{display:flex;flex:1}:host ::ng-deep .mat-expansion-panel-header-title{margin:0}:host ::ng-deep .mat-expansion-panel .actions{display:none}:host ::ng-deep .mat-expansion-panel.mat-expanded .actions{display:block}:host ::ng-deep .setting.has-instruction fs-file-picker fs-label-message{display:block;padding-bottom:1em}\n"], dependencies: [{ kind: "directive", type: MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$4.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: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: FsDatePickerModule }, { kind: "component", type: i2$4.FsDatePickerComponent, selector: "[fsDatePicker]", inputs: ["minYear", "maxYear", "minDate", "maxDate", "startOfDay", "view", "format", "minutes"], outputs: ["change"] }, { kind: "component", type: i2$4.FsTimePickerComponent, selector: "[fsTimePicker]", inputs: ["view"] }, { kind: "ngmodule", type: FsColorPickerModule }, { kind: "component", type: i3$3.FsColorPickerComponent, selector: "[fsColorPicker]", inputs: ["showClear"] }, { kind: "ngmodule", type: FsFileModule }, { kind: "component", type: i4$1.FsFilePickerComponent, selector: "fs-file-picker", inputs: ["minWidth", "minHeight", "imageWidth", "imageHeight", "imageQuality", "label", "showFilename", "allowDownload", "allowReupload", "multiple", "allowRemove", "url", "file", "accept", "disabled", "previewWidth", "previewHeight"], outputs: ["select", "remove", "download"] }, { kind: "directive", type: i4$1.FsFileLabelDirective, selector: "[fsFileLabel]" }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "pipe", type: KeyNameValuePipe, name: "keyNameValue" }, { kind: "pipe", type: LinkifyPipe, name: "linkify" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1793
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: SettingsComponent, isStandalone: true, selector: "fs-system-settings", inputs: { loadSettings: "loadSettings", save: "save" }, outputs: { fileRemove: "fileRemove", fileSelect: "fileSelect" }, ngImport: i0, template: "<mat-accordion>\n @for (group of groups; track group) {\n <mat-expansion-panel\n hideToggle\n >\n <mat-expansion-panel-header>\n <mat-panel-title>\n <div class=\"title-row\">\n <div class=\"title\">\n {{ group || 'General' }}\n </div>\n <div class=\"actions\">\n <button\n type=\"button\"\n [matTooltip]=\"'Export ' + (group || 'General') + ' Settings'\"\n mat-icon-button\n (click)=\"export($event, groupedSettings[group])\">\n <mat-icon>\n cloud_download\n </mat-icon>\n </button>\n <button\n type=\"button\"\n [matTooltip]=\"'Import ' + (group || 'General') + ' Settings'\"\n mat-icon-button\n (click)=\"import($event, group)\">\n <mat-icon>\n cloud_upload\n </mat-icon>\n </button>\n </div>\n </div>\n </mat-panel-title>\n </mat-expansion-panel-header>\n @for (setting of groupedSettings[group]; track setting) {\n <div\n hideToggle\n class=\"setting\"\n [ngClass]=\"{ 'has-instruction': !! setting.instruction }\">\n @if (setting.interfaceType===SettingInterfaceType.InputBox) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n @if (setting.instructions) {\n <button\n type=\"button\"\n matSuffix\n mat-icon-button\n matTooltip=\"Setup instructions\"\n (click)=\"openInstructions(setting)\">\n <mat-icon>\n help_outline\n </mat-icon>\n </button>\n }\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Textarea) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <textarea\n matInput\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n </textarea>\n @if (setting.instructions) {\n <button\n type=\"button\"\n matSuffix\n mat-icon-button\n matTooltip=\"Setup instructions\"\n (click)=\"openInstructions(setting)\">\n <mat-icon>\n help_outline\n </mat-icon>\n </button>\n }\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Select || setting.interfaceType===SettingInterfaceType.SelectMultiple) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <mat-select\n [(ngModel)]=\"setting.value\"\n [multiple]=\"setting.interfaceType===SettingInterfaceType.SelectMultiple\"\n [name]=\"'setting' + setting.id\">\n @for (item of setting.values | keyNameValue; track item) {\n <mat-option\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n @if (setting.instructions) {\n <button\n type=\"button\"\n matSuffix\n mat-icon-button\n matTooltip=\"Setup instructions\"\n (click)=\"openInstructions(setting)\">\n <mat-icon>\n help_outline\n </mat-icon>\n </button>\n }\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Date) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n @if (setting.instructions) {\n <button\n type=\"button\"\n matSuffix\n mat-icon-button\n matTooltip=\"Setup instructions\"\n (click)=\"openInstructions(setting)\">\n <mat-icon>\n help_outline\n </mat-icon>\n </button>\n }\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Color) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsColorPicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n @if (setting.instructions) {\n <button\n type=\"button\"\n matSuffix\n mat-icon-button\n matTooltip=\"Setup instructions\"\n (click)=\"openInstructions(setting)\">\n <mat-icon>\n help_outline\n </mat-icon>\n </button>\n }\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Time) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsTimePicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n @if (setting.instructions) {\n <button\n type=\"button\"\n matSuffix\n mat-icon-button\n matTooltip=\"Setup instructions\"\n (click)=\"openInstructions(setting)\">\n <mat-icon>\n help_outline\n </mat-icon>\n </button>\n }\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.File) {\n <fs-file-picker\n [allowRemove]=\"true\"\n [allowDownload]=\"true\"\n (select)=\"fileSelect.emit({ setting: setting, file: $event.file })\"\n (remove)=\"fileRemove.emit(setting)\"\n [url]=\"setting.value\">\n <div fsFileLabel>\n {{ setting.label }}\n @if (setting.instructions) {\n <button\n type=\"button\"\n mat-icon-button\n matTooltip=\"Setup instructions\"\n (click)=\"openInstructions(setting)\">\n <mat-icon>\n help_outline\n </mat-icon>\n </button>\n }\n </div>\n <div\n fsFileHint\n [innerHTML]=\"setting.instruction | linkify\">\n </div>\n </fs-file-picker>\n }\n </div>\n }\n <button\n mat-stroked-button\n color=\"primary\"\n type=\"button\"\n (click)=\"saveGroup(group)\">\n Save\n </button>\n </mat-expansion-panel>\n }\n</mat-accordion>", styles: [".mat-expansion-panel-header{font-size:19px}.full-width{width:100%}.title-row{flex-direction:row;box-sizing:border-box;display:flex;place-content:center flex-start;align-items:center;width:100%}.title-row .title{display:flex;flex:1}:host ::ng-deep .mat-expansion-panel-header-title{margin:0}:host ::ng-deep .mat-expansion-panel .actions{display:none}:host ::ng-deep .mat-expansion-panel.mat-expanded .actions{display:block}:host ::ng-deep .setting.has-instruction fs-file-picker fs-label-message{display:block;padding-bottom:1em}\n"], dependencies: [{ kind: "directive", type: MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$4.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: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: FsDatePickerModule }, { kind: "component", type: i2$4.FsDatePickerComponent, selector: "[fsDatePicker]", inputs: ["minYear", "maxYear", "minDate", "maxDate", "startOfDay", "view", "format", "minutes"], outputs: ["change"] }, { kind: "component", type: i2$4.FsTimePickerComponent, selector: "[fsTimePicker]", inputs: ["view"] }, { kind: "ngmodule", type: FsColorPickerModule }, { kind: "component", type: i3$3.FsColorPickerComponent, selector: "[fsColorPicker]", inputs: ["showClear"] }, { kind: "ngmodule", type: FsFileModule }, { kind: "component", type: i4$1.FsFilePickerComponent, selector: "fs-file-picker", inputs: ["minWidth", "minHeight", "imageWidth", "imageHeight", "imageQuality", "label", "showFilename", "allowDownload", "allowReupload", "multiple", "allowRemove", "url", "file", "accept", "disabled", "previewWidth", "previewHeight"], outputs: ["select", "remove", "download"] }, { kind: "directive", type: i4$1.FsFileLabelDirective, selector: "[fsFileLabel]" }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "pipe", type: KeyNameValuePipe, name: "keyNameValue" }, { kind: "pipe", type: LinkifyPipe, name: "linkify" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1734
1794
  }
1735
1795
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: SettingsComponent, decorators: [{
1736
1796
  type: Component,
@@ -1748,6 +1808,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
1748
1808
  MatInput,
1749
1809
  FormsModule,
1750
1810
  MatHint,
1811
+ MatSuffix,
1751
1812
  MatSelect,
1752
1813
  MatOption,
1753
1814
  FsDatePickerModule,
@@ -1756,7 +1817,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
1756
1817
  MatButton,
1757
1818
  KeyNameValuePipe,
1758
1819
  LinkifyPipe,
1759
- ], template: "<mat-accordion>\n @for (group of groups; track group) {\n <mat-expansion-panel\n hideToggle\n >\n <mat-expansion-panel-header>\n <mat-panel-title>\n <div class=\"title-row\">\n <div class=\"title\">\n {{ group || 'General' }}\n </div>\n <div class=\"actions\">\n <button\n type=\"button\"\n [matTooltip]=\"'Export ' + (group || 'General') + ' Settings'\"\n mat-icon-button\n (click)=\"export($event, groupedSettings[group])\">\n <mat-icon>\n cloud_download\n </mat-icon>\n </button>\n <button\n type=\"button\"\n [matTooltip]=\"'Import ' + (group || 'General') + ' Settings'\"\n mat-icon-button\n (click)=\"import($event, group)\">\n <mat-icon>\n cloud_upload\n </mat-icon>\n </button>\n </div>\n </div>\n </mat-panel-title>\n </mat-expansion-panel-header>\n @for (setting of groupedSettings[group]; track setting) {\n <div\n hideToggle\n class=\"setting\"\n [ngClass]=\"{ 'has-instruction': !! setting.instruction }\">\n @if (setting.interfaceType===SettingInterfaceType.InputBox) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Textarea) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <textarea\n matInput\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n </textarea>\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Select || setting.interfaceType===SettingInterfaceType.SelectMultiple) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <mat-select\n [(ngModel)]=\"setting.value\"\n [multiple]=\"setting.interfaceType===SettingInterfaceType.SelectMultiple\"\n [name]=\"'setting' + setting.id\">\n @for (item of setting.values | keyNameValue; track item) {\n <mat-option\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Date) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Color) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsColorPicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Time) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsTimePicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.File) {\n <fs-file-picker\n [allowRemove]=\"true\"\n [allowDownload]=\"true\"\n (select)=\"fileSelect.emit({ setting: setting, file: $event.file })\"\n (remove)=\"fileRemove.emit(setting)\"\n [url]=\"setting.value\">\n <div fsFileLabel>\n {{ setting.label }}\n </div>\n <div\n fsFileHint\n [innerHTML]=\"setting.instruction | linkify\">\n </div>\n </fs-file-picker>\n }\n </div>\n }\n <button\n mat-stroked-button\n color=\"primary\"\n type=\"button\"\n (click)=\"saveGroup(group)\">\n Save\n </button>\n </mat-expansion-panel>\n }\n</mat-accordion>", styles: [".mat-expansion-panel-header{font-size:19px}.full-width{width:100%}.title-row{flex-direction:row;box-sizing:border-box;display:flex;place-content:center flex-start;align-items:center;width:100%}.title-row .title{display:flex;flex:1}:host ::ng-deep .mat-expansion-panel-header-title{margin:0}:host ::ng-deep .mat-expansion-panel .actions{display:none}:host ::ng-deep .mat-expansion-panel.mat-expanded .actions{display:block}:host ::ng-deep .setting.has-instruction fs-file-picker fs-label-message{display:block;padding-bottom:1em}\n"] }]
1820
+ ], template: "<mat-accordion>\n @for (group of groups; track group) {\n <mat-expansion-panel\n hideToggle\n >\n <mat-expansion-panel-header>\n <mat-panel-title>\n <div class=\"title-row\">\n <div class=\"title\">\n {{ group || 'General' }}\n </div>\n <div class=\"actions\">\n <button\n type=\"button\"\n [matTooltip]=\"'Export ' + (group || 'General') + ' Settings'\"\n mat-icon-button\n (click)=\"export($event, groupedSettings[group])\">\n <mat-icon>\n cloud_download\n </mat-icon>\n </button>\n <button\n type=\"button\"\n [matTooltip]=\"'Import ' + (group || 'General') + ' Settings'\"\n mat-icon-button\n (click)=\"import($event, group)\">\n <mat-icon>\n cloud_upload\n </mat-icon>\n </button>\n </div>\n </div>\n </mat-panel-title>\n </mat-expansion-panel-header>\n @for (setting of groupedSettings[group]; track setting) {\n <div\n hideToggle\n class=\"setting\"\n [ngClass]=\"{ 'has-instruction': !! setting.instruction }\">\n @if (setting.interfaceType===SettingInterfaceType.InputBox) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n @if (setting.instructions) {\n <button\n type=\"button\"\n matSuffix\n mat-icon-button\n matTooltip=\"Setup instructions\"\n (click)=\"openInstructions(setting)\">\n <mat-icon>\n help_outline\n </mat-icon>\n </button>\n }\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Textarea) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <textarea\n matInput\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n </textarea>\n @if (setting.instructions) {\n <button\n type=\"button\"\n matSuffix\n mat-icon-button\n matTooltip=\"Setup instructions\"\n (click)=\"openInstructions(setting)\">\n <mat-icon>\n help_outline\n </mat-icon>\n </button>\n }\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Select || setting.interfaceType===SettingInterfaceType.SelectMultiple) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <mat-select\n [(ngModel)]=\"setting.value\"\n [multiple]=\"setting.interfaceType===SettingInterfaceType.SelectMultiple\"\n [name]=\"'setting' + setting.id\">\n @for (item of setting.values | keyNameValue; track item) {\n <mat-option\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n @if (setting.instructions) {\n <button\n type=\"button\"\n matSuffix\n mat-icon-button\n matTooltip=\"Setup instructions\"\n (click)=\"openInstructions(setting)\">\n <mat-icon>\n help_outline\n </mat-icon>\n </button>\n }\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Date) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n @if (setting.instructions) {\n <button\n type=\"button\"\n matSuffix\n mat-icon-button\n matTooltip=\"Setup instructions\"\n (click)=\"openInstructions(setting)\">\n <mat-icon>\n help_outline\n </mat-icon>\n </button>\n }\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Color) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsColorPicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n @if (setting.instructions) {\n <button\n type=\"button\"\n matSuffix\n mat-icon-button\n matTooltip=\"Setup instructions\"\n (click)=\"openInstructions(setting)\">\n <mat-icon>\n help_outline\n </mat-icon>\n </button>\n }\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Time) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsTimePicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n @if (setting.instructions) {\n <button\n type=\"button\"\n matSuffix\n mat-icon-button\n matTooltip=\"Setup instructions\"\n (click)=\"openInstructions(setting)\">\n <mat-icon>\n help_outline\n </mat-icon>\n </button>\n }\n <mat-hint\n [innerHTML]=\"setting.instruction | linkify\">\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.File) {\n <fs-file-picker\n [allowRemove]=\"true\"\n [allowDownload]=\"true\"\n (select)=\"fileSelect.emit({ setting: setting, file: $event.file })\"\n (remove)=\"fileRemove.emit(setting)\"\n [url]=\"setting.value\">\n <div fsFileLabel>\n {{ setting.label }}\n @if (setting.instructions) {\n <button\n type=\"button\"\n mat-icon-button\n matTooltip=\"Setup instructions\"\n (click)=\"openInstructions(setting)\">\n <mat-icon>\n help_outline\n </mat-icon>\n </button>\n }\n </div>\n <div\n fsFileHint\n [innerHTML]=\"setting.instruction | linkify\">\n </div>\n </fs-file-picker>\n }\n </div>\n }\n <button\n mat-stroked-button\n color=\"primary\"\n type=\"button\"\n (click)=\"saveGroup(group)\">\n Save\n </button>\n </mat-expansion-panel>\n }\n</mat-accordion>", styles: [".mat-expansion-panel-header{font-size:19px}.full-width{width:100%}.title-row{flex-direction:row;box-sizing:border-box;display:flex;place-content:center flex-start;align-items:center;width:100%}.title-row .title{display:flex;flex:1}:host ::ng-deep .mat-expansion-panel-header-title{margin:0}:host ::ng-deep .mat-expansion-panel .actions{display:none}:host ::ng-deep .mat-expansion-panel.mat-expanded .actions{display:block}:host ::ng-deep .setting.has-instruction fs-file-picker fs-label-message{display:block;padding-bottom:1em}\n"] }]
1760
1821
  }], propDecorators: { loadSettings: [{
1761
1822
  type: Input
1762
1823
  }], save: [{
@@ -1854,7 +1915,8 @@ class FsSystemModule {
1854
1915
  InfoComponent,
1855
1916
  ProcessComponent,
1856
1917
  CronComponent,
1857
- CronLogComponent], exports: [DashboardComponent,
1918
+ CronLogComponent,
1919
+ SettingInstructionsComponent], exports: [DashboardComponent,
1858
1920
  CronsComponent,
1859
1921
  SettingsComponent,
1860
1922
  ProcessesComponent,
@@ -1898,7 +1960,8 @@ class FsSystemModule {
1898
1960
  ApiLogComponent,
1899
1961
  ProcessComponent,
1900
1962
  CronComponent,
1901
- CronLogComponent] });
1963
+ CronLogComponent,
1964
+ SettingInstructionsComponent] });
1902
1965
  }
1903
1966
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsSystemModule, decorators: [{
1904
1967
  type: NgModule,
@@ -1943,6 +2006,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
1943
2006
  ProcessComponent,
1944
2007
  CronComponent,
1945
2008
  CronLogComponent,
2009
+ SettingInstructionsComponent,
1946
2010
  ],
1947
2011
  exports: [
1948
2012
  DashboardComponent,
@@ -2125,5 +2189,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
2125
2189
  * Generated bundle index. Do not edit.
2126
2190
  */
2127
2191
 
2128
- export { ApiLogComponent, ApiLogState, ApiLogStates, ApiLogsComponent, CronComponent, CronLogComponent, CronState, CronStates, CronsComponent, DashboardComponent, FS_SYSTEM_CONFIG, FsSystemModule, InfoComponent, KeyNameValuePipe, LinkifyPipe, ProcessComponent, ProcessState, ProcessStates, ProcessesComponent, QueryLogsComponent, ServerLogsComponent, SettingsComponent, UpgradeLogsComponent };
2192
+ export { ApiLogComponent, ApiLogState, ApiLogStates, ApiLogsComponent, CronComponent, CronLogComponent, CronState, CronStates, CronsComponent, DashboardComponent, FS_SYSTEM_CONFIG, FsSystemModule, InfoComponent, KeyNameValuePipe, LinkifyPipe, ProcessComponent, ProcessState, ProcessStates, ProcessesComponent, QueryLogsComponent, ServerLogsComponent, SettingInstructionsComponent, SettingsComponent, UpgradeLogsComponent };
2129
2193
  //# sourceMappingURL=firestitch-system.mjs.map