This is an automated email from the ASF dual-hosted git repository.
chanholee pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zeppelin.git
The following commit(s) were added to refs/heads/master by this push:
new ae68cf5741 [ZEPPELIN-6328] Enable strict template modes in
zeppelin-web-angular
ae68cf5741 is described below
commit ae68cf57413c0848bd958201a6121a9fabc0365b
Author: ChanHo Lee <[email protected]>
AuthorDate: Sat Sep 27 13:57:47 2025 +0900
[ZEPPELIN-6328] Enable strict template modes in zeppelin-web-angular
### What is this PR for?
Type checks in template checks are not fully enabled right now, which makes
it harder to catch type errors.
Enabling strict type checks in Angular templates would help surface these
errors at compile time.
I enabled `strictTemplates` and `fullTemplateTypeCheck` options in tsconfig
files.
Then I ran `npm run build` and fixed those type errors.
### What type of PR is it?
Refactoring
### What is the Jira issue?
https://issues.apache.org/jira/browse/ZEPPELIN-6328
### Questions:
* Does the license files need to update? No
* Is there breaking changes for older versions? No
* Does this needs documentation? No
Closes #5075 from tbonelee/strict-template.
Signed-off-by: ChanHo Lee <[email protected]>
---
.../projects/helium-vis-example/tsconfig.lib.json | 1 +
.../projects/zeppelin-helium/tsconfig.lib.json | 1 +
.../projects/zeppelin-sdk/tsconfig.lib.json | 1 +
.../zeppelin-visualization/tsconfig.lib.json | 1 +
.../src/app/core/paragraph-base/paragraph-base.ts | 8 +--
.../src/app/helium-manager/public-api.ts | 0
.../workspace/interpreter/item/item.component.html | 48 +++++++------
.../job-status/job-status.component.html | 2 +-
.../workspace/job-manager/job/job.component.ts | 2 +-
.../notebook-repos/item/item.component.html | 9 +--
.../notebook-repos/item/item.component.ts | 16 +++--
.../notebook/action-bar/action-bar.component.html | 4 +-
.../notebook/action-bar/action-bar.component.ts | 4 +-
.../workspace/notebook/notebook.component.html | 4 +-
.../paragraph/code-editor/code-editor.component.ts | 8 +--
.../paragraph/control/control.component.ts | 54 +++++++--------
.../notebook/paragraph/paragraph.component.html | 35 +++++-----
.../notebook/paragraph/paragraph.component.ts | 80 +++++++++++++++++++---
.../published/paragraph/paragraph.component.html | 18 ++---
.../published/paragraph/paragraph.component.ts | 4 +-
.../dynamic-forms/dynamic-forms.component.html | 2 +-
.../share/dynamic-forms/dynamic-forms.component.ts | 2 +-
.../workspace/share/result/result.component.html | 20 ++++--
.../workspace/share/result/result.component.ts | 7 +-
.../src/app/services/runtime-compiler.service.ts | 2 +-
.../share/note-import/note-import.component.html | 8 +--
.../share/page-header/page-header.component.html | 2 +-
.../app/share/page-header/page-header.component.ts | 2 +-
.../src/app/share/pipes/humanize-bytes.pipe.ts | 13 +++-
.../scatter-setting/scatter-setting.component.ts | 8 +--
.../table/table-visualization.component.html | 13 ++--
.../table/table-visualization.component.ts | 36 +++++-----
zeppelin-web-angular/src/tsconfig.app.json | 4 ++
33 files changed, 250 insertions(+), 169 deletions(-)
diff --git a/zeppelin-web-angular/projects/helium-vis-example/tsconfig.lib.json
b/zeppelin-web-angular/projects/helium-vis-example/tsconfig.lib.json
index 2972099ba1..c2d2516358 100644
--- a/zeppelin-web-angular/projects/helium-vis-example/tsconfig.lib.json
+++ b/zeppelin-web-angular/projects/helium-vis-example/tsconfig.lib.json
@@ -11,6 +11,7 @@
"angularCompilerOptions": {
"annotateForClosureCompiler": true,
"skipTemplateCodegen": true,
+ "strictTemplates": true,
"strictMetadataEmit": true,
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true,
diff --git a/zeppelin-web-angular/projects/zeppelin-helium/tsconfig.lib.json
b/zeppelin-web-angular/projects/zeppelin-helium/tsconfig.lib.json
index 9e14859e0b..b661be2611 100644
--- a/zeppelin-web-angular/projects/zeppelin-helium/tsconfig.lib.json
+++ b/zeppelin-web-angular/projects/zeppelin-helium/tsconfig.lib.json
@@ -11,6 +11,7 @@
"angularCompilerOptions": {
"annotateForClosureCompiler": true,
"skipTemplateCodegen": true,
+ "strictTemplates": true,
"strictMetadataEmit": true,
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true,
diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/tsconfig.lib.json
b/zeppelin-web-angular/projects/zeppelin-sdk/tsconfig.lib.json
index 08b5b68195..ba13f82a90 100644
--- a/zeppelin-web-angular/projects/zeppelin-sdk/tsconfig.lib.json
+++ b/zeppelin-web-angular/projects/zeppelin-sdk/tsconfig.lib.json
@@ -11,6 +11,7 @@
"angularCompilerOptions": {
"annotateForClosureCompiler": true,
"skipTemplateCodegen": true,
+ "strictTemplates": true,
"strictMetadataEmit": true,
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true,
diff --git
a/zeppelin-web-angular/projects/zeppelin-visualization/tsconfig.lib.json
b/zeppelin-web-angular/projects/zeppelin-visualization/tsconfig.lib.json
index 15cc393d9b..e3109fca05 100644
--- a/zeppelin-web-angular/projects/zeppelin-visualization/tsconfig.lib.json
+++ b/zeppelin-web-angular/projects/zeppelin-visualization/tsconfig.lib.json
@@ -11,6 +11,7 @@
"angularCompilerOptions": {
"annotateForClosureCompiler": true,
"skipTemplateCodegen": true,
+ "strictTemplates": true,
"strictMetadataEmit": true,
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true,
diff --git a/zeppelin-web-angular/src/app/core/paragraph-base/paragraph-base.ts
b/zeppelin-web-angular/src/app/core/paragraph-base/paragraph-base.ts
index 85a59ec343..fca72b174f 100644
--- a/zeppelin-web-angular/src/app/core/paragraph-base/paragraph-base.ts
+++ b/zeppelin-web-angular/src/app/core/paragraph-base/paragraph-base.ts
@@ -51,8 +51,8 @@ export abstract class ParagraphBase extends
MessageListenersManager {
revisionView = false;
diffMatchPatch = new DiffMatchPatch();
isParagraphRunning = false;
- results: ParagraphResults | undefined = [];
- configs: ParagraphConfigResults | undefined = {};
+ results: ParagraphIResultsMsgItem[] = [];
+ configs: ParagraphConfigResults = {};
progress = 0;
colWidthOption = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
editorSetting: ParagraphEditorSetting = {
@@ -292,8 +292,8 @@ export abstract class ParagraphBase extends
MessageListenersManager {
setResults(paragraph: ParagraphItem) {
if (paragraph.results) {
- this.results = paragraph.results.msg;
- this.configs = paragraph.config.results;
+ this.results = paragraph.results.msg || [];
+ this.configs = paragraph.config.results || {};
}
if (!paragraph.config) {
paragraph.config = {};
diff --git a/zeppelin-web-angular/src/app/helium-manager/public-api.ts
b/zeppelin-web-angular/src/app/helium-manager/public-api.ts
deleted file mode 100644
index e69de29bb2..0000000000
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/interpreter/item/item.component.html
b/zeppelin-web-angular/src/app/pages/workspace/interpreter/item/item.component.html
index ebd1977e52..55bb61f49b 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/interpreter/item/item.component.html
+++
b/zeppelin-web-angular/src/app/pages/workspace/interpreter/item/item.component.html
@@ -13,8 +13,8 @@
<nz-card
[class.edit]="mode === 'edit'"
class="interpreter-item"
- [nzTitle]="mode !== 'create' ? viewModeTitleTemplate : null"
- [nzExtra]="mode === 'view' ? extraTemplate : null"
+ [nzTitle]="mode !== 'create' ? viewModeTitleTemplate : undefined"
+ [nzExtra]="mode === 'view' ? extraTemplate : undefined"
>
<ng-template #viewModeTitleTemplate>
<div class="card-title" *ngIf="interpreter">
@@ -125,11 +125,11 @@
[nzDisabled]="interpreterRunningOption ===
runningOptionMap.globallyModeName || mode === 'view'"
>
<span *ngIf="interpreterRunningOption ===
runningOptionMap.perUserModeName; else perNote">
- {{ optionFormGroup.get('perUser').value }}
+ {{ optionFormGroup.get('perUser')?.value || '' }}
</span>
<ng-template #perNote>
<span>
- {{ optionFormGroup.get('perNote').value }}
+ {{ optionFormGroup.get('perNote')?.value || '' }}
</span>
</ng-template>
<i nz-icon nzType="down"></i>
@@ -173,7 +173,7 @@
[nzDropdownMenu]="perNoteMenu"
[nzDisabled]="interpreterRunningOption ===
runningOptionMap.globallyModeName || mode === 'view'"
>
- {{ optionFormGroup.get('perNote').value }}
+ {{ optionFormGroup.get('perNote')?.value || '' }}
<i nz-icon nzType="down"></i>
</a>
<nz-dropdown-menu #perNoteMenu="nzDropdownMenu">
@@ -197,7 +197,7 @@
"
>
<button
- *ngIf="optionFormGroup.get('perNote').value ===
sessionOptionMap.shared; else minusButton"
+ *ngIf="optionFormGroup.get('perNote')?.value ===
sessionOptionMap.shared; else minusButton"
nz-button
(click)="setPerNoteOrUserOption('perNote', 'scoped')"
>
@@ -232,7 +232,7 @@
</nz-form-control>
</nz-form-item>
- <ng-container *ngIf="optionForm.control.get('isExistingProcess').value">
+ <ng-container *ngIf="optionForm.control.get('isExistingProcess')?.value">
<nz-form-item>
<nz-form-label>Host</nz-form-label>
<nz-form-control>
@@ -260,7 +260,7 @@
</nz-form-control>
</nz-form-item>
- <ng-container *ngIf="optionForm.control.get('setPermission').value">
+ <ng-container *ngIf="optionForm.control.get('setPermission')?.value">
<nz-form-item>
<nz-form-label>Owners</nz-form-label>
<nz-form-control
@@ -299,11 +299,11 @@
</thead>
<tbody formArrayName="properties">
<tr *ngFor="let control of propertiesFormArray.controls; index as i"
[formGroupName]="i">
- <td>{{ control.get('key').value }}</td>
+ <td>{{ control.get('key')?.value || '' }}</td>
<td>
<ng-container
*ngIf="mode !== 'view'; else viewModePropertiesValue"
- [ngSwitch]="control.get('type').value"
+ [ngSwitch]="control.get('type')?.value"
>
<textarea
*ngSwitchCase="'textarea'"
@@ -317,33 +317,39 @@
<input *ngSwitchCase="'url'" nz-input type="url"
formControlName="value" placeholder="" />
<input *ngSwitchCase="'password'" nz-input type="password"
formControlName="value" placeholder="" />
<label *ngSwitchCase="'checkbox'" nz-checkbox
formControlName="value">
- {{ control.get('value').value }}
+ {{ control.get('value')?.value || '' }}
</label>
</ng-container>
<ng-template #viewModePropertiesValue>
- <ng-container [ngSwitch]="control.get('type').value">
+ <ng-container [ngSwitch]="control.get('type')?.value">
<ng-container
*ngSwitchCase="'password'">******</ng-container>
<ng-container *ngSwitchCase="'url'">
- <a [href]="control.get('value').value" target="_blank">{{
control.get('value').value }}</a>
+ <a [href]="control.get('value')?.value || ''"
target="_blank">
+ {{ control.get('value')?.value || '' }}
+ </a>
</ng-container>
- <ng-container *ngSwitchDefault>{{ control.get('value').value
}}</ng-container>
+ <ng-container *ngSwitchDefault>{{
control.get('value')?.value || '' }}</ng-container>
</ng-container>
</ng-template>
</td>
- <td *ngIf="mode === 'create'">{{ control.get('description').value
}}</td>
+ <td *ngIf="mode === 'create'">{{ control.get('description')?.value
|| '' }}</td>
<td *ngIf="mode !== 'view'">
<button class="transparent-button" (click)="removeProperty(i)"
nz-button nzShape="circle" nzSize="small">
<i nz-icon nzType="close" nzTheme="outline"></i>
</button>
</td>
</tr>
- <tr *ngIf="mode !== 'view'" [formGroup]="editingPropertiesFormGroup"
#editingForm="ngForm">
+ <tr
+ *ngIf="mode !== 'view' && editingPropertiesFormGroup"
+ [formGroup]="editingPropertiesFormGroup"
+ #editingForm="ngForm"
+ >
<td>
<input nz-input formControlName="key" placeholder="" />
</td>
<td>
<div class="edit-properties-value">
- <ng-container
[ngSwitch]="editingForm.control.get('type').value">
+ <ng-container
[ngSwitch]="editingForm.control.get('type')?.value">
<textarea
*ngSwitchCase="'textarea'"
nz-input
@@ -356,7 +362,7 @@
<input *ngSwitchCase="'url'" nz-input type="url"
formControlName="value" placeholder="" />
<input *ngSwitchCase="'password'" nz-input type="password"
formControlName="value" placeholder="" />
<label *ngSwitchCase="'checkbox'" nz-checkbox
formControlName="value">
- {{ editingForm.control.get('value').value }}
+ {{ editingForm.control.get('value')?.value || '' }}
</label>
</ng-container>
<nz-select class="type-selector" formControlName="type"
(ngModelChange)="onTypeChange($event)">
@@ -410,11 +416,11 @@
</td>
</ng-container>
<ng-template #viewModeDependencies>
- <td>{{ control.get('groupArtifactVersion').value }}</td>
- <td>{{ control.get('exclusions').value }}</td>
+ <td>{{ control.get('groupArtifactVersion')?.value || '' }}</td>
+ <td>{{ control.get('exclusions')?.value || '' }}</td>
</ng-template>
</tr>
- <tr *ngIf="mode !== 'view'" [formGroup]="editingDependenceFormGroup">
+ <tr *ngIf="mode !== 'view' && editingDependenceFormGroup"
[formGroup]="editingDependenceFormGroup">
<td>
<input
nz-input
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-status/job-status.component.html
b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-status/job-status.component.html
index ac946054c2..2ca6055160 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-status/job-status.component.html
+++
b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-status/job-status.component.html
@@ -12,6 +12,6 @@
<nz-badge
[class.ready]="status === jobStatus.READY"
- [nzText]="showText ? status : null"
+ [nzText]="showText ? status : undefined"
[nzStatus]="statusMap[status]"
></nz-badge>
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/job-manager/job/job.component.ts
b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job/job.component.ts
index cf26233768..62ffeb13c8 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/job-manager/job/job.component.ts
+++
b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job/job.component.ts
@@ -33,7 +33,7 @@ import { JobsItem, JobStatus } from '@zeppelin/sdk';
})
export class JobManagerJobComponent implements OnInit, OnChanges {
@Input() note!: JobsItem;
- @Input() highlight: string | null = null;
+ @Input() highlight = '';
@Output() readonly start = new EventEmitter<string>();
@Output() readonly stop = new EventEmitter<string>();
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/item/item.component.html
b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/item/item.component.html
index 125c2b3f8d..0ba8522a45 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/item/item.component.html
+++
b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/item/item.component.html
@@ -46,14 +46,9 @@
</ng-container>
<ng-container *ngIf="editMode">
<td>
- <input
- *ngIf="setting.type === 'INPUT'"
- nzSize="small"
- nz-input
- [formControl]="settingFormArray.controls[i]"
- />
+ <input *ngIf="setting.type === 'INPUT'" nzSize="small" nz-input
[formControl]="getSettingControl(i)" />
- <nz-select *ngIf="setting.type === 'DROPDOWN'"
[formControl]="settingFormArray.controls[i]">
+ <nz-select *ngIf="setting.type === 'DROPDOWN'"
[formControl]="getSettingControl(i)">
<nz-option *ngFor="let option of setting.value"
[nzLabel]="option" [nzValue]="option"></nz-option>
</nz-select>
</td>
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/item/item.component.ts
b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/item/item.component.ts
index afa7339f2a..227dea92d8 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/item/item.component.ts
+++
b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/item/item.component.ts
@@ -19,7 +19,7 @@ import {
Output,
SimpleChanges
} from '@angular/core';
-import { FormArray, FormBuilder, Validators } from '@angular/forms';
+import { FormArray, FormBuilder, FormControl, Validators } from
'@angular/forms';
import { NotebookRepo } from '@zeppelin/interfaces';
@Component({
@@ -32,10 +32,13 @@ export class NotebookRepoItemComponent implements OnChanges
{
@Input() repo!: NotebookRepo;
@Output() readonly repoChange = new EventEmitter<NotebookRepo>();
- settingFormArray?: FormArray;
+ settingFormArray: FormArray;
editMode = false;
- constructor(private cdr: ChangeDetectorRef, private fb: FormBuilder) {}
+ constructor(private cdr: ChangeDetectorRef, private fb: FormBuilder) {
+ // Initialize an empty form array to avoid undefined type error in the
template
+ this.settingFormArray = this.fb.array([]);
+ }
triggerEditMode() {
this.editMode = !this.editMode;
@@ -43,9 +46,6 @@ export class NotebookRepoItemComponent implements OnChanges {
}
save() {
- if (!this.settingFormArray) {
- throw new Error('settingFormArray is not defined');
- }
this.settingFormArray.controls.forEach(control => {
control.markAsDirty();
control.updateValueAndValidity();
@@ -73,6 +73,10 @@ export class NotebookRepoItemComponent implements OnChanges {
this.settingFormArray = this.fb.array(controls);
}
+ getSettingControl(index: number): FormControl {
+ return this.settingFormArray.at(index) as FormControl;
+ }
+
ngOnChanges(changes: SimpleChanges): void {
if (changes.repo) {
this.buildForm();
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/notebook/action-bar/action-bar.component.html
b/zeppelin-web-angular/src/app/pages/workspace/notebook/action-bar/action-bar.component.html
index ffea598632..deba0b7106 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/notebook/action-bar/action-bar.component.html
+++
b/zeppelin-web-angular/src/app/pages/workspace/notebook/action-bar/action-bar.component.html
@@ -171,7 +171,9 @@
<li nz-menu-item *ngFor="let r of noteRevisions"
(click)="visitRevision(r)">
<strong>{{ r.message }}</strong>
<nz-divider nzType="vertical"></nz-divider>
- <em class="font-sm opacity-05">{{ (r.time * 1000 | date: 'MMMM dd
yyyy, h:mm:ss a') || 'Current' }}</em>
+ <em class="font-sm opacity-05">
+ {{ r.time === undefined ? 'Current' : (r.time * 1000 | date:
'MMMM dd yyyy, h:mm:ss a') }}
+ </em>
</li>
</ul>
</nz-dropdown-menu>
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/notebook/action-bar/action-bar.component.ts
b/zeppelin-web-angular/src/app/pages/workspace/notebook/action-bar/action-bar.component.ts
index a7adbaceb3..4d05d866bd 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/notebook/action-bar/action-bar.component.ts
+++
b/zeppelin-web-angular/src/app/pages/workspace/notebook/action-bar/action-bar.component.ts
@@ -43,7 +43,7 @@ export class NotebookActionBarComponent extends
MessageListenersManager implemen
@Input() noteRevisions: RevisionListItem[] = [];
@Input() currentRevision?: string;
@Input() collaborativeMode = false;
- @Input() collaborativeModeUsers = [];
+ @Input() collaborativeModeUsers: string[] = [];
@Input() revisionView = false;
@Input() activatedExtension: 'interpreter' | 'permissions' | 'revisions' |
'hide' = 'hide';
@Output() readonly activatedExtensionChange = new EventEmitter<
@@ -145,7 +145,7 @@ export class NotebookActionBarComponent extends
MessageListenersManager implemen
this.messageService.paragraphClearAllOutput(this.note.id);
}
- setCronScheduler(cronExpr: string) {
+ setCronScheduler(cronExpr: string | undefined) {
if (cronExpr) {
if (!this.note.config.cronExecutingUser) {
this.note.config.cronExecutingUser =
this.ticketService.ticket.principal;
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.html
b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.html
index 301ff35e4a..f5f9e0a1a3 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.html
+++
b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.html
@@ -42,7 +42,7 @@
<nz-resize-handle *ngIf="isSidebarOpen" nzDirection="right"><div
class="sidebar-resize"></div></nz-resize-handle>
</div>
<div class="notebook-area">
- <div class="extension-area" [ngSwitch]="activatedExtension"
*ngIf="activatedExtension !== 'hide'">
+ <div class="extension-area" [ngSwitch]="activatedExtension"
*ngIf="activatedExtension !== 'hide' && permissions">
<zeppelin-notebook-interpreter-binding
*ngSwitchCase="'interpreter'"
[noteId]="note.id"
@@ -71,7 +71,7 @@
<zeppelin-notebook-paragraph
nz-col
*ngFor="let p of note.paragraphs; let first = first; let last =
last; index as i"
- [nzSpan]="p.config.colWidth * 2"
+ [nzSpan]="(p.config.colWidth || 12) * 2"
[select]="p.id === selectId"
[scrolled]="p.id === scrolledId"
[index]="i"
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/code-editor/code-editor.component.ts
b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/code-editor/code-editor.component.ts
index d162af28a0..d396bbae2e 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/code-editor/code-editor.component.ts
+++
b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/code-editor/code-editor.component.ts
@@ -23,7 +23,7 @@ import {
Output,
SimpleChanges
} from '@angular/core';
-import { editor as MonacoEditor, IDisposable, IPosition, KeyCode, Position }
from 'monaco-editor';
+import { editor as MonacoEditor, IDisposable, IPosition, KeyCode } from
'monaco-editor';
import { InterpreterBindingItem } from '@zeppelin/sdk';
import { CompletionService, MessageService } from '@zeppelin/services';
@@ -43,10 +43,10 @@ type IEditor = MonacoEditor.IEditor;
export class NotebookParagraphCodeEditorComponent implements OnChanges,
OnDestroy, AfterViewInit {
@Input() position: IPosition | null = null;
@Input() readOnly = false;
- @Input() language = 'text';
+ @Input() language?: string = 'text';
@Input() paragraphControl!: NotebookParagraphControlComponent;
- @Input() lineNumbers = false;
- @Input() focus = false;
+ @Input() lineNumbers?: boolean = false;
+ @Input() focus?: boolean = false;
@Input() collaborativeMode = false;
@Input() text!: string;
@Input() fontSize: number | undefined;
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/control/control.component.ts
b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/control/control.component.ts
index 741c9288c0..53576cba2f 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/control/control.component.ts
+++
b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/control/control.component.ts
@@ -40,28 +40,28 @@ export class NotebookParagraphControlComponent implements
OnInit, OnChanges {
@Input() status!: string;
@Input() progress = 0;
@Input() revisionView = false;
- @Input() enabled = true;
+ @Input() enabled?: boolean = true;
@Input() pid!: string;
- @Input() tableHide = false;
- @Input() editorHide = false;
+ @Input() tableHide?: boolean = false;
+ @Input() editorHide?: boolean = false;
@Input() colWidth?: number;
@Input() fontSize?: number;
- @Input() runOnSelectionChange = true;
+ @Input() runOnSelectionChange?: boolean = true;
@Input() isEntireNoteRunning = true;
@Input() runtimeInfos?: RuntimeInfos;
- @Input() colWidthOption = [];
+ @Input() colWidthOption: number[] = [];
@Input() first = false;
@Input() last = false;
- @Input() title = false;
- @Input() lineNumbers = false;
+ @Input() titleShow?: boolean = false;
+ @Input() showLineNumbers?: boolean = false;
@Input() paragraphLength!: number;
@Output() readonly colWidthChange = new EventEmitter<number>();
- @Output() readonly titleChange = new EventEmitter<boolean>();
+ @Output() readonly titleShowChange = new EventEmitter<boolean>();
@Output() readonly enabledChange = new EventEmitter<boolean>();
@Output() readonly fontSizeChange = new EventEmitter<number>();
@Output() readonly tableHideChange = new EventEmitter<boolean>();
@Output() readonly runParagraph = new EventEmitter();
- @Output() readonly lineNumbersChange = new EventEmitter<boolean>();
+ @Output() readonly showLineNumbersChange = new EventEmitter<boolean>();
@Output() readonly cancelParagraph = new EventEmitter();
@Output() readonly editorHideChange = new EventEmitter<boolean>();
@Output() readonly runOnSelectionChangeChange = new EventEmitter<boolean>();
@@ -178,15 +178,15 @@ export class NotebookParagraphControlComponent implements
OnInit, OnChanges {
shortCut: this.formatShortcut('Shift+Ctrl+C', this.isMac)
},
{
- label: this.title ? 'Hide Title' : 'Show Title',
+ label: this.titleShow ? 'Hide Title' : 'Show Title',
show: true,
disabled: false,
icon: 'font-colors',
- trigger: () => this.toggleTitle(),
+ trigger: () => this.toggleShowTitle(),
shortCut: this.formatShortcut('Ctrl+Alt+T', this.isMac)
},
{
- label: this.lineNumbers ? 'Hide line numbers' : 'Show line numbers',
+ label: this.showLineNumbers ? 'Hide line numbers' : 'Show line
numbers',
show: true,
disabled: false,
icon: 'ordered-list',
@@ -205,46 +205,38 @@ export class NotebookParagraphControlComponent implements
OnInit, OnChanges {
}
toggleEditor() {
- this.editorHide = !this.editorHide;
- this.editorHideChange.emit(this.editorHide);
+ this.editorHideChange.emit(!this.editorHide);
}
toggleOutput() {
- this.tableHide = !this.tableHide;
- this.tableHideChange.emit(this.tableHide);
+ this.tableHideChange.emit(!this.tableHide);
}
toggleRunOnSelectionChange() {
- this.runOnSelectionChange = !this.runOnSelectionChange;
- this.runOnSelectionChangeChange.emit(this.runOnSelectionChange);
+ this.runOnSelectionChangeChange.emit(!this.runOnSelectionChange);
}
- toggleTitle() {
- this.title = !this.title;
- this.titleChange.emit(this.title);
+ toggleShowTitle() {
+ this.titleShowChange.emit(!this.titleShow);
}
toggleLineNumbers() {
- this.lineNumbers = !this.lineNumbers;
- this.lineNumbersChange.emit(this.lineNumbers);
+ this.showLineNumbersChange.emit(!this.showLineNumbers);
}
toggleEnabled() {
if (!this.isEntireNoteRunning) {
- this.enabled = !this.enabled;
- this.enabledChange.emit(this.enabled);
+ this.enabledChange.emit(!this.enabled);
}
}
- changeColWidth(colWidth: number) {
- this.colWidth = +colWidth;
- this.colWidthChange.emit(this.colWidth);
+ changeColWidth(colWidth: string) {
+ this.colWidthChange.emit(+colWidth);
this.dropdownVisible = false;
}
- changeFontSize(fontSize: number) {
- this.fontSize = +fontSize;
- this.fontSizeChange.emit(this.fontSize);
+ changeFontSize(fontSize: string) {
+ this.fontSizeChange.emit(+fontSize);
}
copyClipboard(id: string) {
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.html
b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.html
index 2797e82633..09239cfdcc 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.html
+++
b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.html
@@ -40,26 +40,27 @@
[colWidthOption]="colWidthOption"
[pid]="paragraph.id"
[isEntireNoteRunning]="isEntireNoteRunning"
- [(enabled)]="paragraph.config.enabled"
- [(tableHide)]="paragraph.config.tableHide"
- [(colWidth)]="paragraph.config.colWidth"
- [(title)]="paragraph.config.title"
- [(fontSize)]="paragraph.config.fontSize"
- [(lineNumbers)]="paragraph.config.lineNumbers"
- [(editorHide)]="paragraph.config.editorHide"
- [(runOnSelectionChange)]="paragraph.config.runOnSelectionChange"
- (tableHideChange)="commitParagraph()"
+ [enabled]="paragraph.config.enabled"
+ [tableHide]="paragraph.config.tableHide"
+ [colWidth]="paragraph.config.colWidth"
+ [titleShow]="paragraph.config.title"
+ [fontSize]="paragraph.config.fontSize"
+ [showLineNumbers]="paragraph.config.lineNumbers"
+ [editorHide]="paragraph.config.editorHide"
+ [runOnSelectionChange]="paragraph.config.runOnSelectionChange"
+ (tableHideChange)="tableHideChange($event)"
(removeParagraph)="removeParagraph()"
- (colWidthChange)="changeColWidth(true)"
- (fontSizeChange)="commitParagraph()"
- (editorHideChange)="commitParagraph()"
- (enabledChange)="commitParagraph()"
- (titleChange)="commitParagraph()"
+ (colWidthChange)="colWidthChange($event, true)"
+ (fontSizeChange)="fontSizeChange($event)"
+ (showLineNumbersChange)="showLineNumbersChange($event)"
+ (editorHideChange)="editorHideChange($event)"
+ (enabledChange)="enabledChange($event)"
+ (titleShowChange)="titleShowChange($event)"
(openSingleParagraph)="openSingleParagraph($event)"
- (runOnSelectionChangeChange)="commitParagraph()"
+ (runOnSelectionChangeChange)="runOnSelectionChange($event)"
(runParagraph)="runParagraph()"
- (moveUp)="moveUpParagraph()"
- (moveDown)="moveDownParagraph()"
+ (moveUp)="moveParagraphUp()"
+ (moveDown)="moveParagraphDown()"
(insertNew)="insertParagraph('below')"
(runAllAbove)="runAllAbove()"
(runAllBelowAndCurrent)="runAllBelowAndCurrent()"
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.ts
b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.ts
index 0ee3171f4b..960abbdfb0 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.ts
+++
b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.ts
@@ -378,6 +378,76 @@ export class NotebookParagraphComponent extends
ParagraphBase implements OnInit,
this.commitParagraph();
}
+ setEditorHide(editorHide: boolean) {
+ this.paragraph.config.editorHide = editorHide;
+ this.cdr.markForCheck();
+ }
+
+ editorHideChange(event: boolean) {
+ this.setEditorHide(event);
+ this.commitParagraph();
+ }
+
+ setTitleShow(titleShow: boolean) {
+ this.paragraph.config.title = titleShow;
+ this.cdr.markForCheck();
+ }
+
+ titleShowChange(event: boolean) {
+ this.setTitleShow(event);
+ this.commitParagraph();
+ }
+
+ setEnabled(enabled: boolean) {
+ this.paragraph.config.enabled = enabled;
+ this.cdr.markForCheck();
+ }
+
+ enabledChange(event: boolean) {
+ this.setEnabled(event);
+ this.commitParagraph();
+ }
+
+ setTableHide(tableHide: boolean) {
+ this.paragraph.config.tableHide = tableHide;
+ this.cdr.markForCheck();
+ }
+
+ tableHideChange(event: boolean) {
+ this.setTableHide(event);
+ this.commitParagraph();
+ }
+
+ setRunOnSelection(runOnSelection: boolean) {
+ this.paragraph.config.runOnSelectionChange = runOnSelection;
+ this.cdr.markForCheck();
+ }
+
+ runOnSelectionChange(event: boolean) {
+ this.setRunOnSelection(event);
+ this.commitParagraph();
+ }
+
+ setShowLineNumbers(showLineNumbers: boolean) {
+ this.paragraph.config.lineNumbers = showLineNumbers;
+ this.cdr.markForCheck();
+ }
+
+ showLineNumbersChange(event: boolean) {
+ this.setShowLineNumbers(event);
+ this.commitParagraph();
+ }
+
+ colWidthChange(colWidth: number, needCommit: boolean, updateResult = true) {
+ this.paragraph.config.colWidth = colWidth;
+ this.changeColWidth(needCommit, updateResult);
+ }
+
+ fontSizeChange(fontSize: number) {
+ this.paragraph.config.fontSize = fontSize;
+ this.commitParagraph();
+ }
+
commitParagraph() {
const {
id,
@@ -467,16 +537,6 @@ export class NotebookParagraphComponent extends
ParagraphBase implements OnInit,
this.commitParagraph();
}
- setEditorHide(editorHide: boolean) {
- this.paragraph.config.editorHide = editorHide;
- this.cdr.markForCheck();
- }
-
- setTableHide(tableHide: boolean) {
- this.paragraph.config.tableHide = tableHide;
- this.cdr.markForCheck();
- }
-
openSingleParagraph(paragraphId: string): void {
const noteId = this.note.id;
const redirectToUrl =
`${location.protocol}//${location.host}${location.pathname}#/notebook/${noteId}/paragraph/${paragraphId}`;
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/published/paragraph/paragraph.component.html
b/zeppelin-web-angular/src/app/pages/workspace/published/paragraph/paragraph.component.html
index 4be27e236f..2a2bb7ca8f 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/published/paragraph/paragraph.component.html
+++
b/zeppelin-web-angular/src/app/pages/workspace/published/paragraph/paragraph.component.html
@@ -17,11 +17,13 @@
[runOnChange]="paragraph.config.runOnSelectionChange"
(formChange)="runParagraph()"
></zeppelin-notebook-paragraph-dynamic-forms>
-<zeppelin-notebook-paragraph-result
- *ngFor="let result of results; index as i; trackBy: trackByIndexFn"
- [id]="paragraph.id"
- [published]="true"
- [currentCol]="paragraph.config.colWidth"
- [config]="configs[i]"
- [result]="result"
-></zeppelin-notebook-paragraph-result>
+<ng-container *ngIf="paragraph">
+ <zeppelin-notebook-paragraph-result
+ *ngFor="let result of results; index as i; trackBy: trackByIndexFn"
+ [id]="paragraph.id"
+ [published]="true"
+ [currentCol]="paragraph.config.colWidth"
+ [config]="configs[i]"
+ [result]="result"
+ ></zeppelin-notebook-paragraph-result>
+</ng-container>
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/published/paragraph/paragraph.component.ts
b/zeppelin-web-angular/src/app/pages/workspace/published/paragraph/paragraph.component.ts
index b7be6c4292..ca7f2b7aeb 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/published/paragraph/paragraph.component.ts
+++
b/zeppelin-web-angular/src/app/pages/workspace/published/paragraph/paragraph.component.ts
@@ -81,8 +81,8 @@ export class PublishedParagraphComponent extends
ParagraphBase implements Publis
setResults(paragraph: ParagraphItem) {
if (paragraph.results) {
- this.results = paragraph.results.msg;
- this.configs = paragraph.config.results;
+ this.results = paragraph.results.msg || [];
+ this.configs = paragraph.config.results || {};
}
if (!paragraph.config) {
paragraph.config = {};
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/share/dynamic-forms/dynamic-forms.component.html
b/zeppelin-web-angular/src/app/pages/workspace/share/dynamic-forms/dynamic-forms.component.html
index 3774f1ac26..679f2f2eb6 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/share/dynamic-forms/dynamic-forms.component.html
+++
b/zeppelin-web-angular/src/app/pages/workspace/share/dynamic-forms/dynamic-forms.component.html
@@ -10,7 +10,7 @@
~ limitations under the License.
-->
-<div nz-row nzGutter="24">
+<div nz-row [nzGutter]="24">
<div
*ngFor="let form of forms; trackBy: trackByNameFn"
class="form-item"
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/share/dynamic-forms/dynamic-forms.component.ts
b/zeppelin-web-angular/src/app/pages/workspace/share/dynamic-forms/dynamic-forms.component.ts
index a5c3612ffb..72bd4d55eb 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/share/dynamic-forms/dynamic-forms.component.ts
+++
b/zeppelin-web-angular/src/app/pages/workspace/share/dynamic-forms/dynamic-forms.component.ts
@@ -40,7 +40,7 @@ export class NotebookParagraphDynamicFormsComponent
implements OnInit, OnChanges
@Input() formDefs!: DynamicForms;
@Input() paramDefs!: DynamicFormParams;
- @Input() runOnChange = false;
+ @Input() runOnChange?: boolean = false;
@Input() disable = false;
@Input() removable = false;
@Output() readonly formChange = new EventEmitter<void>();
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/share/result/result.component.html
b/zeppelin-web-angular/src/app/pages/workspace/share/result/result.component.html
index b24a08b775..1bf9dc85a8 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/share/result/result.component.html
+++
b/zeppelin-web-angular/src/app/pages/workspace/share/result/result.component.html
@@ -12,7 +12,7 @@
<div class="setting-bar" *ngIf="result.type === datasetType.TABLE &&
!published">
<div class="visualization-selector">
- <nz-radio-group [(ngModel)]="config?.graph.mode"
(ngModelChange)="switchMode($event)" nzButtonStyle="solid">
+ <nz-radio-group [ngModel]="config?.graph?.mode"
(ngModelChange)="switchMode($event)" nzButtonStyle="solid">
<label
class="viz-icon"
*ngFor="let item of visualizations"
@@ -49,7 +49,13 @@
<a class="setting-trigger" tabindex="-1" (click)="switchSetting()">
Setting
- <i nz-icon nzType="caret-down" [nzRotate]="config?.graph.optionOpen ? 180
: 0" class="setting-icon" nz-dropdown></i>
+ <i
+ nz-icon
+ nzType="caret-down"
+ [nzRotate]="config?.graph?.optionOpen ? 180 : 0"
+ class="setting-icon"
+ nz-dropdown
+ ></i>
</a>
</div>
<div nz-resizable nzPreview (nzResizeEnd)="onResize($event)"
[nzGridColumnCount]="12" [nzMinColumn]="1">
@@ -60,20 +66,20 @@
<!-- Transformation setting container for classic visualizations -->
<div
*ngIf="getCurrentVisualization()?.isClassic"
- [style.display]="config?.graph.optionOpen ? 'block' : 'none'"
- [id]="'trsetting' + id + '_' + config?.graph.mode"
+ [style.display]="config?.graph?.optionOpen ? 'block' : 'none'"
+ [id]="'trsetting' + id + '_' + config?.graph?.mode"
class="transformation-setting"
></div>
<!-- Visualization setting container for classic visualizations -->
<div
*ngIf="getCurrentVisualization()?.isClassic"
- [style.display]="config?.graph.optionOpen ? 'block' : 'none'"
- [id]="'vizsetting' + id + '_' + config?.graph.mode"
+ [style.display]="config?.graph?.optionOpen ? 'block' : 'none'"
+ [id]="'vizsetting' + id + '_' + config?.graph?.mode"
class="visualization-setting"
></div>
<div
*ngIf="getCurrentVisualization()?.isClassic"
- [id]="'p' + id + '_' + config?.graph.mode"
+ [id]="'p' + id + '_' + config?.graph?.mode"
class="classic-visualization-container"
></div>
<ng-container [ngSwitch]="result?.type">
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/share/result/result.component.ts
b/zeppelin-web-angular/src/app/pages/workspace/share/result/result.component.ts
index eacd7239a1..71079fc654 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/share/result/result.component.ts
+++
b/zeppelin-web-angular/src/app/pages/workspace/share/result/result.component.ts
@@ -67,19 +67,20 @@ import {
interface VisualizationItem {
id: string;
name: string;
- icon: string | SafeHtml;
changeSubscription: Subscription | null;
componentFactoryResolver?: ComponentFactoryResolver;
}
interface ClassicVisualizationItem extends VisualizationItem {
isClassic: true;
+ icon: SafeHtml;
Class: HeliumClassicVisualizationConstructor;
instance: HeliumClassicVisualization | undefined;
}
interface ModernVisualizationItem extends VisualizationItem {
isClassic: false;
+ icon: string;
// tslint:disable-next-line:no-any
Class: any;
instance: Visualization | undefined;
@@ -98,7 +99,7 @@ export class NotebookParagraphResultComponent implements
OnInit, AfterViewInit,
@Input() config?: ParagraphConfigResult;
@Input() id!: string;
@Input() published = false;
- @Input() currentCol = 12;
+ @Input() currentCol?: number = 12;
@Input() isPending!: boolean;
@Output() readonly configChange = new EventEmitter<ParagraphConfigResult>();
@Output() readonly sizeChange = new EventEmitter<NzResizeEvent>();
@@ -170,7 +171,7 @@ export class NotebookParagraphResultComponent implements
OnInit, AfterViewInit,
];
constructor(
- protected injector: Injector,
+ public injector: Injector,
private viewContainerRef: ViewContainerRef,
private cdr: ChangeDetectorRef,
private runtimeCompilerService: RuntimeCompilerService,
diff --git a/zeppelin-web-angular/src/app/services/runtime-compiler.service.ts
b/zeppelin-web-angular/src/app/services/runtime-compiler.service.ts
index 8ca218ccb9..fee3ed0fb6 100644
--- a/zeppelin-web-angular/src/app/services/runtime-compiler.service.ts
+++ b/zeppelin-web-angular/src/app/services/runtime-compiler.service.ts
@@ -21,7 +21,7 @@ export class DynamicTemplate {
// tslint:disable-next-line:no-any
public readonly component: Type<any>,
// tslint:disable-next-line:no-any
- public readonly moduleFactory?: NgModuleFactory<any>
+ public readonly moduleFactory: NgModuleFactory<any>
) {}
}
diff --git
a/zeppelin-web-angular/src/app/share/note-import/note-import.component.html
b/zeppelin-web-angular/src/app/share/note-import/note-import.component.html
index dfe25a7e6e..ae099ca1c9 100644
--- a/zeppelin-web-angular/src/app/share/note-import/note-import.component.html
+++ b/zeppelin-web-angular/src/app/share/note-import/note-import.component.html
@@ -42,13 +42,7 @@
</nz-form-item>
<nz-form-item>
<nz-form-control>
- <button
- nz-button
- nzType="primary"
- (click)="importNote()"
- [disabled]="control.status === 'error'"
- [nzLoading]="importLoading"
- >
+ <button nz-button nzType="primary" (click)="importNote()"
[disabled]="!importUrl" [nzLoading]="importLoading">
Import Note
</button>
</nz-form-control>
diff --git
a/zeppelin-web-angular/src/app/share/page-header/page-header.component.html
b/zeppelin-web-angular/src/app/share/page-header/page-header.component.html
index c86a695fd0..c81a488414 100644
--- a/zeppelin-web-angular/src/app/share/page-header/page-header.component.html
+++ b/zeppelin-web-angular/src/app/share/page-header/page-header.component.html
@@ -13,7 +13,7 @@
<nz-card class="header">
<h2>
{{ title }}
- <span class="header-extra"><ng-container
[ngTemplateOutlet]="extra"></ng-container></span>
+ <span class="header-extra"><ng-container [ngTemplateOutlet]="extra ||
null"></ng-container></span>
</h2>
<p>
<ng-container [ngTemplateOutlet]="description"></ng-container>
diff --git
a/zeppelin-web-angular/src/app/share/page-header/page-header.component.ts
b/zeppelin-web-angular/src/app/share/page-header/page-header.component.ts
index 1ed36b64b4..76c3997802 100644
--- a/zeppelin-web-angular/src/app/share/page-header/page-header.component.ts
+++ b/zeppelin-web-angular/src/app/share/page-header/page-header.component.ts
@@ -21,7 +21,7 @@ import { InputBoolean } from 'ng-zorro-antd/core/util';
})
export class PageHeaderComponent implements OnInit {
@Input() title!: string;
- @Input() description!: string | TemplateRef<void>;
+ @Input() description!: TemplateRef<void>;
@Input() @InputBoolean() divider = false;
@Input() extra?: TemplateRef<void>;
diff --git a/zeppelin-web-angular/src/app/share/pipes/humanize-bytes.pipe.ts
b/zeppelin-web-angular/src/app/share/pipes/humanize-bytes.pipe.ts
index 5460413af8..cd61fec8b6 100644
--- a/zeppelin-web-angular/src/app/share/pipes/humanize-bytes.pipe.ts
+++ b/zeppelin-web-angular/src/app/share/pipes/humanize-bytes.pipe.ts
@@ -16,10 +16,17 @@ import { Pipe, PipeTransform } from '@angular/core';
name: 'humanizeBytes'
})
export class HumanizeBytesPipe implements PipeTransform {
- transform(value: number): string {
+ transform(value: number | string | null | undefined): string {
if (value === null || value === undefined) {
return '-';
}
+ let parsedValue = value;
+ if (typeof parsedValue === 'string') {
+ parsedValue = parseInt(parsedValue, 10);
+ if (isNaN(parsedValue)) {
+ return '-';
+ }
+ }
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB'];
const converter = (v: number, p: number): string => {
const base = Math.pow(1024, p);
@@ -31,10 +38,10 @@ export class HumanizeBytesPipe implements PipeTransform {
return converter(v, p + 1);
}
};
- if (value < 1000) {
+ if (parsedValue < 1000) {
return value + ' B';
} else {
- return converter(value, 1);
+ return converter(parsedValue, 1);
}
}
}
diff --git
a/zeppelin-web-angular/src/app/visualizations/common/scatter-setting/scatter-setting.component.ts
b/zeppelin-web-angular/src/app/visualizations/common/scatter-setting/scatter-setting.component.ts
index be4ddeb4e2..11da05cc7e 100644
---
a/zeppelin-web-angular/src/app/visualizations/common/scatter-setting/scatter-setting.component.ts
+++
b/zeppelin-web-angular/src/app/visualizations/common/scatter-setting/scatter-setting.component.ts
@@ -31,10 +31,10 @@ export class VisualizationScatterSettingComponent
implements OnInit {
columns: Array<Exclude<VisualizationScatterChart[keyof
VisualizationScatterChart], undefined>> = [];
field: {
- xAxis: Array<VisualizationScatterChart['xAxis']>;
- yAxis: Array<VisualizationScatterChart['yAxis']>;
- group: Array<VisualizationScatterChart['group']>;
- size: Array<VisualizationScatterChart['size']>;
+ xAxis: Array<Exclude<VisualizationScatterChart['xAxis'], undefined>>;
+ yAxis: Array<Exclude<VisualizationScatterChart['yAxis'], undefined>>;
+ group: Array<Exclude<VisualizationScatterChart['group'], undefined>>;
+ size: Array<Exclude<VisualizationScatterChart['size'], undefined>>;
} = {
xAxis: [],
yAxis: [],
diff --git
a/zeppelin-web-angular/src/app/visualizations/table/table-visualization.component.html
b/zeppelin-web-angular/src/app/visualizations/table/table-visualization.component.html
index a3aa5f4693..4b84fc3027 100644
---
a/zeppelin-web-angular/src/app/visualizations/table/table-visualization.component.html
+++
b/zeppelin-web-angular/src/app/visualizations/table/table-visualization.component.html
@@ -46,7 +46,7 @@
nzShowSort
nzCustomFilter
[nzSortKey]="col"
- (nzSortChange)="onSortChange($event, col)"
+ (nzSortChange)="onSortChange(col, $event)"
>
{{ col }}
<i
@@ -73,7 +73,8 @@
placeholder="Search..."
(blur)="onSearch()"
(keydown.enter)="onSearch()"
- [(ngModel)]="colOptions.get(col).term"
+ [ngModel]="getColOptionOrThrow(col).term"
+ (ngModelChange)="onTermChange(col, $event)"
/>
</nz-input-group>
<ng-template #suffixIconButton>
@@ -89,7 +90,7 @@
<li
*ngFor="let type of types"
nz-menu-item
- [nzSelected]="colOptions.get(col).type === type"
+ [nzSelected]="getColOptionOrThrow(col).type === type"
(click)="onChangeType(type, col)"
>
{{ type | titlecase }}
@@ -103,7 +104,7 @@
<li
*ngFor="let aggregation of aggregations"
nz-menu-item
- [nzSelected]="colOptions.get(col).aggregation ===
aggregation"
+ [nzSelected]="getColOptionOrThrow(col).aggregation ===
aggregation"
(click)="onChangeAggregation(aggregation, col)"
>
{{ aggregation | titlecase }}
@@ -124,11 +125,11 @@
<ng-template #aggregatesFooter>
<div class="aggregation-wrap">
<span *ngFor="let col of columns">
- <span class="aggregation-item" *ngIf="colOptions.get(col).aggregation as
aggregation">
+ <span class="aggregation-item"
*ngIf="getColOptionOrThrow(col).aggregation as aggregation">
{{ aggregation }}(
<strong>{{ col }}</strong>
):
- <span>{{ colOptions.get(col).aggregationValue }}</span>
+ <span>{{ getColOptionOrThrow(col).aggregationValue }}</span>
</span>
</span>
</div>
diff --git
a/zeppelin-web-angular/src/app/visualizations/table/table-visualization.component.ts
b/zeppelin-web-angular/src/app/visualizations/table/table-visualization.component.ts
index c2b94ed812..51660f4f89 100644
---
a/zeppelin-web-angular/src/app/visualizations/table/table-visualization.component.ts
+++
b/zeppelin-web-angular/src/app/visualizations/table/table-visualization.component.ts
@@ -13,7 +13,7 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject,
OnInit, ViewChild } from '@angular/core';
import { filter, maxBy, minBy, orderBy, sumBy } from 'lodash';
-import { NzTableComponent } from 'ng-zorro-antd/table';
+import { NzTableComponent, NzTableSortOrder } from 'ng-zorro-antd/table';
import { utils, writeFile, WorkSheet } from 'xlsx';
import { TableData, Visualization, VISUALIZATION } from
'@zeppelin/visualization';
@@ -74,20 +74,13 @@ export class TableVisualizationComponent implements OnInit {
}
onChangeType(type: ColType, col: string) {
- const opt = this.colOptions.get(col);
- if (!opt) {
- throw new Error('opt is not found');
- }
- opt.type = type;
+ this.getColOptionOrThrow(col).type = type;
this.filterRows();
this.aggregate();
}
onChangeAggregation(aggregation: AggregationType, col: string) {
- const opt = this.colOptions.get(col);
- if (!opt) {
- throw new Error('opt is not found');
- }
+ const opt = this.getColOptionOrThrow(col);
opt.aggregation = opt.aggregation === aggregation ? null : aggregation;
this.aggregate();
}
@@ -96,21 +89,30 @@ export class TableVisualizationComponent implements OnInit {
this.filterRows();
}
- onSortChange(type: 'descend' | 'ascend' | string, key: string): void {
- const opt = this.colOptions.get(key);
- if (!opt) {
- throw new Error('opt is not found');
- }
- this.colOptions.delete(key);
+ onSortChange(col: string, type: NzTableSortOrder): void {
+ const opt = this.getColOptionOrThrow(col);
+ this.colOptions.delete(col);
if (type) {
opt.sort = type === 'descend' ? 'desc' : 'asc';
} else {
opt.sort = '';
}
- this.colOptions.set(key, opt);
+ this.colOptions.set(col, opt);
this.filterRows();
}
+ onTermChange(col: string, term: string) {
+ this.getColOptionOrThrow(col).term = term;
+ }
+
+ getColOptionOrThrow(col: string): FilterOption {
+ const opt = this.colOptions.get(col);
+ if (!opt) {
+ throw new Error('Column option should have been initialized');
+ }
+ return opt;
+ }
+
aggregate() {
if (!this.tableData) {
throw new Error('tableData is not defined');
diff --git a/zeppelin-web-angular/src/tsconfig.app.json
b/zeppelin-web-angular/src/tsconfig.app.json
index 50958688db..564b7a3ea5 100644
--- a/zeppelin-web-angular/src/tsconfig.app.json
+++ b/zeppelin-web-angular/src/tsconfig.app.json
@@ -4,5 +4,9 @@
"outDir": "../out-tsc/app",
"types": ["mathjax"]
},
+ "angularCompilerOptions": {
+ "fullTemplateTypeCheck": true,
+ "strictTemplates": true
+ },
"exclude": ["test.ts", "**/*.spec.ts"]
}