@c8y/ngx-components 1024.2.4 → 1024.8.3
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/fesm2022/{c8y-ngx-components-asset-property-grid.component-DhfJagxU.mjs → c8y-ngx-components-asset-property-grid.component-Ddva2QJW.mjs} +35 -19
- package/fesm2022/c8y-ngx-components-asset-property-grid.component-Ddva2QJW.mjs.map +1 -0
- package/fesm2022/c8y-ngx-components-bookmarks.mjs +33 -23
- package/fesm2022/c8y-ngx-components-bookmarks.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-context-dashboard.mjs +30 -16
- package/fesm2022/c8y-ngx-components-context-dashboard.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs +3 -2
- package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-datapoints-export-selector.mjs +2 -2
- package/fesm2022/c8y-ngx-components-datapoints-export-selector.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-device-profile.mjs +27 -9
- package/fesm2022/c8y-ngx-components-device-profile.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-icon-selector.mjs +1538 -59
- package/fesm2022/c8y-ngx-components-icon-selector.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-protocol-opcua.mjs +9 -11
- package/fesm2022/c8y-ngx-components-protocol-opcua.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-remote-access-data.mjs +52 -2
- package/fesm2022/c8y-ngx-components-remote-access-data.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-remote-access-ssh-remote-access-ssh-endpoint-modal.mjs +17 -3
- package/fesm2022/c8y-ngx-components-remote-access-ssh-remote-access-ssh-endpoint-modal.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-remote-access-terminal-viewer.mjs +184 -41
- package/fesm2022/c8y-ngx-components-remote-access-terminal-viewer.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-repository-configuration.mjs +94 -49
- package/fesm2022/c8y-ngx-components-repository-configuration.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-repository-firmware.mjs +5 -4
- package/fesm2022/c8y-ngx-components-repository-firmware.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-repository-software.mjs +10 -4
- package/fesm2022/c8y-ngx-components-repository-software.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-trusted-certificates.mjs +5 -4
- package/fesm2022/c8y-ngx-components-trusted-certificates.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs +6 -5
- package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components.mjs +10 -5
- package/fesm2022/c8y-ngx-components.mjs.map +1 -1
- package/locales/de.po +327 -8
- package/locales/es.po +327 -8
- package/locales/fr.po +327 -8
- package/locales/ja_JP.po +325 -9
- package/locales/ko.po +327 -8
- package/locales/locales.pot +326 -7
- package/locales/nl.po +327 -8
- package/locales/pl.po +327 -8
- package/locales/pt_BR.po +327 -8
- package/locales/zh_CN.po +327 -8
- package/locales/zh_TW.po +327 -8
- package/package.json +1 -1
- package/types/c8y-ngx-components-bookmarks.d.ts +7 -7
- package/types/c8y-ngx-components-bookmarks.d.ts.map +1 -1
- package/types/c8y-ngx-components-context-dashboard.d.ts +7 -3
- package/types/c8y-ngx-components-context-dashboard.d.ts.map +1 -1
- package/types/c8y-ngx-components-device-profile.d.ts +5 -2
- package/types/c8y-ngx-components-device-profile.d.ts.map +1 -1
- package/types/c8y-ngx-components-icon-selector.d.ts +286 -32
- package/types/c8y-ngx-components-icon-selector.d.ts.map +1 -1
- package/types/c8y-ngx-components-protocol-opcua.d.ts.map +1 -1
- package/types/c8y-ngx-components-remote-access-data.d.ts +27 -1
- package/types/c8y-ngx-components-remote-access-data.d.ts.map +1 -1
- package/types/c8y-ngx-components-remote-access-ssh-remote-access-ssh-endpoint-modal.d.ts +10 -3
- package/types/c8y-ngx-components-remote-access-ssh-remote-access-ssh-endpoint-modal.d.ts.map +1 -1
- package/types/c8y-ngx-components-remote-access-terminal-viewer.d.ts +20 -2
- package/types/c8y-ngx-components-remote-access-terminal-viewer.d.ts.map +1 -1
- package/types/c8y-ngx-components-repository-configuration.d.ts +20 -10
- package/types/c8y-ngx-components-repository-configuration.d.ts.map +1 -1
- package/types/c8y-ngx-components-repository-firmware.d.ts.map +1 -1
- package/types/c8y-ngx-components-repository-software.d.ts +2 -0
- package/types/c8y-ngx-components-repository-software.d.ts.map +1 -1
- package/types/c8y-ngx-components-trusted-certificates.d.ts.map +1 -1
- package/types/c8y-ngx-components-widgets-implementations-asset-table.d.ts.map +1 -1
- package/types/c8y-ngx-components.d.ts +5 -1
- package/types/c8y-ngx-components.d.ts.map +1 -1
- package/fesm2022/c8y-ngx-components-asset-property-grid.component-DhfJagxU.mjs.map +0 -1
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { EventEmitter, Injectable,
|
|
2
|
+
import { EventEmitter, Injectable, signal, computed, inject, DestroyRef, Component, Pipe, ChangeDetectorRef, Input, ChangeDetectionStrategy, Output, ViewChild, NgModule } from '@angular/core';
|
|
3
|
+
import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
3
4
|
import * as i1 from '@angular/router';
|
|
4
5
|
import * as i3$1 from '@c8y/client';
|
|
5
6
|
import { OperationStatus, InventoryBinaryService } from '@c8y/client';
|
|
6
7
|
import { gettext } from '@c8y/ngx-components/gettext';
|
|
7
8
|
import * as i2 from '@c8y/ngx-components';
|
|
8
|
-
import { IconDirective, C8yTranslatePipe, BottomDrawerRef, AlertService, ValidationPattern, isBinaryFile, C8yTranslateDirective, FormGroupComponent, TypeaheadComponent, ForOfDirective, ListItemComponent, HighlightComponent, FilePickerComponent, MessagesComponent, RequiredInputPlaceholderDirective,
|
|
9
|
+
import { IconDirective, SelectComponent, C8yTranslatePipe, BottomDrawerRef, AlertService, ValidationPattern, isBinaryFile, C8yTranslateDirective, FormGroupComponent, TypeaheadComponent, ForOfDirective, ListItemComponent, HighlightComponent, FilePickerComponent, MessagesComponent, RequiredInputPlaceholderDirective, Permissions, DatePipe, FilterInputComponent, ActionBarItemComponent, TabsetAriaDirective, EmptyStateComponent, hookRoute, ViewContext, DataGridService, BottomDrawerService, ModalService, BuiltInActionType, Status, TitleComponent, BreadcrumbComponent, BreadcrumbItemComponent, HelpComponent, DataGridComponent, EmptyStateContextDirective, GuideDocsComponent, GuideHrefDirective, NavigatorNode, hookNavigator, CoreModule, FormsModule as FormsModule$1 } from '@c8y/ngx-components';
|
|
10
|
+
import { EditorComponent, MonacoEditorMarkerValidatorDirective } from '@c8y/ngx-components/editor';
|
|
9
11
|
import * as i3 from '@c8y/ngx-components/repository/shared';
|
|
10
12
|
import { DeviceConfigurationOperation, RepositoryService, RepositoryType, mimeTypeToEditorLanguage, SharedRepositoryModule, RepositoryItemNameGridColumn, DescriptionGridColumn, FileGridColumn, DeviceTypeGridColumn, TypeGridColumn } from '@c8y/ngx-components/repository/shared';
|
|
11
13
|
import { NgClass, NgIf, NgFor, AsyncPipe } from '@angular/common';
|
|
12
14
|
import * as i1$1 from '@angular/forms';
|
|
13
|
-
import {
|
|
15
|
+
import { FormGroup, FormControl, ReactiveFormsModule, Validators, FormsModule } from '@angular/forms';
|
|
14
16
|
import { OperationDetailsComponent, OperationDetailsModule } from '@c8y/ngx-components/operations/operation-details';
|
|
15
17
|
import { has, uniqBy } from 'lodash-es';
|
|
16
18
|
import { saveAs } from 'file-saver';
|
|
17
19
|
import { map } from 'rxjs/operators';
|
|
18
|
-
import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
19
|
-
import { EditorComponent, MonacoEditorMarkerValidatorDirective } from '@c8y/ngx-components/editor';
|
|
20
20
|
import { pipe } from 'rxjs';
|
|
21
21
|
import * as i1$3 from 'ngx-bootstrap/tabs';
|
|
22
22
|
import { TabsetComponent, TabDirective, TabsModule } from 'ngx-bootstrap/tabs';
|
|
@@ -67,6 +67,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
67
67
|
type: Injectable
|
|
68
68
|
}], ctorParameters: () => [{ type: i2.BottomDrawerService }] });
|
|
69
69
|
|
|
70
|
+
/** Shared language list for Monaco-based configuration editors (no "Auto" option). */
|
|
71
|
+
const EDITOR_LANGUAGES = [
|
|
72
|
+
{ value: 'json', label: gettext('JSON') },
|
|
73
|
+
{ value: 'javascript', label: gettext('JavaScript') },
|
|
74
|
+
{ value: 'typescript', label: gettext('TypeScript') },
|
|
75
|
+
{ value: 'css', label: gettext('CSS') },
|
|
76
|
+
{ value: 'html', label: gettext('HTML') },
|
|
77
|
+
{ value: 'yaml', label: gettext('YAML') },
|
|
78
|
+
{ value: 'markdown', label: gettext('Markdown') },
|
|
79
|
+
{ value: 'xml', label: gettext('XML') },
|
|
80
|
+
{ value: 'ini', label: gettext('INI / TOML / Properties') },
|
|
81
|
+
{ value: 'shell', label: gettext('Shell') },
|
|
82
|
+
{ value: 'plaintext', label: gettext('Plain text') }
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
// Device text configs are plain text by default — put plaintext first in the picker.
|
|
86
|
+
const PLAINTEXT_OPTION = EDITOR_LANGUAGES[EDITOR_LANGUAGES.length - 1];
|
|
87
|
+
const TEXT_EDITOR_LANGUAGES = [
|
|
88
|
+
PLAINTEXT_OPTION,
|
|
89
|
+
...EDITOR_LANGUAGES.slice(0, -1)
|
|
90
|
+
];
|
|
70
91
|
class TextBasedConfigurationComponent {
|
|
71
92
|
constructor(route, alertService, repositoryService, deviceConfigurationService, inventoryService) {
|
|
72
93
|
this.route = route;
|
|
@@ -74,7 +95,38 @@ class TextBasedConfigurationComponent {
|
|
|
74
95
|
this.repositoryService = repositoryService;
|
|
75
96
|
this.deviceConfigurationService = deviceConfigurationService;
|
|
76
97
|
this.inventoryService = inventoryService;
|
|
77
|
-
this.reloadingConfig = false;
|
|
98
|
+
this.reloadingConfig = signal(false, ...(ngDevMode ? [{ debugName: "reloadingConfig" }] : /* istanbul ignore next */ []));
|
|
99
|
+
this.latestOperation = signal(undefined, ...(ngDevMode ? [{ debugName: "latestOperation" }] : /* istanbul ignore next */ []));
|
|
100
|
+
this.form = new FormGroup({
|
|
101
|
+
config: new FormControl(''),
|
|
102
|
+
language: new FormControl(PLAINTEXT_OPTION)
|
|
103
|
+
});
|
|
104
|
+
this.editorLanguages = TEXT_EDITOR_LANGUAGES;
|
|
105
|
+
this.editorLanguageValue = toSignal(this.form.controls.language.valueChanges, {
|
|
106
|
+
initialValue: PLAINTEXT_OPTION
|
|
107
|
+
});
|
|
108
|
+
this.editorLanguage = computed(() => this.editorLanguageValue()?.value ?? 'plaintext', ...(ngDevMode ? [{ debugName: "editorLanguage" }] : /* istanbul ignore next */ []));
|
|
109
|
+
this.savingConfig = computed(() => {
|
|
110
|
+
const operation = this.latestOperation();
|
|
111
|
+
return operation
|
|
112
|
+
? !!operation.c8y_Configuration &&
|
|
113
|
+
(operation.status === OperationStatus.PENDING ||
|
|
114
|
+
operation.status === OperationStatus.EXECUTING)
|
|
115
|
+
: false;
|
|
116
|
+
}, ...(ngDevMode ? [{ debugName: "savingConfig" }] : /* istanbul ignore next */ []));
|
|
117
|
+
// Read-only is driven through editorOptions (not the form control's disabled state) because
|
|
118
|
+
// the editor only applies the disabled state at creation time. computed() keeps the reference
|
|
119
|
+
// stable until read-only actually changes, so the editor does not re-run updateOptions() needlessly.
|
|
120
|
+
this.editorOptions = computed(() => ({
|
|
121
|
+
language: this.editorLanguage(),
|
|
122
|
+
readOnly: this.reloadingConfig() || this.savingConfig(),
|
|
123
|
+
minimap: { enabled: false },
|
|
124
|
+
scrollBeyondLastLine: false
|
|
125
|
+
}), ...(ngDevMode ? [{ debugName: "editorOptions" }] : /* istanbul ignore next */ []));
|
|
126
|
+
this.destroyRef = inject(DestroyRef);
|
|
127
|
+
}
|
|
128
|
+
get configControl() {
|
|
129
|
+
return this.form.controls.config;
|
|
78
130
|
}
|
|
79
131
|
async ngOnInit() {
|
|
80
132
|
await this.load();
|
|
@@ -86,35 +138,30 @@ class TextBasedConfigurationComponent {
|
|
|
86
138
|
this.showTextBasedConfigReload = this.deviceConfigurationService.hasAnySupportedOperation(this.device, [DeviceConfigurationOperation.SEND_CONFIG]);
|
|
87
139
|
this.showTextBasedConfigSave = this.deviceConfigurationService.hasAnySupportedOperation(this.device, [DeviceConfigurationOperation.CONFIG]);
|
|
88
140
|
if (this.device.c8y_Configuration && this.device.c8y_Configuration.config) {
|
|
89
|
-
this.
|
|
141
|
+
this.configControl.setValue(this.device.c8y_Configuration.config);
|
|
90
142
|
}
|
|
91
143
|
}
|
|
92
144
|
async loadOperation() {
|
|
93
145
|
const operation = await this.repositoryService.getLastConfigUpdateOperation(this.device.id);
|
|
94
146
|
if (operation !== null) {
|
|
95
|
-
this.reloadingConfig
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
147
|
+
this.reloadingConfig.set(!!operation.c8y_SendConfiguration &&
|
|
148
|
+
(operation.status === OperationStatus.PENDING ||
|
|
149
|
+
operation.status === OperationStatus.EXECUTING));
|
|
150
|
+
this.repositoryService
|
|
151
|
+
.observeOperation(operation)
|
|
152
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
153
|
+
.subscribe(operationUpdate => {
|
|
100
154
|
if (operationUpdate.status === OperationStatus.PENDING ||
|
|
101
155
|
operationUpdate.status === OperationStatus.EXECUTING) {
|
|
102
|
-
this.latestOperation
|
|
156
|
+
this.latestOperation.set(operationUpdate);
|
|
103
157
|
}
|
|
104
158
|
else
|
|
105
|
-
this.latestOperation
|
|
159
|
+
this.latestOperation.set(null);
|
|
106
160
|
});
|
|
107
161
|
}
|
|
108
162
|
}
|
|
109
|
-
get savingConfig() {
|
|
110
|
-
return this.latestOperation
|
|
111
|
-
? !!this.latestOperation.c8y_Configuration &&
|
|
112
|
-
(this.latestOperation.status === OperationStatus.PENDING ||
|
|
113
|
-
this.latestOperation.status === OperationStatus.EXECUTING)
|
|
114
|
-
: false;
|
|
115
|
-
}
|
|
116
163
|
async reloadConfiguration() {
|
|
117
|
-
this.reloadingConfig
|
|
164
|
+
this.reloadingConfig.set(true);
|
|
118
165
|
const operationCfg = await this.repositoryService.createTextBasedConfigurationReloadOperation(this.device);
|
|
119
166
|
try {
|
|
120
167
|
this.repositoryService.createObservedOperation(operationCfg).subscribe(operationUpdate => this.onOperationReloadSuccess(operationUpdate), operationUpdate => this.onOperationReloadError(operationUpdate), () => this.onOperationReloadComplete());
|
|
@@ -133,31 +180,31 @@ class TextBasedConfigurationComponent {
|
|
|
133
180
|
}
|
|
134
181
|
}
|
|
135
182
|
onOperationReloadSuccess(operationUpdate) {
|
|
136
|
-
this.latestOperation
|
|
183
|
+
this.latestOperation.set(operationUpdate);
|
|
137
184
|
if (operationUpdate.status === OperationStatus.PENDING) {
|
|
138
185
|
this.alertService.success(gettext('Configuration will be reloaded.'));
|
|
139
186
|
}
|
|
140
187
|
}
|
|
141
188
|
onOperationReloadError(operationUpdate) {
|
|
142
|
-
this.latestOperation
|
|
143
|
-
this.reloadingConfig
|
|
189
|
+
this.latestOperation.set(operationUpdate);
|
|
190
|
+
this.reloadingConfig.set(false);
|
|
144
191
|
}
|
|
145
192
|
async onOperationReloadComplete() {
|
|
146
193
|
await this.loadDevice();
|
|
147
|
-
this.
|
|
148
|
-
this.reloadingConfig
|
|
194
|
+
this.configControl.setValue(this.device.c8y_Configuration.config);
|
|
195
|
+
this.reloadingConfig.set(false);
|
|
149
196
|
}
|
|
150
197
|
onOperationUpdateSuccess(operationUpdate) {
|
|
151
|
-
this.latestOperation
|
|
198
|
+
this.latestOperation.set(operationUpdate);
|
|
152
199
|
if (operationUpdate.status === OperationStatus.PENDING) {
|
|
153
200
|
this.alertService.success(gettext('Configuration will be updated.'));
|
|
154
201
|
}
|
|
155
202
|
}
|
|
156
203
|
onOperationUpdateError(operationUpdate) {
|
|
157
|
-
this.latestOperation
|
|
204
|
+
this.latestOperation.set(operationUpdate);
|
|
158
205
|
}
|
|
159
206
|
onOperationUpdateComplete() {
|
|
160
|
-
this.device.c8y_Configuration.config = this.
|
|
207
|
+
this.device.c8y_Configuration.config = this.configControl.value;
|
|
161
208
|
}
|
|
162
209
|
async loadDevice() {
|
|
163
210
|
this.device = (await this.inventoryService.detail(this.device.id, {
|
|
@@ -165,11 +212,19 @@ class TextBasedConfigurationComponent {
|
|
|
165
212
|
})).data;
|
|
166
213
|
}
|
|
167
214
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: TextBasedConfigurationComponent, deps: [{ token: i1.ActivatedRoute }, { token: i2.AlertService }, { token: i3.RepositoryService }, { token: DeviceConfigurationService }, { token: i3$1.InventoryService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
168
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: TextBasedConfigurationComponent, isStandalone: true, selector: "c8y-text-based-configuration", ngImport: i0, template: "<div
|
|
215
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: TextBasedConfigurationComponent, isStandalone: true, selector: "c8y-text-based-configuration", ngImport: i0, template: "<div\n class=\"d-flex d-col fit-h min-height-0\"\n [formGroup]=\"form\"\n>\n <fieldset class=\"card-block bg-level-1 fit-w\">\n <div class=\"content-flex-50 d-flex a-i-center\">\n <label\n class=\"m-r-8 flex-no-shrink\"\n for=\"textCfgEditorLanguage\"\n translate\n >\n Language\n </label>\n <c8y-select\n aria-label=\"{{ 'Editor language' | translate }}\"\n id=\"textCfgEditorLanguage\"\n [items]=\"editorLanguages\"\n formControlName=\"language\"\n ></c8y-select>\n <div class=\"m-l-auto d-flex\">\n @if (showTextBasedConfigReload) {\n <button\n class=\"btn btn-default btn-sm a-s-center m-t-8 m-b-8\"\n title=\"{{ 'Get configuration from device' | translate }}\"\n type=\"button\"\n (click)=\"reloadConfiguration()\"\n [disabled]=\"reloadingConfig() || savingConfig()\"\n >\n @if (reloadingConfig()) {\n <i\n class=\"m-r-4\"\n c8yIcon=\"refresh\"\n [ngClass]=\"{ 'icon-spin': reloadingConfig() }\"\n ></i>\n }\n @if (!reloadingConfig()) {\n <i\n class=\"m-r-4\"\n c8yIcon=\"download\"\n ></i>\n }\n\n {{ 'Get configuration from device' | translate }}\n </button>\n }\n </div>\n </div>\n </fieldset>\n <div class=\"p-relative flex-grow min-height-0\">\n <c8y-editor\n class=\"p-absolute top-0 left-0 fit-w fit-h\"\n formControlName=\"config\"\n [editorOptions]=\"editorOptions()\"\n ></c8y-editor>\n </div>\n @if (latestOperation() !== undefined) {\n <c8y-operation-details\n class=\"bg-level-2 p-0\"\n [operation]=\"latestOperation()\"\n ></c8y-operation-details>\n }\n @if (showTextBasedConfigSave) {\n <div class=\"card-footer flex-no-shrink fit-w separator\">\n <button\n class=\"btn btn-primary\"\n id=\"send-config-btn\"\n type=\"button\"\n (click)=\"updateConfiguration(configControl.value)\"\n [disabled]=\"reloadingConfig() || savingConfig() || !configControl.value\"\n [ngClass]=\"{ 'btn-pending': savingConfig() }\"\n >\n @if (!savingConfig()) {\n <span title=\"{{ 'Send' | translate }}\">\n {{ 'Send configuration to device' | translate }}\n </span>\n }\n @if (savingConfig()) {\n <span title=\"{{ 'Sending\u2026' | translate }}\">\n {{ 'Sending\u2026' | translate }}\n </span>\n }\n </button>\n </div>\n }\n</div>\n", dependencies: [{ kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: EditorComponent, selector: "c8y-editor", inputs: ["editorOptions", "theme"], outputs: ["editorInit"] }, { kind: "component", type: OperationDetailsComponent, selector: "c8y-operation-details", inputs: ["operation"] }, { kind: "component", type: SelectComponent, selector: "c8y-select", inputs: ["placeholder", "items", "selected", "container", "multi", "canSelectWithSpace", "disabled", "autoClose", "insideClick", "required", "canDeselect", "name", "icon", "filterItems"], outputs: ["onSelect", "onDeselect", "onIconClick"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
|
|
169
216
|
}
|
|
170
217
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: TextBasedConfigurationComponent, decorators: [{
|
|
171
218
|
type: Component,
|
|
172
|
-
args: [{ selector: 'c8y-text-based-configuration', imports: [
|
|
219
|
+
args: [{ selector: 'c8y-text-based-configuration', imports: [
|
|
220
|
+
IconDirective,
|
|
221
|
+
NgClass,
|
|
222
|
+
ReactiveFormsModule,
|
|
223
|
+
EditorComponent,
|
|
224
|
+
OperationDetailsComponent,
|
|
225
|
+
C8yTranslatePipe,
|
|
226
|
+
SelectComponent
|
|
227
|
+
], template: "<div\n class=\"d-flex d-col fit-h min-height-0\"\n [formGroup]=\"form\"\n>\n <fieldset class=\"card-block bg-level-1 fit-w\">\n <div class=\"content-flex-50 d-flex a-i-center\">\n <label\n class=\"m-r-8 flex-no-shrink\"\n for=\"textCfgEditorLanguage\"\n translate\n >\n Language\n </label>\n <c8y-select\n aria-label=\"{{ 'Editor language' | translate }}\"\n id=\"textCfgEditorLanguage\"\n [items]=\"editorLanguages\"\n formControlName=\"language\"\n ></c8y-select>\n <div class=\"m-l-auto d-flex\">\n @if (showTextBasedConfigReload) {\n <button\n class=\"btn btn-default btn-sm a-s-center m-t-8 m-b-8\"\n title=\"{{ 'Get configuration from device' | translate }}\"\n type=\"button\"\n (click)=\"reloadConfiguration()\"\n [disabled]=\"reloadingConfig() || savingConfig()\"\n >\n @if (reloadingConfig()) {\n <i\n class=\"m-r-4\"\n c8yIcon=\"refresh\"\n [ngClass]=\"{ 'icon-spin': reloadingConfig() }\"\n ></i>\n }\n @if (!reloadingConfig()) {\n <i\n class=\"m-r-4\"\n c8yIcon=\"download\"\n ></i>\n }\n\n {{ 'Get configuration from device' | translate }}\n </button>\n }\n </div>\n </div>\n </fieldset>\n <div class=\"p-relative flex-grow min-height-0\">\n <c8y-editor\n class=\"p-absolute top-0 left-0 fit-w fit-h\"\n formControlName=\"config\"\n [editorOptions]=\"editorOptions()\"\n ></c8y-editor>\n </div>\n @if (latestOperation() !== undefined) {\n <c8y-operation-details\n class=\"bg-level-2 p-0\"\n [operation]=\"latestOperation()\"\n ></c8y-operation-details>\n }\n @if (showTextBasedConfigSave) {\n <div class=\"card-footer flex-no-shrink fit-w separator\">\n <button\n class=\"btn btn-primary\"\n id=\"send-config-btn\"\n type=\"button\"\n (click)=\"updateConfiguration(configControl.value)\"\n [disabled]=\"reloadingConfig() || savingConfig() || !configControl.value\"\n [ngClass]=\"{ 'btn-pending': savingConfig() }\"\n >\n @if (!savingConfig()) {\n <span title=\"{{ 'Send' | translate }}\">\n {{ 'Send configuration to device' | translate }}\n </span>\n }\n @if (savingConfig()) {\n <span title=\"{{ 'Sending\u2026' | translate }}\">\n {{ 'Sending\u2026' | translate }}\n </span>\n }\n </button>\n </div>\n }\n</div>\n" }]
|
|
173
228
|
}], ctorParameters: () => [{ type: i1.ActivatedRoute }, { type: i2.AlertService }, { type: i3.RepositoryService }, { type: DeviceConfigurationService }, { type: i3$1.InventoryService }] });
|
|
174
229
|
|
|
175
230
|
class DeviceConfigurationGuard {
|
|
@@ -257,20 +312,10 @@ function mimeForFilename(filename) {
|
|
|
257
312
|
}
|
|
258
313
|
/** Sentinel value meaning "derive language from filename". */
|
|
259
314
|
const AUTO_LANGUAGE = 'auto';
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
{ value: 'typescript', label: gettext('TypeScript') },
|
|
265
|
-
{ value: 'css', label: gettext('CSS') },
|
|
266
|
-
{ value: 'html', label: gettext('HTML') },
|
|
267
|
-
{ value: 'yaml', label: gettext('YAML') },
|
|
268
|
-
{ value: 'markdown', label: gettext('Markdown') },
|
|
269
|
-
{ value: 'xml', label: gettext('XML') },
|
|
270
|
-
{ value: 'ini', label: gettext('INI / TOML / Properties') },
|
|
271
|
-
{ value: 'shell', label: gettext('Shell') },
|
|
272
|
-
{ value: 'plaintext', label: gettext('Plain text') }
|
|
273
|
-
];
|
|
315
|
+
const AUTO_LANGUAGE_OPTION = {
|
|
316
|
+
value: AUTO_LANGUAGE,
|
|
317
|
+
label: gettext('Auto (from filename)')
|
|
318
|
+
};
|
|
274
319
|
class ConfigurationDetailComponent {
|
|
275
320
|
constructor() {
|
|
276
321
|
this.repositoryService = inject(RepositoryService);
|
|
@@ -298,7 +343,7 @@ class ConfigurationDetailComponent {
|
|
|
298
343
|
editorFilename: new FormControl('', [
|
|
299
344
|
Validators.pattern(ValidationPattern.rules.noWhiteSpaceOnly.pattern)
|
|
300
345
|
]),
|
|
301
|
-
editorLanguage: new FormControl(
|
|
346
|
+
editorLanguage: new FormControl(AUTO_LANGUAGE_OPTION),
|
|
302
347
|
editorContent: new FormControl('')
|
|
303
348
|
});
|
|
304
349
|
this.configurationTypeMO = {};
|
|
@@ -321,7 +366,7 @@ class ConfigurationDetailComponent {
|
|
|
321
366
|
initialValue: ''
|
|
322
367
|
});
|
|
323
368
|
this.editorLanguageValue = toSignal(this.form.controls.editorLanguage.valueChanges, {
|
|
324
|
-
initialValue:
|
|
369
|
+
initialValue: AUTO_LANGUAGE_OPTION
|
|
325
370
|
});
|
|
326
371
|
/** User's manual pick (when not "auto") wins over auto-detection from filename. */
|
|
327
372
|
this.editorLanguage = computed(() => {
|
|
@@ -330,7 +375,7 @@ class ConfigurationDetailComponent {
|
|
|
330
375
|
? detectLanguage(this.editorFilenameValue() ?? '')
|
|
331
376
|
: picked;
|
|
332
377
|
}, ...(ngDevMode ? [{ debugName: "editorLanguage" }] : /* istanbul ignore next */ []));
|
|
333
|
-
this.editorLanguages = EDITOR_LANGUAGES;
|
|
378
|
+
this.editorLanguages = [AUTO_LANGUAGE_OPTION, ...EDITOR_LANGUAGES];
|
|
334
379
|
this.submitButtonTitle = computed(() => this.mo?.id ? gettext('Update configuration') : gettext('Add configuration'), ...(ngDevMode ? [{ debugName: "submitButtonTitle" }] : /* istanbul ignore next */ []));
|
|
335
380
|
this.form.controls.uploadChoice.valueChanges.pipe(takeUntilDestroyed()).subscribe(choice => {
|
|
336
381
|
const ctrl = this.form.controls.editorFilename;
|