add developer center in swagger ui way

Signed-off-by: Meina Zhou <meinaz@vmware.com>
This commit is contained in:
Meina Zhou 2018-12-05 15:08:40 +08:00
parent 5388eb4db6
commit d45ccbbb29
22 changed files with 834 additions and 84 deletions

View File

@ -5,6 +5,7 @@ RUN mkdir -p /build_dir
COPY make/photon/portal/entrypoint.sh /
COPY src/portal /portal_src
COPY ./docs/swagger.yaml /portal_src
WORKDIR /portal_src
@ -24,7 +25,11 @@ RUN tdnf install -y nginx >> /dev/null \
EXPOSE 80
VOLUME /var/cache/nginx /var/log/nginx /run
COPY --from=nodeportal /build_dir/dist /usr/share/nginx/html
COPY --from=nodeportal /build_dir/swagger.yaml /usr/share/nginx/html
COPY --from=nodeportal /build_dir/swagger.json /usr/share/nginx/html
COPY make/photon/portal/nginx.conf /etc/nginx/nginx.conf
STOPSIGNAL SIGQUIT

View File

@ -5,6 +5,11 @@ cd /build_dir
cp -r /portal_src/* .
ls -la
# Update
apt-get update
apt-get install -y ruby
ruby -ryaml -rjson -e 'puts JSON.pretty_generate(YAML.load(ARGF))' swagger.yaml>swagger.json
cat ./package.json
npm install
@ -13,4 +18,4 @@ npm run build_lib
npm run link_lib
## Build production
npm run release
npm run release

View File

@ -24,6 +24,7 @@
"styles": [
"node_modules/@clr/icons/clr-icons.min.css",
"node_modules/@clr/ui/clr-ui.min.css",
"node_modules/swagger-ui/dist/swagger-ui.css",
"node_modules/prismjs/themes/prism-solarizedlight.css",
"src/styles.css"
],
@ -35,7 +36,10 @@
"node_modules/web-animations-js/web-animations.min.js",
"node_modules/marked/lib/marked.js",
"node_modules/prismjs/prism.js",
"node_modules/prismjs/components/prism-yaml.min.js"
"node_modules/prismjs/components/prism-yaml.min.js",
"node_modules/jquery/dist/jquery.slim.js",
"node_modules/popper.js/dist/umd/popper.js",
"node_modules/bootstrap/dist/js/bootstrap.js"
]
},
"configurations": {

View File

@ -1,8 +1,7 @@
<div>
<h2 class="h2-log-override" *ngIf="withTitle">{{'SIDE_NAV.LOGS' | translate}}</h2>
<div class="row flex-items-xs-between flex-items-xs-bottom">
<div></div>
<div class="action-head-pos rightPos">
<div class="action-head-pos">
<div class="select filterTag" [hidden]="!isOpenFilterTag">
<select id="selectKey" (change)="selectFilterKey($event)">
<option value="username">{{"AUDIT_LOG.USERNAME" | translate | lowercase}}</option>

File diff suppressed because it is too large Load Diff

View File

@ -32,18 +32,26 @@
"@clr/angular": "^0.12.10",
"@clr/icons": "^0.12.0",
"@clr/ui": "^0.12.0",
"@fortawesome/fontawesome-free": "^5.1.0-4",
"@ng-bootstrap/ng-bootstrap": "^2.0.0",
"@ngx-translate/core": "^10.0.2",
"@ngx-translate/http-loader": "^3.0.1",
"@types/jquery": "^2.0.41",
"@webcomponents/custom-elements": "^1.1.3",
"bootstrap": "^4.1.1",
"buffer": "^5.2.1",
"core-js": "^2.5.4",
"intl": "^1.2.5",
"jquery": "^3.3.1",
"mutationobserver-shim": "^0.3.2",
"ng-packagr": "^4.1.1",
"ngx-clipboard": "^11.1.1",
"ngx-cookie": "^1.0.0",
"ngx-markdown": "^6.2.0",
"popper.js": "^1.14.3",
"rxjs": "^6.3.1",
"stream": "^0.0.2",
"swagger-ui": "^3.20.2",
"ts-helpers": "^1.1.1",
"tslib": "^1.9.0",
"types": "^0.1.1",

View File

@ -20,6 +20,7 @@ import { HarborRoutingModule } from './harbor-routing.module';
import { SharedModule } from './shared/shared.module';
import { AccountModule } from './account/account.module';
import { ConfigurationModule } from './config/config.module';
import { DeveloperCenterModule } from './dev-center/dev-center.module';
import { registerLocaleData } from '@angular/common';
import { TranslateService } from "@ngx-translate/core";
@ -30,6 +31,7 @@ import { ProjectConfigComponent } from './project/project-config/project-config.
import zh from '@angular/common/locales/zh-Hans';
import es from '@angular/common/locales/es';
import localeFr from '@angular/common/locales/fr';
import { DevCenterComponent } from './dev-center/dev-center.component';
registerLocaleData(zh, 'zh-cn');
registerLocaleData(es, 'es-es');
registerLocaleData(localeFr, 'fr-fr');
@ -49,7 +51,7 @@ export function getCurrentLanguage(translateService: TranslateService) {
@NgModule({
declarations: [
AppComponent,
ProjectConfigComponent,
ProjectConfigComponent
],
imports: [
BrowserModule,
@ -57,7 +59,8 @@ export function getCurrentLanguage(translateService: TranslateService) {
BaseModule,
AccountModule,
HarborRoutingModule,
ConfigurationModule
ConfigurationModule,
DeveloperCenterModule
],
exports: [
],

View File

@ -2,7 +2,8 @@
<global-message [isAppLevel]="true"></global-message>
<navigator (showAccountSettingsModal)="openModal($event)" (showPwdChangeModal)="openModal($event)"></navigator>
<div class="content-container">
<div class="content-area" [class.container-override]="showSearch" [class.content-area-override]="!shouldOverrideContent" [class.start-content-padding]="shouldOverrideContent">
<div class="content-area" [class.container-override]="showSearch" [class.content-area-override]="!shouldOverrideContent"
[class.start-content-padding]="shouldOverrideContent">
<global-message [isAppLevel]="false"></global-message>
<!-- Only appear when searching -->
<search-result></search-result>
@ -17,46 +18,39 @@
<clr-icon shape="list" clrVerticalNavIcon></clr-icon>
{{'SIDE_NAV.LOGS' | translate}}
</a>
<clr-vertical-nav-group *ngIf="isSystemAdmin" routerLinkActive="active">
<a clrVerticalNavLink target="_blank" routerLink="/devcenter" routerLinkActive="active">
<clr-icon shape="terminal" clrVerticalNavIcon></clr-icon>
{{'SIDE_NAV.SYSTEM_MGMT.DEVCENTER' | translate}}
</a>
<clr-vertical-nav-group *ngIf="isSystemAdmin" routerLinkActive="active">
<clr-icon shape="administrator" clrVerticalNavIcon></clr-icon>
{{'SIDE_NAV.SYSTEM_MGMT.NAME' | translate}}
<a routerLink="#" hidden aria-hidden="true"></a>
<clr-vertical-nav-group-children *clrIfExpanded="true">
<a clrVerticalNavLink
routerLink="/harbor/users"
routerLinkActive="active">
<clr-icon shape="users" clrVerticalNavIcon></clr-icon>
{{'SIDE_NAV.SYSTEM_MGMT.USER' | translate}}
<a clrVerticalNavLink routerLink="/harbor/users" routerLinkActive="active">
<clr-icon shape="users" clrVerticalNavIcon></clr-icon>
{{'SIDE_NAV.SYSTEM_MGMT.USER' | translate}}
</a>
<a *ngIf='isLdapMode'
clrVerticalNavLink
routerLink="/harbor/groups"
routerLinkActive="active">
<clr-icon shape="users" clrVerticalNavIcon></clr-icon>
<a *ngIf='isLdapMode' clrVerticalNavLink routerLink="/harbor/groups" routerLinkActive="active">
<clr-icon shape="users" clrVerticalNavIcon></clr-icon>
{{'SIDE_NAV.SYSTEM_MGMT.GROUP' | translate}}
</a>
<a clrVerticalNavLink
routerLink="/harbor/registries"
routerLinkActive="active">
<clr-icon shape="block" clrVerticalNavIcon></clr-icon>
{{'SIDE_NAV.SYSTEM_MGMT.REGISTRY' | translate}}
<a clrVerticalNavLink routerLink="/harbor/registries" routerLinkActive="active">
<clr-icon shape="block" clrVerticalNavIcon></clr-icon>
{{'SIDE_NAV.SYSTEM_MGMT.REGISTRY' | translate}}
</a>
<a clrVerticalNavLink
routerLink="/harbor/replications"
routerLinkActive="active">
<clr-icon shape="cloud-traffic" clrVerticalNavIcon></clr-icon>
{{'SIDE_NAV.SYSTEM_MGMT.REPLICATION' | translate}}
<a clrVerticalNavLink routerLink="/harbor/replications" routerLinkActive="active">
<clr-icon shape="cloud-traffic" clrVerticalNavIcon></clr-icon>
{{'SIDE_NAV.SYSTEM_MGMT.REPLICATION' | translate}}
</a>
<a clrVerticalNavLink
routerLink="/harbor/configs"
routerLinkActive="active">
<clr-icon shape="cog" clrVerticalNavIcon></clr-icon>
{{'SIDE_NAV.SYSTEM_MGMT.CONFIG' | translate}}
<a clrVerticalNavLink routerLink="/harbor/configs" routerLinkActive="active">
<clr-icon shape="cog" clrVerticalNavIcon></clr-icon>
{{'SIDE_NAV.SYSTEM_MGMT.CONFIG' | translate}}
</a>
</clr-vertical-nav-group-children>
</clr-vertical-nav-group>
</clr-vertical-nav>
<hbr-operation-model *ngIf="isUserExisting"></hbr-operation-model>
<hbr-operation-model *ngIf="isUserExisting"></hbr-operation-model>
</div>
</clr-main-container>
<account-settings-modal></account-settings-modal>

View File

@ -0,0 +1,2 @@
<div class="swagger-container" style="overflow:scroll;"></div>

View File

@ -0,0 +1,8 @@
.swagger-container {
overflow: auto;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}

View File

@ -0,0 +1,26 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DevCenterComponent } from './dev-center.component';
describe('DevCenterComponent', () => {
let component: DevCenterComponent;
let fixture: ComponentFixture<DevCenterComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ DevCenterComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DevCenterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,37 @@
import { AfterViewInit, Component, ElementRef, OnInit } from '@angular/core';
import { Http } from '@angular/http';
import { throwError as observableThrowError, Observable } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
const SwaggerUI = require('swagger-ui');
@Component({
selector: 'dev-center',
templateUrl: 'dev-center.component.html',
styleUrls: ['dev-center.component.scss']
})
export class DevCenterComponent implements AfterViewInit {
private ui: any;
private host: any;
private json: any;
constructor(private el: ElementRef, private http: Http) {
}
ngAfterViewInit() {
this.http.get("/swagger.json")
.pipe(catchError(error => observableThrowError(error)))
.pipe(map(response => response.json())).subscribe(json => {
json.host = window.location.host;
const protocal = window.location.protocol;
json.schemes = [protocal.replace(":", "")];
let ui = SwaggerUI({
spec: json,
domNode: this.el.nativeElement.querySelector('.swagger-container'),
deepLinking: true,
presets: [
SwaggerUI.presets.apis
],
});
});
}
}

View File

@ -0,0 +1,23 @@
import { NgModule } from "@angular/core";
import { RouterModule } from "@angular/router";
import { CommonModule } from "@angular/common";
import { ClarityModule } from '@clr/angular';
import { SharedModule } from '../shared/shared.module';
import { DevCenterComponent } from "./dev-center.component";
@NgModule({
imports: [
CommonModule,
SharedModule,
RouterModule.forChild([{
path: "**",
component: DevCenterComponent,
}]),
ClarityModule.forRoot(),
],
declarations: [
DevCenterComponent,
],
})
export class DeveloperCenterModule {}

View File

@ -22,6 +22,7 @@ import { MemberGuard } from './shared/route/member-guard-activate.service';
import { PageNotFoundComponent } from './shared/not-found/not-found.component';
import { HarborShellComponent } from './base/harbor-shell/harbor-shell.component';
import { ConfigurationComponent } from './config/config.component';
import { DevCenterComponent } from './dev-center/dev-center.component';
import { UserComponent } from './user/user.component';
import { SignInComponent } from './account/sign-in/sign-in.component';
@ -43,7 +44,7 @@ import { LeavingRepositoryRouteDeactivate } from './shared/route/leaving-reposit
import { ProjectComponent } from './project/project.component';
import { ProjectDetailComponent } from './project/project-detail/project-detail.component';
import { MemberComponent } from './project/member/member.component';
import {ProjectLabelComponent} from "./project/project-label/project-label.component";
import { ProjectLabelComponent } from "./project/project-label/project-label.component";
import { ProjectConfigComponent } from './project/project-config/project-config.component';
import { ProjectRoutingResolver } from './project/project-routing-resolver.service';
import { ListChartsComponent } from './project/list-charts/list-charts.component';
@ -53,6 +54,10 @@ import { ChartDetailComponent } from './project/chart-detail/chart-detail.compon
const harborRoutes: Routes = [
{ path: '', redirectTo: 'harbor', pathMatch: 'full' },
{ path: 'reset_password', component: ResetPasswordComponent },
{
path: 'devcenter',
component: DevCenterComponent
},
{
path: 'harbor',
component: HarborShellComponent,

View File

@ -121,7 +121,8 @@
"GROUP": "Groups",
"REGISTRY": "Registries",
"REPLICATION": "Replications",
"CONFIG": "Configuration"
"CONFIG": "Configuration",
"DEVCENTER": "Developer Center"
},
"LOGS": "Logs"
},

View File

@ -121,7 +121,8 @@
"REGISTRY": "Registries",
"GROUP": "Groups",
"REPLICATION": "Replicacións",
"CONFIG": "Configuración"
"CONFIG": "Configuración",
"DEVCENTER": "Developer Center"
},
"LOGS": "Logs"
},

View File

@ -107,7 +107,8 @@
"USER": "Utilisateurs",
"GROUP": "Groups",
"REPLICATION": "Réplication",
"CONFIG": "Configuration"
"CONFIG": "Configuration",
"DEVCENTER": "Developer Center"
},
"LOGS": "Logs"
},

View File

@ -119,7 +119,8 @@
"GROUP": "Grupos",
"REGISTRY": "Registros",
"REPLICATION": "Replicações",
"CONFIG": "Configuração"
"CONFIG": "Configuração",
"DEVCENTER": "Developer Center"
},
"LOGS": "Logs"
},

View File

@ -120,7 +120,8 @@
"GROUP": "组管理",
"REGISTRY": "仓库管理",
"REPLICATION": "复制管理",
"CONFIG": "配置管理"
"CONFIG": "配置管理",
"DEVCENTER": "开发者中心"
},
"LOGS": "日志"
},

View File

@ -37,3 +37,6 @@ import 'intl/locale-data/jsonp/zh';
import 'zone.js/dist/zone';
(window as any).global = window;
// @ts-ignore
window.Buffer = window.Buffer || require('buffer').Buffer;

View File

@ -8,6 +8,10 @@
"es6",
"dom"
],
"types": [
"node",
"jasmine"
],
"mapRoot": "./",
"module": "commonjs",
"moduleResolution": "node",

View File

@ -7,7 +7,7 @@
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": [
"es2015",
"es2017",
"dom"
],
"noImplicitAny": false,