This is an automated email from the ASF dual-hosted git repository. zjffdu pushed a commit to branch web_angular in repository https://gitbox.apache.org/repos/asf/zeppelin.git
The following commit(s) were added to refs/heads/web_angular by this push: new 762a8cd [ZEPPELIN-4398] Add notebook repository page 762a8cd is described below commit 762a8cd9c175ffcdced18b684b43ee59c4be9eaa Author: Hsuan Lee <hsua...@gmail.com> AuthorDate: Fri Dec 6 16:18:18 2019 +0800 [ZEPPELIN-4398] Add notebook repository page ### What is this PR for? Add the notebook repository page ### What type of PR is it? [Feature] ### What is the Jira issue? https://issues.apache.org/jira/browse/ZEPPELIN-4398 ### How should this be tested? Not applicable ### Screenshots (if appropriate) ![repos](https://user-images.githubusercontent.com/22736418/70308435-338edf00-1846-11ea-9030-bcf4ecaf22bb.gif) ### Questions: * Does the licenses files need update? No * Is there breaking changes for older versions? No * Does this needs documentation? No Author: Hsuan Lee <hsua...@gmail.com> Closes #3543 from hsuanxyz/feat/notebook-repos and squashes the following commits: d148902f2 [Hsuan Lee] feat: add notebook repository page --- .../interfaces/{public-api.ts => notebook-repo.ts} | 26 +++++-- .../src/app/interfaces/public-api.ts | 1 + .../notebook-repos/item/item.component.html | 79 ++++++++++++++++++++++ .../notebook-repos/item/item.component.less} | 31 +++++++-- .../notebook-repos/item/item.component.ts | 78 +++++++++++++++++++++ .../notebook-repos-routing.module.ts} | 22 ++++-- .../notebook-repos/notebook-repos.component.html | 21 ++++++ .../notebook-repos/notebook-repos.component.less} | 14 ++-- .../notebook-repos/notebook-repos.component.ts | 51 ++++++++++++++ .../notebook-repos/notebook-repos.module.ts | 49 ++++++++++++++ .../pages/workspace/workspace-routing.module.ts | 5 ++ .../src/app/services/notebook-repos.service.ts | 36 ++++++++++ .../src/app/services/public-api.ts | 1 + .../src/app/share/header/header.component.html | 2 +- 14 files changed, 391 insertions(+), 25 deletions(-) diff --git a/zeppelin-web-angular/src/app/interfaces/public-api.ts b/zeppelin-web-angular/src/app/interfaces/notebook-repo.ts similarity index 60% copy from zeppelin-web-angular/src/app/interfaces/public-api.ts copy to zeppelin-web-angular/src/app/interfaces/notebook-repo.ts index f00e442..de03778 100644 --- a/zeppelin-web-angular/src/app/interfaces/public-api.ts +++ b/zeppelin-web-angular/src/app/interfaces/notebook-repo.ts @@ -10,9 +10,23 @@ * limitations under the License. */ -export * from './ticket'; -export * from './trash-folder-id'; -export * from './interpreter'; -export * from './message-interceptor'; -export * from './security'; -export * from './credential'; +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 f00e442..8c54e3d 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 0000000..3f4875a --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/item/item.component.html @@ -0,0 +1,79 @@ +<!-- + ~ 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. + --> + +<nz-card class="repo-item" + [class.edit]="editMode" + [nzTitle]="repo.name" + [nzExtra]="extraTemplate"> + <ng-template #extraTemplate> + <div class="extra-wrap" *ngIf="!editMode"> + <button nz-button + nzSize="small" + (click)="triggerEditMode()"> + <i nz-icon nzType="edit"></i> + Edit + </button> + </div> + <div class="extra-wrap" *ngIf="editMode"> + <button nz-button + nzType="primary" + nzSize="small" + [disabled]="!settingFormArray.valid" + (click)="save()"> + <i nz-icon nzType="save" nzTheme="outline"></i> + Save + </button> + <button nz-button + nzSize="small" + (click)="cancel()"> + <i nz-icon nzType="close" nzTheme="outline"></i> + Cancel + </button> + </div> + </ng-template> + <h3>Setting</h3> + <form nz-form> + <nz-table nzTemplateMode nzSize="small"> + <thead> + <tr> + <th>Name</th> + <th>Value</th> + </tr> + </thead> + <tbody> + <tr *ngFor="let setting of repo.settings; index as i"> + <td>{{setting.name}}</td> + <ng-container *ngIf="!editMode"> + <td>{{setting.selected}}</td> + </ng-container> + <ng-container *ngIf="editMode"> + <td> + <input *ngIf="setting.type === 'INPUT'" + nzSize="small" + nz-input + [formControl]="settingFormArray.controls[i]"> + + <nz-select *ngIf="setting.type === 'DROPDOWN'" [formControl]="settingFormArray.controls[i]"> + <nz-option + *ngFor="let option of setting.value" + [nzLabel]="option" + [nzValue]="option"> + </nz-option> + </nz-select> + </td> + </ng-container> + </tr> + </tbody> + </nz-table> + </form> + +</nz-card> diff --git a/zeppelin-web-angular/src/app/interfaces/public-api.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/item/item.component.less similarity index 62% copy from zeppelin-web-angular/src/app/interfaces/public-api.ts copy to zeppelin-web-angular/src/app/pages/workspace/notebook-repos/item/item.component.less index f00e442..bc6d280 100644 --- a/zeppelin-web-angular/src/app/interfaces/public-api.ts +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/item/item.component.less @@ -10,9 +10,28 @@ * limitations under the License. */ -export * from './ticket'; -export * from './trash-folder-id'; -export * from './interpreter'; -export * from './message-interceptor'; -export * from './security'; -export * from './credential'; +@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 0000000..f66247c --- /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<NotebookRepo>(); + + 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/interfaces/public-api.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos-routing.module.ts similarity index 59% copy from zeppelin-web-angular/src/app/interfaces/public-api.ts copy to zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos-routing.module.ts index f00e442..e7e7ca1 100644 --- a/zeppelin-web-angular/src/app/interfaces/public-api.ts +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos-routing.module.ts @@ -9,10 +9,20 @@ * 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'; -export * from './ticket'; -export * from './trash-folder-id'; -export * from './interpreter'; -export * from './message-interceptor'; -export * from './security'; -export * from './credential'; +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 0000000..d47ad87 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos.component.html @@ -0,0 +1,21 @@ +<!-- + ~ 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. + --> +<zeppelin-page-header title="Notebook Repository" description="Manage your Notebook Repositories' settings."> +</zeppelin-page-header> +<div class="content"> + <zeppelin-notebook-repo-item + *ngFor="let repo of repositories" + (repoChange)="updateRepoSetting($event)" + [repo]="repo"> + + </zeppelin-notebook-repo-item> +</div> diff --git a/zeppelin-web-angular/src/app/interfaces/public-api.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos.component.less similarity index 74% copy from zeppelin-web-angular/src/app/interfaces/public-api.ts copy to zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos.component.less index f00e442..5a3f8f0 100644 --- a/zeppelin-web-angular/src/app/interfaces/public-api.ts +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook-repos/notebook-repos.component.less @@ -10,9 +10,11 @@ * limitations under the License. */ -export * from './ticket'; -export * from './trash-folder-id'; -export * from './interpreter'; -export * from './message-interceptor'; -export * from './security'; -export * from './credential'; +@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 0000000..1faffee --- /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 0000000..2bb9d25 --- /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 6815b80..16928a3 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 0000000..624599a --- /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<NotebookRepo[]>(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 6c3dbc0..f9bdfe9 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 71e8cd7..645da9a 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 @@ <a [routerLink]="['/interpreter']">Interpreter</a> </li> <li nz-menu-item routerLinkActive="ant-dropdown-menu-item-selected"> - <a [routerLink]="['/notebookRepos']">Notebook + <a [routerLink]="['/notebook-repos']">Notebook Repos </a> </li>