diff --git a/zeppelin-web-angular/src/app/interfaces/notebook-repo.ts b/zeppelin-web-angular/src/app/interfaces/notebook-repo.ts
new file mode 100644
index 00000000000..de037783ca7
--- /dev/null
+++ b/zeppelin-web-angular/src/app/interfaces/notebook-repo.ts
@@ -0,0 +1,32 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export interface NotebookRepo {
+ name: string;
+ className: string;
+ settings: NotebookRepoSettingsItem[];
+}
+
+export interface NotebookRepoPutData {
+ name: string;
+ settings: {
+ [key: string]: string;
+ };
+}
+
+export interface NotebookRepoSettingsItem {
+ type: string;
+ // tslint:disable-next-line:no-any
+ value: any[];
+ selected: string;
+ name: string;
+}
diff --git a/zeppelin-web-angular/src/app/interfaces/public-api.ts b/zeppelin-web-angular/src/app/interfaces/public-api.ts
index f00e442594e..8c54e3d3464 100644
--- a/zeppelin-web-angular/src/app/interfaces/public-api.ts
+++ b/zeppelin-web-angular/src/app/interfaces/public-api.ts
@@ -16,3 +16,4 @@ export * from './interpreter';
export * from './message-interceptor';
export * from './security';
export * from './credential';
+export * from './notebook-repo';
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
new file mode 100644
index 00000000000..3f4875a5bca
--- /dev/null
+++ b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/item/item.component.html
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+ Setting
+
+
+
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/item/item.component.less b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/item/item.component.less
new file mode 100644
index 00000000000..bc6d2805eb8
--- /dev/null
+++ b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/item/item.component.less
@@ -0,0 +1,37 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@import 'theme-mixin';
+
+.themeMixin({
+
+ display: block;
+ margin-bottom: @card-padding-base;
+ position: relative;
+
+ ::ng-deep .repo-item {
+ &.edit {
+ background: @orange-1;
+ }
+ }
+
+ .extra-wrap {
+ button {
+ transition: none;
+ }
+ button + button {
+ margin-bottom: 0;
+ margin-left: 8px;
+ }
+ }
+
+});
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
new file mode 100644
index 00000000000..f66247c9599
--- /dev/null
+++ b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/item/item.component.ts
@@ -0,0 +1,78 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {
+ ChangeDetectionStrategy,
+ ChangeDetectorRef,
+ Component,
+ EventEmitter,
+ Input,
+ OnChanges,
+ Output,
+ SimpleChanges
+} from '@angular/core';
+import { FormArray, FormBuilder, Validators } from '@angular/forms';
+import { NotebookRepo } from '@zeppelin/interfaces';
+
+@Component({
+ selector: 'zeppelin-notebook-repo-item',
+ templateUrl: './item.component.html',
+ styleUrls: ['./item.component.less'],
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class NotebookRepoItemComponent implements OnChanges {
+ @Input() repo: NotebookRepo;
+ @Output() readonly repoChange = new EventEmitter();
+
+ settingFormArray: FormArray;
+ editMode = false;
+
+ constructor(private cdr: ChangeDetectorRef, private fb: FormBuilder) {}
+
+ triggerEditMode() {
+ this.editMode = !this.editMode;
+ this.cdr.markForCheck();
+ }
+
+ save() {
+ this.settingFormArray.controls.forEach(control => {
+ control.markAsDirty();
+ control.updateValueAndValidity();
+ });
+
+ if (this.settingFormArray.valid) {
+ const values = this.settingFormArray.getRawValue() as string[];
+ values.forEach((value, i) => (this.repo.settings[i].selected = value));
+ this.repoChange.emit(this.repo);
+ this.editMode = false;
+ this.cdr.markForCheck();
+ }
+ }
+
+ cancel() {
+ this.buildForm();
+ this.editMode = false;
+ this.cdr.markForCheck();
+ }
+
+ buildForm() {
+ const controls = this.repo.settings.map(setting => {
+ return this.fb.control(setting.selected, [Validators.required]);
+ });
+ this.settingFormArray = this.fb.array(controls);
+ }
+
+ ngOnChanges(changes: SimpleChanges): void {
+ if (changes.repo) {
+ this.buildForm();
+ }
+ }
+}
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos-routing.module.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos-routing.module.ts
new file mode 100644
index 00000000000..e7e7ca19ad2
--- /dev/null
+++ b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos-routing.module.ts
@@ -0,0 +1,28 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import { NotebookReposComponent } from './notebook-repos.component';
+
+const routes: Routes = [
+ {
+ path: '',
+ component: NotebookReposComponent
+ }
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class NotebookReposRoutingModule {}
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos.component.html b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos.component.html
new file mode 100644
index 00000000000..d47ad877782
--- /dev/null
+++ b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos.component.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos.component.less b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos.component.less
new file mode 100644
index 00000000000..5a3f8f0b1ff
--- /dev/null
+++ b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos.component.less
@@ -0,0 +1,20 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@import 'theme-mixin';
+
+.themeMixin({
+
+ .content {
+ padding: @card-padding-base / 2;
+ }
+});
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos.component.ts
new file mode 100644
index 00000000000..1faffeeeab0
--- /dev/null
+++ b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos.component.ts
@@ -0,0 +1,51 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core';
+import { NotebookRepo } from '@zeppelin/interfaces';
+import { NotebookRepoService } from '@zeppelin/services';
+
+@Component({
+ selector: 'zeppelin-notebook-repos',
+ templateUrl: './notebook-repos.component.html',
+ styleUrls: ['./notebook-repos.component.less'],
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class NotebookReposComponent implements OnInit {
+ repositories: NotebookRepo[] = [];
+
+ constructor(private notebookRepoService: NotebookRepoService, private cdr: ChangeDetectorRef) {}
+
+ ngOnInit() {
+ this.getRepos();
+ }
+
+ getRepos() {
+ this.notebookRepoService.getRepos().subscribe(data => {
+ this.repositories = data.sort((a, b) => a.name.charCodeAt(0) - b.name.charCodeAt(0));
+ this.cdr.markForCheck();
+ });
+ }
+
+ updateRepoSetting(repo: NotebookRepo) {
+ const data = {
+ name: repo.className,
+ settings: {}
+ };
+ repo.settings.forEach(({ name, selected }) => {
+ data.settings[name] = selected;
+ });
+
+ this.notebookRepoService.updateRepo(data).subscribe(() => {
+ this.getRepos();
+ });
+ }
+}
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos.module.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos.module.ts
new file mode 100644
index 00000000000..2bb9d2528a9
--- /dev/null
+++ b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos.module.ts
@@ -0,0 +1,49 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+
+import { ShareModule } from '@zeppelin/share';
+
+import {
+ NzButtonModule,
+ NzCardModule,
+ NzFormModule,
+ NzIconModule,
+ NzInputModule,
+ NzSelectModule,
+ NzTableModule
+} from 'ng-zorro-antd';
+
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { NotebookRepoItemComponent } from './item/item.component';
+import { NotebookReposRoutingModule } from './notebook-repos-routing.module';
+import { NotebookReposComponent } from './notebook-repos.component';
+
+@NgModule({
+ declarations: [NotebookReposComponent, NotebookRepoItemComponent],
+ imports: [
+ CommonModule,
+ ShareModule,
+ FormsModule,
+ ReactiveFormsModule,
+ NotebookReposRoutingModule,
+ NzCardModule,
+ NzButtonModule,
+ NzInputModule,
+ NzTableModule,
+ NzIconModule,
+ NzFormModule,
+ NzSelectModule
+ ]
+})
+export class NotebookReposModule {}
diff --git a/zeppelin-web-angular/src/app/pages/workspace/workspace-routing.module.ts b/zeppelin-web-angular/src/app/pages/workspace/workspace-routing.module.ts
index 6815b8097c2..16928a33fc9 100644
--- a/zeppelin-web-angular/src/app/pages/workspace/workspace-routing.module.ts
+++ b/zeppelin-web-angular/src/app/pages/workspace/workspace-routing.module.ts
@@ -53,6 +53,11 @@ const routes: Routes = [
path: 'credential',
loadChildren: () =>
import('@zeppelin/pages/workspace/credential/credential.module').then(m => m.CredentialModule)
+ },
+ {
+ path: 'notebook-repos',
+ loadChildren: () =>
+ import('@zeppelin/pages/workspace/notebook-repos/notebook-repos.module').then(m => m.NotebookReposModule)
}
]
}
diff --git a/zeppelin-web-angular/src/app/services/notebook-repos.service.ts b/zeppelin-web-angular/src/app/services/notebook-repos.service.ts
new file mode 100644
index 00000000000..624599ae0fd
--- /dev/null
+++ b/zeppelin-web-angular/src/app/services/notebook-repos.service.ts
@@ -0,0 +1,36 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { NotebookRepo, NotebookRepoPutData } from '@zeppelin/interfaces';
+
+import { BaseRest } from './base-rest';
+import { BaseUrlService } from './base-url.service';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class NotebookRepoService extends BaseRest {
+ constructor(baseUrlService: BaseUrlService, private http: HttpClient) {
+ super(baseUrlService);
+ }
+
+ getRepos() {
+ return this.http.get(this.restUrl`/notebook-repositories`);
+ }
+
+ updateRepo(repo: NotebookRepoPutData) {
+ return this.http.put(this.restUrl`/notebook-repositories`, repo);
+ }
+}
diff --git a/zeppelin-web-angular/src/app/services/public-api.ts b/zeppelin-web-angular/src/app/services/public-api.ts
index 6c3dbc07ea5..f9bdfe9554f 100644
--- a/zeppelin-web-angular/src/app/services/public-api.ts
+++ b/zeppelin-web-angular/src/app/services/public-api.ts
@@ -29,3 +29,4 @@ export * from './runtime-compiler.service';
export * from './shortcut.service';
export * from './configuration.service';
export * from './credential.service';
+export * from './notebook-repos.service';
diff --git a/zeppelin-web-angular/src/app/share/header/header.component.html b/zeppelin-web-angular/src/app/share/header/header.component.html
index 71e8cd7c614..645da9aa22b 100644
--- a/zeppelin-web-angular/src/app/share/header/header.component.html
+++ b/zeppelin-web-angular/src/app/share/header/header.component.html
@@ -47,7 +47,7 @@
Interpreter
- Notebook
+ Notebook
Repos