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

+
+ + + + Name + Value + + + + + {{setting.name}} + + {{setting.selected}} + + + + + + + + + + + + + + +
+ +
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