- @if (resourcesFormArray.length) {
- @for (resourceControl of resourcesControls; track resourceControl; let i = $index) {
-
+
+
+
+
+
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/html/html-container-settings.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/html/html-container-settings.component.scss
index d2385459e0..c2db82139d 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/html/html-container-settings.component.scss
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/html/html-container-settings.component.scss
@@ -14,15 +14,115 @@
* limitations under the License.
*/
- :host {
- &.tb-html-container-settings {
+.tb-html-container-settings {
+ height: 100%;
+}
+
+.tb-html-container-settings .tb-html-container-settings-panel, .tb-html-container-settings-panel {
+ position: relative;
+ background: #fff;
+ .mat-mdc-tab-body-wrapper {
+ position: relative;
+ top: 0;
+ flex: 1;
+ }
+ .tb-action-expand-button {
+ position: absolute;
+ top: 4px;
+ right: 0;
+ z-index: 2;
+ }
+ .gutter {
+ display: none;
+ background-color: #eee;
+ background-repeat: no-repeat;
+ background-position: 50%;
+ &.gutter-horizontal {
+ cursor: col-resize;
+ background-image: url("../../../../../../../../../assets/split.js/grips/vertical.png");
+ }
+ }
+ .tb-js-func {
+ &:not(.tb-fullscreen) {
+ &.tb-hide-brackets {
+ padding-bottom: 0;
+ }
+ }
+ }
+ .tb-html {
+ position: relative;
+ &:not(.tb-fullscreen) {
+ padding-bottom: 0;
+ }
+ .tb-html-toolbar {
+ position: absolute;
+ top: 0;
+ right: 8px;
+ z-index: 8;
+ .tb-title {
+ display: none;
+ }
+ }
+ .tb-html-content-panel {
+ border-top: none;
+ height: 100%;
+ }
+ }
+ .tb-css {
+ position: relative;
+ &:not(.tb-fullscreen) {
+ .tb-css-content-panel {
+ margin: 0;
+ }
+ }
+ .tb-css-toolbar {
+ position: absolute;
+ top: 0;
+ right: 8px;
+ z-index: 8;
+ .tb-title {
+ display: none;
+ }
+ }
+ .tb-css-content-panel {
+ border-top: none;
height: 100%;
- ::ng-deep {
- .mat-mdc-tab-body-wrapper {
- position: relative;
- top: 0;
- flex: 1;
+ }
+ }
+ &.tb-fullscreen {
+ padding: 8px;
+ gap: 8px;
+ .tb-action-expand-button {
+ position: relative;
+ top: 0;
+ right: 0;
+ }
+ .gutter {
+ display: block;
+ }
+ .tb-content {
+ border: 1px solid #c0c0c0;
+ .tb-html {
+ .tb-html-content-panel {
+ border: none;
+ }
+ }
+ .tb-css {
+ .tb-css-content-panel {
+ border: none;
+ }
+ }
+ .tb-js-func {
+ padding-top: 8px;
+ .tb-js-func-toolbar {
+ padding: 0 5px;
+ }
+ .tb-js-func-panel {
+ border-left: none;
+ border-right: none;
+ border-bottom: none;
}
}
}
+ }
}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/html/html-container-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/html/html-container-settings.component.ts
index 116d69d468..121362ef57 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/html/html-container-settings.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/html/html-container-settings.component.ts
@@ -14,7 +14,18 @@
/// limitations under the License.
///
-import { Component, DestroyRef, forwardRef, HostBinding, Input, OnInit } from '@angular/core';
+import {
+ AfterViewInit,
+ Component,
+ DestroyRef,
+ ElementRef,
+ forwardRef,
+ HostBinding,
+ Input,
+ OnInit,
+ ViewChild,
+ ViewEncapsulation
+} from '@angular/core';
import { WidgetResource } from '@shared/models/widget.models';
import {
ControlValueAccessor,
@@ -28,7 +39,8 @@ import {
Validators
} from '@angular/forms';
import {
- ContainerFunctionEditorCompleter,
+ AngularContainerFunctionEditorCompleter,
+ HTMLContainerFunctionEditorCompleter,
HtmlContainerWidgetSettings,
HtmlContainerWidgetType
} from '@home/components/widget/lib/html/html-container-widget.models';
@@ -52,23 +64,39 @@ import { WidgetService } from '@core/http/widget.service';
multi: true,
}
],
+ encapsulation: ViewEncapsulation.None,
standalone: false
})
-export class HtmlContainerSettingsComponent implements OnInit, ControlValueAccessor, Validator {
+export class HtmlContainerSettingsComponent implements OnInit, AfterViewInit, ControlValueAccessor, Validator {
HtmlContainerWidgetType = HtmlContainerWidgetType;
functionScopeVariables = this.widgetService.getWidgetScopeVariables();
- containerFunctionEditorCompleter = ContainerFunctionEditorCompleter;
+ get containerFunctionEditorCompleter() {
+ return this.htmlContainerSettingsForm.get('type').value === HtmlContainerWidgetType.ANGULAR
+ ? AngularContainerFunctionEditorCompleter
+ : HTMLContainerFunctionEditorCompleter;
+ }
@HostBinding('class')
hostClass = 'tb-html-container-settings';
+ @ViewChild('leftPanel', { read: ElementRef })
+ leftPanelElmRef!: ElementRef;
+
+ @ViewChild('rightPanel', { read: ElementRef })
+ rightPanelElmRef!: ElementRef;
+
@Input()
disabled: boolean;
+ fullscreen = false;
+
+ tabsAnimationDuration = '500ms';
+
htmlContainerSettingsForm: UntypedFormGroup;
+
private modelValue: HtmlContainerWidgetSettings;
constructor(private fb: UntypedFormBuilder,
@@ -102,11 +130,26 @@ export class HtmlContainerSettingsComponent implements OnInit, ControlValueAcces
});
}
+ ngAfterViewInit(): void {
+ if (this.leftPanelElmRef && this.rightPanelElmRef) {
+ this.initSplitLayout(this.leftPanelElmRef.nativeElement,
+ this.rightPanelElmRef.nativeElement);
+ }
+ }
+
+ private initSplitLayout(leftPanel: any, rightPanel: any) {
+ Split([leftPanel, rightPanel], {
+ sizes: [50, 50],
+ gutterSize: 8,
+ cursor: 'col-resize'
+ });
+ }
+
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
- registerOnTouched(fn: any): void {
+ registerOnTouched(_fn: any): void {
}
setDisabledState(isDisabled: boolean): void {
@@ -150,7 +193,15 @@ export class HtmlContainerSettingsComponent implements OnInit, ControlValueAcces
this.resourcesFormArray.removeAt(index);
}
- private propagateChange = (v: any) => { };
+ toggleFullScreen(): void {
+ this.fullscreen = !this.fullscreen;
+ this.tabsAnimationDuration = '0ms';
+ setTimeout(() => {
+ this.tabsAnimationDuration = '500ms';
+ });
+ }
+
+ private propagateChange = (_v: any) => { };
private updateModel() {
this.modelValue = this.htmlContainerSettingsForm.value;
diff --git a/ui-ngx/src/app/shared/import-export/import-export.models.ts b/ui-ngx/src/app/shared/import-export/import-export.models.ts
index 2476922bf9..ab9def1697 100644
--- a/ui-ngx/src/app/shared/import-export/import-export.models.ts
+++ b/ui-ngx/src/app/shared/import-export/import-export.models.ts
@@ -210,7 +210,7 @@ function splitCSV(str: string, sep: string): string[] {
foo = foo.shift().split(sep).concat(foo);
}
} else {
- foo[x].replace(/""/g, '"');
+ foo[x] = foo[x].replace(/""/g, '"');
}
}
return foo;
diff --git a/ui-ngx/src/app/shared/models/page/page-link.ts b/ui-ngx/src/app/shared/models/page/page-link.ts
index 023821587b..eb2c059c2a 100644
--- a/ui-ngx/src/app/shared/models/page/page-link.ts
+++ b/ui-ngx/src/app/shared/models/page/page-link.ts
@@ -84,11 +84,25 @@ export function sortItems(item1: any, item2: any, property: string, asc: boolean
result = item1Value - item2Value;
} else if (item1Type === 'string' && item2Type === 'string') {
result = item1Value.localeCompare(item2Value);
- } else if ((item1Type === 'boolean' && item2Type === 'boolean') || (item1Type !== item2Type)) {
- if (item1Value && !item2Value) {
+ } else if (item1Type === 'boolean' && item2Type === 'boolean') {
+ result = item1Value ? 1 : -1;
+ } else if (item1Type !== item2Type) {
+ const item1Empty = item1Value === null || item1Value === undefined || item1Value === '';
+ const item2Empty = item2Value === null || item2Value === undefined || item2Value === '';
+ if (!item1Empty && item2Empty) {
result = 1;
- } else if (!item1Value && item2Value) {
+ } else if (item1Empty && !item2Empty) {
result = -1;
+ } else if (!item1Empty && !item2Empty) {
+ const str1 = String(item1Value).trim();
+ const str2 = String(item2Value).trim();
+ const num1 = str1.length ? Number(str1) : NaN;
+ const num2 = str2.length ? Number(str2) : NaN;
+ if (!isNaN(num1) && !isNaN(num2)) {
+ result = num1 - num2;
+ } else {
+ result = String(item1Value).localeCompare(String(item2Value));
+ }
}
}
}