+
diff --git a/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.scss b/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.scss
index 2dd61e2722..ee1ca74151 100644
--- a/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.scss
+++ b/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.scss
@@ -13,11 +13,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+@import '../../../../../scss/constants';
+
:host {
+ display: grid;
+ height: 100%;
+ max-width: 100%;
+ max-height: 100vh;
+ grid-template-rows: min-content minmax(auto, 1fr) min-content;
+
+ @media #{$mat-gt-xs} {
+ .mat-mdc-dialog-content {
+ max-height: 80vh;
+ }
+ }
+
.tb-event-content {
- width: 100%;
min-width: 400px;
- height: 100%;
- min-height: 50px;
+ &.border {
+ border: 1px solid #c0c0c0;
+ }
+ @media #{$mat-xs} {
+ min-width: 100%;
+ }
}
}
diff --git a/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts b/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts
index 2ae62dd890..9ca6ad8b43 100644
--- a/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts
+++ b/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts
@@ -23,7 +23,7 @@ import { Ace } from 'ace-builds';
import { DialogComponent } from '@shared/components/dialog.component';
import { Router } from '@angular/router';
import { ContentType, contentTypesMap } from '@shared/models/constants';
-import { getAce } from '@shared/models/ace/ace.models';
+import { getAce, updateEditorSize } from '@shared/models/ace/ace.models';
import { Observable } from 'rxjs/internal/Observable';
import { beautifyJs } from '@shared/models/beautify.models';
import { of } from 'rxjs';
@@ -40,40 +40,38 @@ export interface EventContentDialogData {
templateUrl: './event-content-dialog.component.html',
styleUrls: ['./event-content-dialog.component.scss']
})
-export class EventContentDialogComponent extends DialogComponent
implements OnInit, OnDestroy {
+export class EventContentDialogComponent extends DialogComponent implements OnInit, OnDestroy {
@ViewChild('eventContentEditor', {static: true})
eventContentEditorElmRef: ElementRef;
- content: string;
title: string;
- contentType: ContentType;
- aceEditor: Ace.Editor;
+ showBorder = false;
+
+ private contentType: ContentType;
+ private aceEditor: Ace.Editor;
constructor(protected store: Store,
protected router: Router,
@Inject(MAT_DIALOG_DATA) public data: EventContentDialogData,
- public dialogRef: MatDialogRef,
+ protected dialogRef: MatDialogRef,
private renderer: Renderer2) {
super(store, router, dialogRef);
}
ngOnInit(): void {
- this.content = this.data.content;
this.title = this.data.title;
this.contentType = this.data.contentType;
- this.createEditor(this.eventContentEditorElmRef, this.content);
+ this.createEditor(this.eventContentEditorElmRef, this.data.content);
}
ngOnDestroy(): void {
- if (this.aceEditor) {
- this.aceEditor.destroy();
- }
+ this.aceEditor?.destroy();
super.ngOnDestroy();
}
- isJson(str) {
+ private isJson(str: string) {
try {
return isLiteralObject(JSON.parse(str));
} catch (e) {
@@ -81,78 +79,53 @@ export class EventContentDialogComponent extends DialogComponent = null;
if (this.contentType) {
mode = contentTypesMap.get(this.contentType).code;
if (this.contentType === ContentType.JSON && content) {
- content$ = beautifyJs(content, {indent_size: 4});
+ content$ = beautifyJs(content, {indent_size: 2});
} else if (this.contentType === ContentType.BINARY && content) {
try {
const decodedData = base64toString(content);
if (this.isJson(decodedData)) {
mode = 'json';
- content$ = beautifyJs(decodedData, {indent_size: 4});
+ content$ = beautifyJs(decodedData, {indent_size: 2});
} else {
content$ = of(decodedData);
}
- } catch (e) {}
+ } catch (e) {/**/}
}
}
if (!content$) {
content$ = of(content);
}
- content$.subscribe(
- (processedContent) => {
- let editorOptions: Partial = {
- mode: `ace/mode/${mode}`,
- theme: 'ace/theme/github',
- showGutter: false,
- showPrintMargin: false,
- readOnly: true
- };
-
- const advancedOptions = {
- enableSnippets: false,
- enableBasicAutocompletion: false,
- enableLiveAutocompletion: false
- };
-
- editorOptions = {...editorOptions, ...advancedOptions};
- getAce().subscribe(
- (ace) => {
- this.aceEditor = ace.edit(editorElement, editorOptions);
- this.aceEditor.session.setUseWrapMode(false);
- this.aceEditor.setValue(processedContent, -1);
- this.updateEditorSize(editorElement, processedContent, this.aceEditor);
- }
- );
- }
- );
- }
-
- updateEditorSize(editorElement: any, content: string, editor: Ace.Editor) {
- let newHeight = 400;
- let newWidth = 600;
- if (content && content.length > 0) {
- const lines = content.split('\n');
- newHeight = 17 * lines.length + 16;
- let maxLineLength = 0;
- lines.forEach((row) => {
- const line = row.replace(/\t/g, ' ').replace(/\n/g, '');
- const lineLength = line.length;
- maxLineLength = Math.max(maxLineLength, lineLength);
- });
- newWidth = 9 * maxLineLength + 16;
- }
- // newHeight = Math.min(400, newHeight);
- this.renderer.setStyle(editorElement, 'minHeight', newHeight.toString() + 'px');
- this.renderer.setStyle(editorElement, 'height', newHeight.toString() + 'px');
- this.renderer.setStyle(editorElement, 'width', newWidth.toString() + 'px');
- editor.resize();
+ content$.subscribe((processedContent) => {
+ const isJSON = mode === 'json' && processedContent !== '{}';
+ this.showBorder = isJSON;
+ const editorOptions: Partial = {
+ mode: `ace/mode/${mode}`,
+ theme: 'ace/theme/github',
+ showGutter: isJSON,
+ showFoldWidgets: true,
+ foldStyle: 'markbeginend',
+ showPrintMargin: false,
+ readOnly: true,
+ enableSnippets: false,
+ enableBasicAutocompletion: false,
+ enableLiveAutocompletion: false,
+ };
+ getAce().subscribe(
+ (ace) => {
+ this.aceEditor = ace.edit(editorElement, editorOptions);
+ this.aceEditor.session.setUseWrapMode(false);
+ this.aceEditor.setValue(processedContent, -1);
+ updateEditorSize(editorElement, processedContent, this.aceEditor, this.renderer, {showGutter: isJSON});
+ }
+ )
+ });
}
-
}
diff --git a/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts b/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts
index dc89f05fde..05511095cf 100644
--- a/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts
+++ b/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts
@@ -14,7 +14,7 @@
/// limitations under the License.
///
-import { AfterViewInit, Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
+import { Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import { Observable, ReplaySubject, Subscription, throwError } from 'rxjs';
import { debounceTime, map, mergeMap, share } from 'rxjs/operators';
@@ -46,7 +46,7 @@ import { CalculatedFieldsService } from "@core/http/calculated-fields.service";
}
]
})
-export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, AfterViewInit, OnDestroy {
+export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, OnDestroy {
entitySubtypeListFormGroup: FormGroup;
@@ -119,7 +119,7 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit,
private dirty = false;
- private propagateChange = (v: any) => { };
+ private propagateChange = (_v: any) => { };
private hasPageDataEntitySubTypes = new Set([
EntityType.ALARM,
@@ -225,9 +225,6 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit,
);
}
- ngAfterViewInit(): void {
- }
-
ngOnDestroy(): void {
if (this.broadcastSubscription) {
this.broadcastSubscription.unsubscribe();
@@ -335,7 +332,7 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit,
subTypesPagesObservable = this.alarmService.getAlarmTypes(pageLink, {ignoreLoading: true});
break;
case EntityType.CALCULATED_FIELD:
- subTypesCfPagesObservable = this.calculatedFieldsService.getAlarmRuleNames(pageLink, CalculatedFieldType.ALARM, {ignoreLoading: true});
+ subTypesCfPagesObservable = this.calculatedFieldsService.getCalculatedFieldNames(pageLink, CalculatedFieldType.ALARM, {ignoreLoading: true});
}
if (subTypesPagesObservable) {
this.entitySubtypes = subTypesPagesObservable.pipe(
diff --git a/ui-ngx/src/app/shared/components/hint-tooltip-icon.component.scss b/ui-ngx/src/app/shared/components/hint-tooltip-icon.component.scss
index 2abc704ece..8b1a9ef4d7 100644
--- a/ui-ngx/src/app/shared/components/hint-tooltip-icon.component.scss
+++ b/ui-ngx/src/app/shared/components/hint-tooltip-icon.component.scss
@@ -17,7 +17,6 @@
display: flex;
flex-direction: row;
align-items: center;
- gap: 4px;
}
:host {
diff --git a/ui-ngx/src/app/shared/components/json-object-view.component.ts b/ui-ngx/src/app/shared/components/json-object-view.component.ts
index e549dd03c1..20f8660279 100644
--- a/ui-ngx/src/app/shared/components/json-object-view.component.ts
+++ b/ui-ngx/src/app/shared/components/json-object-view.component.ts
@@ -15,14 +15,11 @@
///
import { Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, Renderer2, ViewChild } from '@angular/core';
-import { NG_VALUE_ACCESSOR } from '@angular/forms';
+import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Ace } from 'ace-builds';
-import { coerceBooleanProperty } from '@angular/cdk/coercion';
-import { Store } from '@ngrx/store';
-import { AppState } from '@core/core.state';
-import { RafService } from '@core/services/raf.service';
import { isDefinedAndNotNull, isUndefined } from '@core/utils';
-import { getAce } from '@shared/models/ace/ace.models';
+import { getAce, updateEditorSize } from '@shared/models/ace/ace.models';
+import { coerceBoolean } from '@shared/decorators/coercion';
@Component({
selector: 'tb-json-object-view',
@@ -36,7 +33,7 @@ import { getAce } from '@shared/models/ace/ace.models';
}
]
})
-export class JsonObjectViewComponent implements OnInit, OnDestroy {
+export class JsonObjectViewComponent implements OnInit, OnDestroy, ControlValueAccessor {
@ViewChild('jsonViewer', {static: true})
jsonViewerElmRef: ElementRef;
@@ -55,96 +52,54 @@ export class JsonObjectViewComponent implements OnInit, OnDestroy {
@Input() sort: (key: string, value: any) => any;
- private widthValue: boolean;
-
- get autoWidth(): boolean {
- return this.widthValue;
- }
-
@Input()
- set autoWidth(value: boolean) {
- this.widthValue = coerceBooleanProperty(value);
- }
-
- private heigthValue: boolean;
-
- get autoHeight(): boolean {
- return this.heigthValue;
- }
+ @coerceBoolean()
+ autoWidth: boolean
@Input()
- set autoHeight(value: boolean) {
- this.heigthValue = coerceBooleanProperty(value);
- }
+ @coerceBoolean()
+ autoHeight: boolean
- constructor(public elementRef: ElementRef,
- protected store: Store,
- private raf: RafService,
- private renderer: Renderer2) {
+ constructor(private renderer: Renderer2) {
}
ngOnInit(): void {
this.viewerElement = this.jsonViewerElmRef.nativeElement;
- let editorOptions: Partial = {
+ const editorOptions: Partial = {
mode: 'ace/mode/java',
theme: 'ace/theme/github',
showGutter: false,
showPrintMargin: false,
- readOnly: true
- };
-
- const advancedOptions = {
+ readOnly: true,
enableSnippets: false,
enableBasicAutocompletion: false,
enableLiveAutocompletion: false
};
- editorOptions = {...editorOptions, ...advancedOptions};
getAce().subscribe(
(ace) => {
this.jsonViewer = ace.edit(this.viewerElement, editorOptions);
this.jsonViewer.session.setUseWrapMode(false);
this.jsonViewer.setValue(this.contentValue ? this.contentValue : '', -1);
- if (this.contentValue && (this.widthValue || this.heigthValue)) {
- this.updateEditorSize(this.viewerElement, this.contentValue, this.jsonViewer);
+ if (this.contentValue && (this.autoWidth || this.autoHeight)) {
+ updateEditorSize(this.viewerElement, this.contentValue, this.jsonViewer, this.renderer, {
+ ignoreHeight: !this.autoHeight,
+ ignoreWidth: !this.autoWidth
+ });
}
}
);
}
ngOnDestroy(): void {
- if (this.jsonViewer) {
- this.jsonViewer.destroy();
- }
+ this.jsonViewer?.destroy();
}
- updateEditorSize(editorElement: any, content: string, editor: Ace.Editor) {
- let newHeight = 200;
- let newWidth = 600;
- if (content && content.length > 0) {
- const lines = content.split('\n');
- newHeight = 17 * lines.length + 17;
- let maxLineLength = 0;
- lines.forEach((row) => {
- const line = row.replace(/\t/g, ' ').replace(/\n/g, '');
- const lineLength = line.length;
- maxLineLength = Math.max(maxLineLength, lineLength);
- });
- newWidth = 8 * maxLineLength + 16;
- }
- if (this.heigthValue) {
- this.renderer.setStyle(editorElement, 'height', newHeight.toString() + 'px');
- }
- if (this.widthValue) {
- this.renderer.setStyle(editorElement, 'width', newWidth.toString() + 'px');
- }
- editor.resize();
- }
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
- registerOnTouched(fn: any): void {
+ registerOnTouched(_fn: any): void {
}
writeValue(value: any): void {
@@ -162,8 +117,11 @@ export class JsonObjectViewComponent implements OnInit, OnDestroy {
}
if (this.jsonViewer) {
this.jsonViewer.setValue(this.contentValue ? this.contentValue : '', -1);
- if (this.contentValue && (this.widthValue || this.heigthValue)) {
- this.updateEditorSize(this.viewerElement, this.contentValue, this.jsonViewer);
+ if (this.contentValue && (this.autoWidth || this.autoHeight)) {
+ updateEditorSize(this.viewerElement, this.contentValue, this.jsonViewer, this.renderer, {
+ ignoreHeight: !this.autoHeight,
+ ignoreWidth: !this.autoWidth
+ });
}
}
}
diff --git a/ui-ngx/src/app/shared/import-export/import-dialog-csv.component.ts b/ui-ngx/src/app/shared/import-export/import-dialog-csv.component.ts
index a3d82952cc..90bd9f30ec 100644
--- a/ui-ngx/src/app/shared/import-export/import-dialog-csv.component.ts
+++ b/ui-ngx/src/app/shared/import-export/import-dialog-csv.component.ts
@@ -39,7 +39,7 @@ import {
import { ImportExportService } from '@shared/import-export/import-export.service';
import { TableColumnsAssignmentComponent } from '@shared/import-export/table-columns-assignment.component';
import { Ace } from 'ace-builds';
-import { getAce } from '@shared/models/ace/ace.models';
+import { getAce, updateEditorSize } from '@shared/models/ace/ace.models';
export interface ImportDialogCsvData {
entityType: EntityType;
@@ -283,21 +283,9 @@ export class ImportDialogCsvComponent extends DialogComponent 0) {
- const lines = content.split('\n');
- newHeight = 16 * lines.length + 24;
- }
- const minHeight = Math.min(200, newHeight);
- this.renderer.setStyle(editorElement, 'minHeight', minHeight.toString() + 'px');
- this.renderer.setStyle(editorElement, 'height', newHeight.toString() + 'px');
- editor.resize();
- }
-
}
diff --git a/ui-ngx/src/app/shared/models/ace/ace.models.ts b/ui-ngx/src/app/shared/models/ace/ace.models.ts
index 49cf670989..31b97ff144 100644
--- a/ui-ngx/src/app/shared/models/ace/ace.models.ts
+++ b/ui-ngx/src/app/shared/models/ace/ace.models.ts
@@ -19,6 +19,7 @@ import { Observable } from 'rxjs/internal/Observable';
import { forkJoin, from, of } from 'rxjs';
import { map, mergeMap, tap } from 'rxjs/operators';
import { unwrapModule } from '@core/utils';
+import { Renderer2 } from '@angular/core';
let aceDependenciesLoaded = false;
let aceModule: any;
@@ -98,6 +99,46 @@ export function getAceDiff(): Observable {
}
}
+export function updateEditorSize(editorElement: any, content: string, editor: Ace.Editor, renderer: Renderer2, options?: {
+ showGutter?: boolean,
+ ignoreHeight?: boolean,
+ ignoreWidth?: boolean,
+ setMinHeight?: boolean
+}): void {
+ let newHeight = 200;
+ let newWidth = 600;
+ if (content && content.length > 0) {
+ if (editor.renderer.lineHeight <= 0) {
+ editor.renderer.updateFull(true);
+ }
+ const lines = content.split('\n');
+ newHeight = editor.renderer.lineHeight * lines.length + 16;
+ let maxLineLength = 0;
+ lines.forEach((row) => {
+ const line = row.replace(/\t/g, ' ').replace(/\n/g, '');
+ const lineLength = line.length;
+ maxLineLength = Math.max(maxLineLength, lineLength);
+ });
+ if (options?.showGutter) {
+ maxLineLength += lines.length.toString().length;
+ }
+ newWidth = 10 * maxLineLength + 16;
+ if (options?.showGutter) {
+ newWidth += 32;
+ }
+ }
+ if (!options.ignoreHeight) {
+ renderer.setStyle(editorElement, 'height', newHeight.toString() + 'px');
+ }
+ if (options.setMinHeight) {
+ renderer.setStyle(editorElement, 'minHeight', newHeight.toString() + 'px');
+ }
+ if (!options.ignoreWidth) {
+ renderer.setStyle(editorElement, 'width', newWidth.toString() + 'px');
+ }
+ editor.resize();
+}
+
export class Range implements Ace.Range {
public start: Ace.Point;
diff --git a/ui-ngx/src/app/shared/models/calculated-field.models.ts b/ui-ngx/src/app/shared/models/calculated-field.models.ts
index 5f07374cf8..825c08a69f 100644
--- a/ui-ngx/src/app/shared/models/calculated-field.models.ts
+++ b/ui-ngx/src/app/shared/models/calculated-field.models.ts
@@ -79,6 +79,8 @@ export type CalculatedField =
| CalculatedFieldRelatedEntityAggregation
| CalculatedFieldAlarmRule;
+export type CalculatedFieldInfo = CalculatedField & {entityName: string};
+
export enum CalculatedFieldType {
SIMPLE = 'SIMPLE',
SCRIPT = 'SCRIPT',
diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json
index a85c490c62..e023179dd3 100644
--- a/ui-ngx/src/assets/locale/locale.constant-en_US.json
+++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json
@@ -1108,9 +1108,9 @@
"geofencing" : "Geofencing",
"propagation": "Propagation",
"related-entities-aggregation": "Related entities aggregation",
- "related-entities-aggregation-hint": "Aggregation of data from related entities",
+ "related-entities-aggregation-hint": "Aggregation of data from related entities.",
"time-series-data-aggregation": "Time series data aggregation",
- "time-series-data-aggregation-hint": "Aggregation of historical data from a current entity"
+ "time-series-data-aggregation-hint": "Aggregation of historical data from a current entity."
},
"arguments": "Arguments",
"decimals-by-default": "Decimals by default",
@@ -1287,9 +1287,9 @@
},
"aggregate-interval-type": "Aggregate interval type",
"aggregate-interval-value": "Aggregate interval value",
- "aggregate-interval-value-required": "Aggregate interval value is required",
- "aggregate-interval-value-min": "Aggregate interval value should be at least { sec, plural, =0 {0 second} =1 {1 second} other {# seconds} }",
- "aggregate-interval-value-step-multiple-of": "Aggregate interval value must be a divisor or multiple of 1 day",
+ "aggregate-interval-value-required": "Aggregate interval value is required.",
+ "aggregate-interval-value-min": "Aggregate interval value should be at least { sec, plural, =0 {0 second} =1 {1 second} other {# seconds} }.",
+ "aggregate-interval-value-step-multiple-of": "Aggregate interval value must be a divisor or multiple of 1 day.",
"aggregate-period": {
"hour": "Hour",
"day": "Day",
@@ -1301,23 +1301,23 @@
"custom": "Custom"
},
"aggregate-period-hint-offset": "Your aggregation interval will be: {{ interval }}",
- "aggregate-period-hint-offset-and-so-on": "Your aggregation interval will be: {{ interval }} and so on",
+ "aggregate-period-hint-offset-and-so-on": "Your aggregation interval will be: {{ interval }} and so on.",
"entity-aggregation": {
- "argument-hint": "Data will be fetched from current entity",
+ "argument-hint": "Data will be fetched from current entity.",
"argument-setting-hint": "Latest telemetry is the only available argument type for this calculated field.",
"aggregation-interval": "Aggregation interval",
"aggregation-interval-hint": "Defines how often to perform aggregation. Example: every 1 hour aggregates data at 00:00, 01:00, 02:00, etc.",
"apply-offset": "Apply offset to aggregation interval",
"apply-offset-hint": "Defines how much to shift the start of each aggregation period (e.g., +10 minutes - 00:10, 01:10).",
"offset-value": "Offset value",
- "offset-value-required": "Offset value is required",
- "offset-value-min": "Offset value must be a positive integer",
- "offset-value-max": "Offset value should be less than the aggregate interval value",
+ "offset-value-required": "Offset value is required.",
+ "offset-value-min": "Offset value must be a positive integer.",
+ "offset-value-max": "Offset value should be less than the aggregate interval value.",
"wait-delay": "Apply await timeout for delayed telemetry",
"wait-delay-hint": "Defines how long to wait for delayed telemetry after the interval ends. If such telemetry arrives, the result for that interval will be recalculated.",
"duration": "Duration",
- "duration-required": "Duration is required",
- "duration-min": "Duration should be at least 1 minute",
+ "duration-required": "Duration is required.",
+ "duration-min": "Duration should be at least 1 minute.",
"duration-hint": "How long to wait for delayed data after the interval ends.",
"produce-intermediate-result": "Produce intermediate result",
"produce-intermediate-result-hint": "Calculates metrics during the current interval to produce an intermediate result. Updates occur no more often than once every {{ time }}."
@@ -1488,7 +1488,7 @@
"alarm-rule-additional-info-hint": "Hint: use ${Argument name} to substitute values of the arguments that are used in alarm rule condition.",
"alarm-rule-additional-info-icon-hint": "Use Argument name to substitute values of the arguments that are used in alarm rule condition.",
"alarm-rule-mobile-dashboard": "Mobile dashboard",
- "alarm-rule-mobile-dashboard-hint": "Used by mobile application as an alarm details dashboard",
+ "alarm-rule-mobile-dashboard-hint": "Used by mobile application as an alarm details dashboard.",
"alarm-rule-no-mobile-dashboard": "No dashboard selected",
"alarm-rule-condition": "Alarm rule condition",
"enter-alarm-rule-condition-prompt": "Add condition",
diff --git a/ui-ngx/src/form.scss b/ui-ngx/src/form.scss
index f300b5e42b..517fc535fb 100644
--- a/ui-ngx/src/form.scss
+++ b/ui-ngx/src/form.scss
@@ -178,10 +178,11 @@
}
&.tb-required::after {
- font-size: 13px;
- color: rgba(0, 0, 0, .54);
+ font-size: inherit;
+ color: inherit;
vertical-align: top;
- content: " *";
+ content: "*";
+ margin-left: 1px;
}
}
.tb-form-panel-hint {
@@ -298,10 +299,11 @@
margin: 8px 0;
}
.tb-required::after {
- font-size: 13px;
- color: rgba(0, 0, 0, .54);
+ font-size: inherit;
+ color: inherit;
vertical-align: top;
- content: " *";
+ content: "*";
+ margin-left: 1px;
}
}