mirror of https://github.com/apache/nifi.git
NIFI-13136: Allowing users to unset optional property values (#8734)
* NIFI-13136: - Allowing users to unset optional property values. - Only selecting value and applying focus if it is not read only. * NIFI-13136: - Addressing review feedback. - Adding styles to disabled editor input. - Fixing show hint/autocomplete in production build. This closes #8734
This commit is contained in:
parent
37937ffa15
commit
914e2b1057
|
@ -28,7 +28,6 @@ import { MatSelectModule } from '@angular/material/select';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { ParameterContextEntity, SelectOption } from '../../../../../../../state/shared';
|
import { ParameterContextEntity, SelectOption } from '../../../../../../../state/shared';
|
||||||
import { Client } from '../../../../../../../service/client.service';
|
import { Client } from '../../../../../../../service/client.service';
|
||||||
import { PropertyTable } from '../../../../../../../ui/common/property-table/property-table.component';
|
|
||||||
import { NifiSpinnerDirective } from '../../../../../../../ui/common/spinner/nifi-spinner.directive';
|
import { NifiSpinnerDirective } from '../../../../../../../ui/common/spinner/nifi-spinner.directive';
|
||||||
import { NifiTooltipDirective } from '../../../../../../../ui/common/tooltips/nifi-tooltip.directive';
|
import { NifiTooltipDirective } from '../../../../../../../ui/common/tooltips/nifi-tooltip.directive';
|
||||||
import { TextTip } from '../../../../../../../ui/common/tooltips/text-tip/text-tip.component';
|
import { TextTip } from '../../../../../../../ui/common/tooltips/text-tip/text-tip.component';
|
||||||
|
@ -51,7 +50,6 @@ import { ErrorBanner } from '../../../../../../../ui/common/error-banner/error-b
|
||||||
MatOptionModule,
|
MatOptionModule,
|
||||||
MatSelectModule,
|
MatSelectModule,
|
||||||
AsyncPipe,
|
AsyncPipe,
|
||||||
PropertyTable,
|
|
||||||
NifiSpinnerDirective,
|
NifiSpinnerDirective,
|
||||||
NifiTooltipDirective,
|
NifiTooltipDirective,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
|
|
|
@ -27,6 +27,8 @@ import { provideMockStore } from '@ngrx/store/testing';
|
||||||
import { initialState } from '../../../../../../../state/error/error.reducer';
|
import { initialState } from '../../../../../../../state/error/error.reducer';
|
||||||
import { ClusterConnectionService } from '../../../../../../../service/cluster-connection.service';
|
import { ClusterConnectionService } from '../../../../../../../service/cluster-connection.service';
|
||||||
|
|
||||||
|
import 'codemirror/addon/hint/show-hint';
|
||||||
|
|
||||||
describe('EditProcessor', () => {
|
describe('EditProcessor', () => {
|
||||||
let component: EditProcessor;
|
let component: EditProcessor;
|
||||||
let fixture: ComponentFixture<EditProcessor>;
|
let fixture: ComponentFixture<EditProcessor>;
|
||||||
|
|
|
@ -27,6 +27,8 @@ import { initialState } from '../../../state/parameter-context-listing/parameter
|
||||||
import { ClusterConnectionService } from '../../../../../service/cluster-connection.service';
|
import { ClusterConnectionService } from '../../../../../service/cluster-connection.service';
|
||||||
import { ParameterContextEntity } from '../../../../../state/shared';
|
import { ParameterContextEntity } from '../../../../../state/shared';
|
||||||
|
|
||||||
|
import 'codemirror/addon/hint/show-hint';
|
||||||
|
|
||||||
describe('EditParameterContext', () => {
|
describe('EditParameterContext', () => {
|
||||||
let component: EditParameterContext;
|
let component: EditParameterContext;
|
||||||
let fixture: ComponentFixture<EditParameterContext>;
|
let fixture: ComponentFixture<EditParameterContext>;
|
||||||
|
|
|
@ -26,6 +26,8 @@ import { provideMockStore } from '@ngrx/store/testing';
|
||||||
import { initialState } from '../../../../../state/error/error.reducer';
|
import { initialState } from '../../../../../state/error/error.reducer';
|
||||||
import { ClusterConnectionService } from '../../../../../service/cluster-connection.service';
|
import { ClusterConnectionService } from '../../../../../service/cluster-connection.service';
|
||||||
|
|
||||||
|
import 'codemirror/addon/hint/show-hint';
|
||||||
|
|
||||||
describe('EditFlowAnalysisRule', () => {
|
describe('EditFlowAnalysisRule', () => {
|
||||||
let component: EditFlowAnalysisRule;
|
let component: EditFlowAnalysisRule;
|
||||||
let fixture: ComponentFixture<EditFlowAnalysisRule>;
|
let fixture: ComponentFixture<EditFlowAnalysisRule>;
|
||||||
|
|
|
@ -26,6 +26,8 @@ import { provideMockStore } from '@ngrx/store/testing';
|
||||||
import { initialState } from '../../../../../state/error/error.reducer';
|
import { initialState } from '../../../../../state/error/error.reducer';
|
||||||
import { ClusterConnectionService } from '../../../../../service/cluster-connection.service';
|
import { ClusterConnectionService } from '../../../../../service/cluster-connection.service';
|
||||||
|
|
||||||
|
import 'codemirror/addon/hint/show-hint';
|
||||||
|
|
||||||
describe('EditRegistryClient', () => {
|
describe('EditRegistryClient', () => {
|
||||||
let component: EditRegistryClient;
|
let component: EditRegistryClient;
|
||||||
let fixture: ComponentFixture<EditRegistryClient>;
|
let fixture: ComponentFixture<EditRegistryClient>;
|
||||||
|
|
|
@ -26,6 +26,8 @@ import { provideMockStore } from '@ngrx/store/testing';
|
||||||
import { initialState } from '../../../../../state/error/error.reducer';
|
import { initialState } from '../../../../../state/error/error.reducer';
|
||||||
import { ClusterConnectionService } from '../../../../../service/cluster-connection.service';
|
import { ClusterConnectionService } from '../../../../../service/cluster-connection.service';
|
||||||
|
|
||||||
|
import 'codemirror/addon/hint/show-hint';
|
||||||
|
|
||||||
describe('EditReportingTask', () => {
|
describe('EditReportingTask', () => {
|
||||||
let component: EditReportingTask;
|
let component: EditReportingTask;
|
||||||
let fixture: ComponentFixture<EditReportingTask>;
|
let fixture: ComponentFixture<EditReportingTask>;
|
||||||
|
|
|
@ -28,7 +28,6 @@ import { AsyncPipe, NgTemplateOutlet } from '@angular/common';
|
||||||
import { MatTabsModule } from '@angular/material/tabs';
|
import { MatTabsModule } from '@angular/material/tabs';
|
||||||
import { MatOptionModule } from '@angular/material/core';
|
import { MatOptionModule } from '@angular/material/core';
|
||||||
import { MatSelectModule } from '@angular/material/select';
|
import { MatSelectModule } from '@angular/material/select';
|
||||||
import { PropertyTable } from '../../property-table/property-table.component';
|
|
||||||
import { ControllerServiceApi } from '../controller-service-api/controller-service-api.component';
|
import { ControllerServiceApi } from '../controller-service-api/controller-service-api.component';
|
||||||
import { ControllerServiceReferences } from '../controller-service-references/controller-service-references.component';
|
import { ControllerServiceReferences } from '../controller-service-references/controller-service-references.component';
|
||||||
import { NifiSpinnerDirective } from '../../spinner/nifi-spinner.directive';
|
import { NifiSpinnerDirective } from '../../spinner/nifi-spinner.directive';
|
||||||
|
@ -59,7 +58,6 @@ import {
|
||||||
MatTabsModule,
|
MatTabsModule,
|
||||||
MatOptionModule,
|
MatOptionModule,
|
||||||
MatSelectModule,
|
MatSelectModule,
|
||||||
PropertyTable,
|
|
||||||
ControllerServiceApi,
|
ControllerServiceApi,
|
||||||
ControllerServiceReferences,
|
ControllerServiceReferences,
|
||||||
AsyncPipe,
|
AsyncPipe,
|
||||||
|
|
|
@ -26,6 +26,8 @@ import { provideMockStore } from '@ngrx/store/testing';
|
||||||
import { initialState } from '../../../../state/error/error.reducer';
|
import { initialState } from '../../../../state/error/error.reducer';
|
||||||
import { ClusterConnectionService } from '../../../../service/cluster-connection.service';
|
import { ClusterConnectionService } from '../../../../service/cluster-connection.service';
|
||||||
|
|
||||||
|
import 'codemirror/addon/hint/show-hint';
|
||||||
|
|
||||||
describe('EditControllerService', () => {
|
describe('EditControllerService', () => {
|
||||||
let component: EditControllerService;
|
let component: EditControllerService;
|
||||||
let fixture: ComponentFixture<EditControllerService>;
|
let fixture: ComponentFixture<EditControllerService>;
|
||||||
|
|
|
@ -30,7 +30,6 @@ import { AsyncPipe, NgTemplateOutlet } from '@angular/common';
|
||||||
import { MatTabsModule } from '@angular/material/tabs';
|
import { MatTabsModule } from '@angular/material/tabs';
|
||||||
import { MatOptionModule } from '@angular/material/core';
|
import { MatOptionModule } from '@angular/material/core';
|
||||||
import { MatSelectModule } from '@angular/material/select';
|
import { MatSelectModule } from '@angular/material/select';
|
||||||
import { PropertyTable } from '../../property-table/property-table.component';
|
|
||||||
import { ControllerServiceApi } from '../controller-service-api/controller-service-api.component';
|
import { ControllerServiceApi } from '../controller-service-api/controller-service-api.component';
|
||||||
import { ControllerServiceReferences } from '../controller-service-references/controller-service-references.component';
|
import { ControllerServiceReferences } from '../controller-service-references/controller-service-references.component';
|
||||||
import { NifiSpinnerDirective } from '../../spinner/nifi-spinner.directive';
|
import { NifiSpinnerDirective } from '../../spinner/nifi-spinner.directive';
|
||||||
|
@ -67,7 +66,6 @@ import {
|
||||||
MatTabsModule,
|
MatTabsModule,
|
||||||
MatOptionModule,
|
MatOptionModule,
|
||||||
MatSelectModule,
|
MatSelectModule,
|
||||||
PropertyTable,
|
|
||||||
ControllerServiceApi,
|
ControllerServiceApi,
|
||||||
ControllerServiceReferences,
|
ControllerServiceReferences,
|
||||||
AsyncPipe,
|
AsyncPipe,
|
||||||
|
|
|
@ -61,17 +61,14 @@
|
||||||
@include mat.button-density(-1);
|
@include mat.button-density(-1);
|
||||||
|
|
||||||
.nf-editor {
|
.nf-editor {
|
||||||
|
border-color: var(--mdc-outlined-text-field-label-text-color);
|
||||||
|
|
||||||
|
&.blank {
|
||||||
|
border-color: var(--mdc-outlined-text-field-disabled-label-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
.CodeMirror {
|
.CodeMirror {
|
||||||
background-color: if($is-dark, $nifi-theme-surface-palette-darker, $nifi-theme-surface-palette-lighter);
|
background-color: if($is-dark, $nifi-theme-surface-palette-darker, $nifi-theme-surface-palette-lighter);
|
||||||
|
|
||||||
&.blank {
|
|
||||||
background: $material-theme-primary-palette-default;
|
|
||||||
color: if(
|
|
||||||
$is-dark,
|
|
||||||
$material-theme-primary-palette-darker,
|
|
||||||
$material-theme-primary-palette-lighter
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror-code {
|
.CodeMirror-code {
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
import { ComponentRef, Injectable, Renderer2, ViewContainerRef } from '@angular/core';
|
import { ComponentRef, Injectable, Renderer2, ViewContainerRef } from '@angular/core';
|
||||||
import * as CodeMirror from 'codemirror';
|
import * as CodeMirror from 'codemirror';
|
||||||
import { Editor, Hint, Hints, StringStream } from 'codemirror';
|
import { Editor, Hint, Hints, StringStream } from 'codemirror';
|
||||||
import 'codemirror/addon/hint/show-hint';
|
|
||||||
import { ElFunction, Parameter } from '../../../../../../state/shared';
|
import { ElFunction, Parameter } from '../../../../../../state/shared';
|
||||||
import { ParameterTip } from '../../../../tooltips/parameter-tip/parameter-tip.component';
|
import { ParameterTip } from '../../../../tooltips/parameter-tip/parameter-tip.component';
|
||||||
import { ElService } from './el.service';
|
import { ElService } from './el.service';
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
cdkDrag
|
cdkDrag
|
||||||
resizable
|
resizable
|
||||||
(resized)="resized()">
|
(resized)="resized()">
|
||||||
<form class="h-full" [formGroup]="nfEditorForm" cdkTrapFocus cdkTrapFocusAutoCapture>
|
<form class="h-full" [formGroup]="nfEditorForm" cdkTrapFocus [cdkTrapFocusAutoCapture]="!readonly">
|
||||||
<div class="flex flex-col gap-y-3 h-full">
|
<div class="flex flex-col gap-y-3 h-full">
|
||||||
<div class="flex justify-end">
|
<div class="flex justify-end">
|
||||||
<div
|
<div
|
||||||
|
@ -47,10 +47,9 @@
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-y-0.5 flex-1">
|
<div class="flex flex-col gap-y-0.5 flex-1">
|
||||||
<div class="nf-editor flex-1" #nfEditorContainer>
|
<div class="nf-editor flex-1" [class.blank]="blank">
|
||||||
<ngx-codemirror
|
<ngx-codemirror
|
||||||
[options]="getOptions()"
|
[options]="getOptions()"
|
||||||
[autoFocus]="true"
|
|
||||||
formControlName="value"
|
formControlName="value"
|
||||||
(mousedown)="preventDrag($event)"
|
(mousedown)="preventDrag($event)"
|
||||||
(codeMirrorLoaded)="codeMirrorLoaded($event)"></ngx-codemirror>
|
(codeMirrorLoaded)="codeMirrorLoaded($event)"></ngx-codemirror>
|
||||||
|
|
|
@ -31,7 +31,8 @@
|
||||||
.nf-editor {
|
.nf-editor {
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
min-width: 210px;
|
min-width: 210px;
|
||||||
border: 1px solid;
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
|
||||||
.CodeMirror {
|
.CodeMirror {
|
||||||
|
@ -40,11 +41,6 @@
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
|
|
||||||
&.blank {
|
|
||||||
border-width: 1px;
|
|
||||||
border-style: solid;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror-scroll {
|
.CodeMirror-scroll {
|
||||||
|
|
|
@ -21,6 +21,8 @@ import { NfEditor } from './nf-editor.component';
|
||||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||||
import { PropertyItem } from '../../property-table.component';
|
import { PropertyItem } from '../../property-table.component';
|
||||||
|
|
||||||
|
import 'codemirror/addon/hint/show-hint';
|
||||||
|
|
||||||
describe('NfEditor', () => {
|
describe('NfEditor', () => {
|
||||||
let component: NfEditor;
|
let component: NfEditor;
|
||||||
let fixture: ComponentFixture<NfEditor>;
|
let fixture: ComponentFixture<NfEditor>;
|
||||||
|
|
|
@ -57,15 +57,16 @@ import { Resizable } from '../../../resizable/resizable.component';
|
||||||
export class NfEditor implements OnDestroy {
|
export class NfEditor implements OnDestroy {
|
||||||
@Input() set item(item: PropertyItem) {
|
@Input() set item(item: PropertyItem) {
|
||||||
this.nfEditorForm.get('value')?.setValue(item.value);
|
this.nfEditorForm.get('value')?.setValue(item.value);
|
||||||
|
if (item.descriptor.required) {
|
||||||
const isEmptyString: boolean = item.value == '';
|
this.nfEditorForm.get('value')?.addValidators(Validators.required);
|
||||||
this.nfEditorForm.get('setEmptyString')?.setValue(isEmptyString);
|
|
||||||
if (isEmptyString) {
|
|
||||||
this.nfEditorForm.get('value')?.disable();
|
|
||||||
} else {
|
} else {
|
||||||
this.nfEditorForm.get('value')?.enable();
|
this.nfEditorForm.get('value')?.removeValidators(Validators.required);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isEmptyString: boolean = item.value === '';
|
||||||
|
this.nfEditorForm.get('setEmptyString')?.setValue(isEmptyString);
|
||||||
|
this.setEmptyStringChanged();
|
||||||
|
|
||||||
this.supportsEl = item.descriptor.supportsEl;
|
this.supportsEl = item.descriptor.supportsEl;
|
||||||
this.sensitive = item.descriptor.sensitive;
|
this.sensitive = item.descriptor.sensitive;
|
||||||
this.mode = this.supportsEl ? this.nfel.getLanguageId() : this.nfpr.getLanguageId();
|
this.mode = this.supportsEl ? this.nfel.getLanguageId() : this.nfpr.getLanguageId();
|
||||||
|
@ -83,7 +84,7 @@ export class NfEditor implements OnDestroy {
|
||||||
@Input() width!: number;
|
@Input() width!: number;
|
||||||
@Input() readonly: boolean = false;
|
@Input() readonly: boolean = false;
|
||||||
|
|
||||||
@Output() ok: EventEmitter<string> = new EventEmitter<string>();
|
@Output() ok: EventEmitter<string | null> = new EventEmitter<string | null>();
|
||||||
@Output() cancel: EventEmitter<void> = new EventEmitter<void>();
|
@Output() cancel: EventEmitter<void> = new EventEmitter<void>();
|
||||||
|
|
||||||
protected readonly PropertyHintTip = PropertyHintTip;
|
protected readonly PropertyHintTip = PropertyHintTip;
|
||||||
|
@ -95,6 +96,7 @@ export class NfEditor implements OnDestroy {
|
||||||
sensitive = false;
|
sensitive = false;
|
||||||
supportsEl = false;
|
supportsEl = false;
|
||||||
supportsParameters = false;
|
supportsParameters = false;
|
||||||
|
blank = false;
|
||||||
|
|
||||||
mode!: string;
|
mode!: string;
|
||||||
_parameters!: Parameter[];
|
_parameters!: Parameter[];
|
||||||
|
@ -109,7 +111,7 @@ export class NfEditor implements OnDestroy {
|
||||||
private nfpr: NfPr
|
private nfpr: NfPr
|
||||||
) {
|
) {
|
||||||
this.nfEditorForm = this.formBuilder.group({
|
this.nfEditorForm = this.formBuilder.group({
|
||||||
value: new FormControl('', Validators.required),
|
value: new FormControl(''),
|
||||||
setEmptyString: new FormControl(false)
|
setEmptyString: new FormControl(false)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -117,7 +119,17 @@ export class NfEditor implements OnDestroy {
|
||||||
codeMirrorLoaded(codeEditor: any): void {
|
codeMirrorLoaded(codeEditor: any): void {
|
||||||
this.editor = codeEditor.codeMirror;
|
this.editor = codeEditor.codeMirror;
|
||||||
this.editor.setSize('100%', '100%');
|
this.editor.setSize('100%', '100%');
|
||||||
this.editor.execCommand('selectAll');
|
|
||||||
|
if (!this.readonly) {
|
||||||
|
this.editor.execCommand('selectAll');
|
||||||
|
}
|
||||||
|
|
||||||
|
// disabling of the input through the form isn't supported until codemirror
|
||||||
|
// has loaded so we must disable again if the value is an empty string
|
||||||
|
if (this.nfEditorForm.get('setEmptyString')?.value) {
|
||||||
|
this.nfEditorForm.get('value')?.disable();
|
||||||
|
this.editor.setOption('readOnly', 'nocursor');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadParameters(): void {
|
loadParameters(): void {
|
||||||
|
@ -164,7 +176,9 @@ export class NfEditor implements OnDestroy {
|
||||||
extraKeys: {
|
extraKeys: {
|
||||||
'Ctrl-Space': 'autocomplete',
|
'Ctrl-Space': 'autocomplete',
|
||||||
Enter: () => {
|
Enter: () => {
|
||||||
this.okClicked();
|
if (this.nfEditorForm.dirty && this.nfEditorForm.valid) {
|
||||||
|
this.okClicked();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -188,6 +202,8 @@ export class NfEditor implements OnDestroy {
|
||||||
setEmptyStringChanged(): void {
|
setEmptyStringChanged(): void {
|
||||||
const emptyStringChecked: AbstractControl | null = this.nfEditorForm.get('setEmptyString');
|
const emptyStringChecked: AbstractControl | null = this.nfEditorForm.get('setEmptyString');
|
||||||
if (emptyStringChecked) {
|
if (emptyStringChecked) {
|
||||||
|
this.blank = emptyStringChecked.value;
|
||||||
|
|
||||||
if (emptyStringChecked.value) {
|
if (emptyStringChecked.value) {
|
||||||
this.nfEditorForm.get('value')?.setValue('');
|
this.nfEditorForm.get('value')?.setValue('');
|
||||||
this.nfEditorForm.get('value')?.disable();
|
this.nfEditorForm.get('value')?.disable();
|
||||||
|
@ -207,8 +223,18 @@ export class NfEditor implements OnDestroy {
|
||||||
|
|
||||||
okClicked(): void {
|
okClicked(): void {
|
||||||
const valueControl: AbstractControl | null = this.nfEditorForm.get('value');
|
const valueControl: AbstractControl | null = this.nfEditorForm.get('value');
|
||||||
if (valueControl) {
|
const emptyStringChecked: AbstractControl | null = this.nfEditorForm.get('setEmptyString');
|
||||||
this.ok.next(valueControl.value);
|
if (valueControl && emptyStringChecked) {
|
||||||
|
const value = valueControl.value;
|
||||||
|
if (value === '') {
|
||||||
|
if (emptyStringChecked.value) {
|
||||||
|
this.ok.next('');
|
||||||
|
} else {
|
||||||
|
this.ok.next(null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.ok.next(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { PropertyTable } from './property-table.component';
|
import { PropertyTable } from './property-table.component';
|
||||||
|
|
||||||
|
import 'codemirror/addon/hint/show-hint';
|
||||||
|
|
||||||
describe('PropertyTable', () => {
|
describe('PropertyTable', () => {
|
||||||
let component: PropertyTable;
|
let component: PropertyTable;
|
||||||
let fixture: ComponentFixture<PropertyTable>;
|
let fixture: ComponentFixture<PropertyTable>;
|
||||||
|
|
|
@ -554,7 +554,7 @@ export class PropertyTable implements AfterViewInit, ControlValueAccessor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
savePropertyValue(item: PropertyItem, newValue: string): void {
|
savePropertyValue(item: PropertyItem, newValue: string | null): void {
|
||||||
if (item.value != newValue) {
|
if (item.value != newValue) {
|
||||||
item.value = newValue;
|
item.value = newValue;
|
||||||
item.dirty = true;
|
item.dirty = true;
|
||||||
|
|
|
@ -19,6 +19,15 @@ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
import { AppModule } from './app/app.module';
|
import { AppModule } from './app/app.module';
|
||||||
|
|
||||||
|
import 'codemirror/addon/edit/matchbrackets';
|
||||||
|
import 'codemirror/addon/fold/brace-fold';
|
||||||
|
import 'codemirror/addon/fold/comment-fold';
|
||||||
|
import 'codemirror/addon/fold/foldcode';
|
||||||
|
import 'codemirror/addon/fold/foldgutter';
|
||||||
|
import 'codemirror/addon/fold/markdown-fold';
|
||||||
|
import 'codemirror/addon/fold/xml-fold';
|
||||||
|
import 'codemirror/addon/hint/show-hint';
|
||||||
|
|
||||||
platformBrowserDynamic()
|
platformBrowserDynamic()
|
||||||
.bootstrapModule(AppModule)
|
.bootstrapModule(AppModule)
|
||||||
.catch((err) => console.error(err));
|
.catch((err) => console.error(err));
|
||||||
|
|
Loading…
Reference in New Issue