New updates about current progress.

This commit is contained in:
kunw 2017-02-13 13:43:38 +08:00
parent fa072a2903
commit 9a97af1783
101 changed files with 8807 additions and 1 deletions

16
Dockerfile Normal file
View File

@ -0,0 +1,16 @@
FROM node:7.4.0
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY harbor-app /usr/src/app
RUN npm install -g bower
RUN npm install -g angular-cli
RUN npm install
EXPOSE 4200
ENTRYPOINT [ "npm", "start" ]

9
README.md Normal file
View File

@ -0,0 +1,9 @@
# Harbor Clarity Demo
How to run this demo by using Docker?
Follow up these steps below.
```sh
$ docker build -t . harbor-clarity-demo
$ docker run -d -p 4200:4200 harbor-clarity-demo
```

View File

@ -1 +0,0 @@
#Harbor Clarity

20
harbor-app/.editorconfig Normal file
View File

@ -0,0 +1,20 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = 0
trim_trailing_whitespace = true
# Indentation override
#[lib/**.js]
#[{package.json,.travis.yml}]
#[**/**.js]

9
harbor-app/.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
coverage/
dist/
html-report/
node_modules/
typings/
**/*npm-debug.log.*
**/*yarn-error.log.*
.idea/
.DS_Store

10
harbor-app/.travis.yml Normal file
View File

@ -0,0 +1,10 @@
language: node_js
node_js:
- "6.0"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8

View File

@ -0,0 +1,19 @@
Contributor Code of Conduct
======================
As contributors and maintainers of the Clarity project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities.
Communication through any of Clarity's channels (GitHub, mailing lists, Twitter, and so on) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
We promise to extend courtesy and respect to everyone involved in this project, regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the Clarity project to do the same.
If any member of the community violates this code of conduct, the maintainers of the Clarity project may take action, including removing issues, comments, and PRs or blocking accounts, as deemed appropriate.
If you are subjected to or witness unacceptable behavior, or have any other concerns, please communicate with us.
If you have suggestions to improve this Code of Conduct, please submit an issue or PR.
**Attribution**
This Code of Conduct is adapted from the Angular project, version 0.3a-angular, available at this page: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md

113
harbor-app/CONTRIBUTING.md Normal file
View File

@ -0,0 +1,113 @@
# Contributing to clarity-seed
The clarity-seed project team welcomes contributions from the community. Follow the guidelines to contribute to the seed.
## Contribution Guidelines
Before you start working with Clarity, please complete the following steps:
- Read our [code of conduct](/CODE_OF_CONDUCT.md).
- Read our [Developer Certificate of Origin](https://cla.vmware.com/dco). All contributions to this repository must be signed as described on that page. Your signature certifies that you wrote the patch or have the right to pass it on as an open-source patch.
## Contribution Flow
Here are the typical steps in a contributor's workflow:
- [Fork](https://help.github.com/articles/fork-a-repo/) the main Clarity seed repository.
- Clone your fork and set the upstream remote to the main Clarity repository.
- Set your name and e-mail in the Git configuration for signing.
- Create a topic branch from where you want to base your work.
- Make commits of logical units.
- Make sure your commit messages are in the proper format (see below).
- Push your changes to a topic branch in your fork of the repository.
- [Submit a pull request](https://help.github.com/articles/about-pull-requests/).
Example:
``` shell
# Clone your forked repository
git clone git@github.com:<github username>/clarity-seed.git
# Navigate to the directory
cd clarity-seed
# Set name and e-mail configuration
git config user.name "John Doe"
git config user.email johndoe@example.com
# Setup the upstream remote
git remote add upstream https://github.com/vmware/clarity-seed.git
# Create a topic branch for your changes
git checkout -b my-new-feature master
# After making the desired changes, commit and push to your fork
git commit -a -s
git push origin my-new-feature
```
### Staying In Sync With Upstream
When your branch gets out of sync with the master branch, use the following to update:
``` shell
git checkout my-new-feature
git fetch -a
git pull --rebase upstream master
git push --force-with-lease origin my-new-feature
```
### Updating Pull Requests
If your PR fails to pass CI, or requires changes based on code review, you'll most likely want to squash these changes into existing commits.
If your pull request contains a single commit, or your changes are related to the most recent commit, you can amend the commit.
``` shell
git add .
git commit --amend
git push --force-with-lease origin my-new-feature
```
If you need to squash changes into an earlier commit, use the following:
``` shell
git add .
git commit --fixup <commit>
git rebase -i --autosquash master
git push --force-with-lease origin my-new-feature
```
Make sure you add a comment to the PR indicating that your changes are ready to review. GitHub does not generate a notification when you use git push.
### Formatting Commit Messages
Use this format for your commit message:
```
<detailed commit message>
<BLANK LINE>
<reference to closing an issue>
<BLANK LINE>
Signed-off-by: Your Name <your.email@example.com>
```
#### Writing Guidelines
These documents provide guidance creating a well-crafted commit message:
* [How to Write a Git Commit Message](http://chris.beams.io/posts/git-commit/)
* [Closing Issues Via Commit Messages](https://help.github.com/articles/closing-issues-via-commit-messages/)
## Reporting Bugs and Creating Issues
You can submit an issue or a bug to our [GitHub repository](https://github.com/vmware/clarity-seed/issues). You must provide:
* Instruction on how to replicate the issue
* The version number of Angular
* The version number of Clarity
* The version number of Node
* The browser name and version number
* The OS running the seed

View File

@ -0,0 +1,16 @@
Clarity Seed
Copyright © 2016 VMware, Inc. All rights reserved
The MIT license (the “License”) set forth below applies to all parts of the Clarity Seed project. You may not use this file except in compliance with the License. 
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,8 @@
Clarity Seed
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
This product is licensed to you under the MIT license (the "MIT License"). You may not use this product except in compliance with the MIT License.
This product may include a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file.

121
harbor-app/README.md Normal file
View File

@ -0,0 +1,121 @@
![Clarity](logo.png)
Clarity Seed
============
This is a seed project for Angular 2 applications using [Clarity](https://github.com/vmware/clarity). For more information on the Clarity Design System, visit the [Clarity website](https://vmware.github.io/clarity/).
We offer this seed project in three different build systems:
1. **Angular-CLI version (branch: master)**
2. Webpack 2 version (branch: webpack)
3. SystemJS version (branch: systemjs)
Getting started
----------------------------------
#### Angular-CLI version
This seed version provides the following out of the box:
- Angular 2 application with [clarity-icons](https://www.npmjs.com/package/clarity-icons), [clarity-ui](https://www.npmjs.com/package/clarity-ui) and [clarity-angular](https://www.npmjs.com/package/clarity-angular) included
- Development and production builds
- Unit test setup with Jasmine and Karma
- End-to-end test setup with Protractor
- SASS processor
- TSLint
- And other goodies that come with [Angular-CLI](https://github.com/angular/angular-cli#generating-and-serving-an-angular2-project-via-a-development-server) (v1.0.0-beta.20-4)
#### Installation
*Prerequisite*: Please install Angular-CLI by following [these instructions](https://github.com/angular/angular-cli#installation).
*Note*: Even though it's optional, we recommend you to use [yarn](https://yarnpkg.com/) instead of `npm install` for installing the dependencies.
```bash
git clone https://github.com/vmware/clarity-seed.git
cd clarity-seed
# install the project's dependencies
yarn # or run "npm install"
# starts the application in dev mode and watches your files for livereload
ng serve
```
#### Using Angular-CLI
```bash
# generating a new component
ng g component my-new-component
# generating a new directive
ng g directive my-new-directive
# to learn more about Angular-CLI commands and their usages
ng help
```
For comprehensive documentation on Angular-CLI, please see their [github repository](https://github.com/angular/angular-cli).
#### Test and build scripts
```bash
# running unit tests
ng test
# running e2e tests
ng e2e
# dev build
ng build
# prod build
ng build --prod
```
## Documentation
For documentation on the Clarity Design System, including a list of components and example usage, see [our website](https://vmware.github.io/clarity).
#### Directory structure
```
.
├── README.md
├── karma.conf.js <- configuration of the test runner
├── package.json <- dependencies of the project
├── protractor.config.js <- e2e tests configuration
├── src/ <- source code of the application
│   ├── app/
│   │   └── component/
│   │   └── <component>.component.html
│   │   └── <component>.component.scss
│   │   └── <component>.component.spec.ts
│   │   └── <component>.component.ts
│   │   └── app.component.html
│   │   └── app.component.scss
│   │   └── app.component.ts
│   │   └── app.e2e-spec.js <- sample e2e spec file
│   │   └── app.module.ts
│   │   └── app.routing.ts
│   │   └── main.ts <- boostrap file for the angular app
│   └── index.html
├── angular-cli.json <- configuration of the angular-cli
├── tsconfig.json <- configuration of the typescript project
├── tslint.json <- sample configuration file for tslint
└── yarn.lock
```
## Contributing
The Clarity project team welcomes contributions from the community. For more detailed information, see [CONTRIBUTING.md](CONTRIBUTING.md).
## License
The clarity-seed project is licensed under the MIT license.
## Feedback
If you find a bug or want to request a new feature, please open a [GitHub issue](https://github.com/vmware/clarity-seed/issues).

View File

@ -0,0 +1,67 @@
{
"project": {
"version": "1.0.0-beta.20-4",
"name": "clarity-seed"
},
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": [
"images",
"favicon.ico"
],
"index": "index.html",
"main": "main.ts",
"test": "test.ts",
"tsconfig": "tsconfig.json",
"prefix": "app",
"mobile": false,
"styles": [
"../node_modules/clarity-icons/clarity-icons.min.css",
"../node_modules/clarity-ui/clarity-ui.min.css",
"styles.css"
],
"scripts": [
"../node_modules/core-js/client/shim.min.js",
"../node_modules/mutationobserver-shim/dist/mutationobserver.min.js",
"../node_modules/@webcomponents/custom-elements/custom-elements.min.js",
"../node_modules/clarity-icons/clarity-icons.min.js",
"../node_modules/web-animations-js/web-animations.min.js"
],
"environments": {
"source": "environments/environment.ts",
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
}
],
"addons": [],
"packages": [],
"e2e": {
"protractor": {
"config": "./protractor.config.js"
}
},
"test": {
"karma": {
"config": "./karma.conf.js"
}
},
"defaults": {
"styleExt": "scss",
"prefixInterfaces": false,
"inline": {
"style": false,
"template": false
},
"spec": {
"class": false,
"component": true,
"directive": true,
"module": false,
"pipe": true,
"service": true
}
}
}

View File

@ -0,0 +1,17 @@
import {ClaritySeedAppHome} from './app.po';
fdescribe('clarity-seed app', function () {
let expectedMsg: string = 'This is a Clarity seed application. This is the default page that loads for the application.';
let page: ClaritySeedAppHome;
beforeEach(() => {
page = new ClaritySeedAppHome();
});
it('should display: ' + expectedMsg, () => {
page.navigateTo();
expect(page.getParagraphText()).toEqual(expectedMsg)
});
});

13
harbor-app/e2e/app.po.ts Normal file
View File

@ -0,0 +1,13 @@
import { browser, element, by } from 'protractor';
export class ClaritySeedAppHome {
navigateTo() {
return browser.get('/');
}
getParagraphText() {
return element(by.css('my-app p')).getText();
}
}

View File

@ -0,0 +1,25 @@
{
"compileOnSave": false,
"compilerOptions": {
"rootDir": "../",
"baseUrl": "",
"declaration": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"module": "commonjs",
"moduleResolution": "node",
"outDir": "dist/out-tsc-e2e",
"sourceMap": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"types": [
"jasmine"
]
},
"exclude": [
"node_modules",
"dist"
]
}

44
harbor-app/karma.conf.js Normal file
View File

@ -0,0 +1,44 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/0.13/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', 'angular-cli'],
plugins: [
require('karma-jasmine'),
require('karma-phantomjs-launcher'),
require('karma-mocha-reporter'),
require('karma-remap-istanbul'),
require('angular-cli/plugins/karma')
],
files: [
{pattern: './src/test.ts', watched: false}
],
preprocessors: {
'./src/test.ts': ['angular-cli']
},
mime: {
'text/x-typescript': ['ts', 'tsx']
},
remapIstanbulReporter: {
reports: {
html: 'coverage',
lcovonly: './coverage/coverage.lcov'
}
},
angularCli: {
config: './angular-cli.json',
environment: 'dev'
},
reporters: config.angularCli && config.angularCli.codeCoverage
? ['mocha', 'karma-remap-istanbul']
: ['mocha'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['PhantomJS'],
singleRun: true
});
};

BIN
harbor-app/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

58
harbor-app/package.json Normal file
View File

@ -0,0 +1,58 @@
{
"name": "clarity-seed",
"version": "0.8.0",
"description": "Angular-CLI starter for a Clarity project",
"angular-cli": {},
"scripts": {
"start": "ng serve --host 0.0.0.0",
"lint": "tslint \"src/**/*.ts\"",
"test": "ng test --single-run",
"pree2e": "webdriver-manager update",
"e2e": "protractor"
},
"private": true,
"dependencies": {
"@angular/common": "^2.4.1",
"@angular/compiler": "^2.4.1",
"@angular/core": "^2.4.1",
"@angular/forms": "^2.4.1",
"@angular/http": "^2.4.1",
"@angular/platform-browser": "^2.4.1",
"@angular/platform-browser-dynamic": "^2.4.1",
"@angular/router": "^3.4.1",
"@webcomponents/custom-elements": "1.0.0-alpha.3",
"clarity-angular": "^0.8.0",
"clarity-icons": "^0.8.0",
"clarity-ui": "^0.8.0",
"core-js": "^2.4.1",
"mutationobserver-shim": "^0.3.2",
"rxjs": "^5.0.1",
"ts-helpers": "^1.1.1",
"web-animations-js": "^2.2.1",
"zone.js": "^0.7.2"
},
"devDependencies": {
"@angular/compiler-cli": "^2.4.1",
"@types/core-js": "^0.9.34",
"@types/jasmine": "^2.2.30",
"@types/node": "^6.0.42",
"angular-cli": "^1.0.0-beta.24",
"bootstrap": "4.0.0-alpha.5",
"codelyzer": "~1.0.0-beta.3",
"enhanced-resolve": "^3.0.0",
"jasmine-core": "2.4.1",
"jasmine-spec-reporter": "2.5.0",
"karma": "1.2.0",
"karma-cli": "^1.0.1",
"karma-jasmine": "^1.0.2",
"karma-mocha-reporter": "^2.2.1",
"karma-phantomjs-launcher": "^1.0.0",
"karma-remap-istanbul": "^0.2.1",
"protractor": "4.0.9",
"ts-node": "1.2.1",
"tslint": "^4.1.1",
"typescript": "~2.0.3",
"typings": "^1.4.0",
"webdriver-manager": "10.2.5"
}
}

View File

@ -0,0 +1,32 @@
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/docs/referenceConf.js
/*global jasmine */
var SpecReporter = require('jasmine-spec-reporter');
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./e2e/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
useAllAngular2AppRoots: true,
beforeLaunch: function() {
require('ts-node').register({
project: 'e2e'
});
},
onPrepare: function() {
jasmine.getEnv().addReporter(new SpecReporter());
}
};

View File

@ -0,0 +1,14 @@
import { NgModule } from '@angular/core';
import { SignInComponent } from './sign-in.component';
import { SharedModule } from '../shared.module';
import { RouterModule } from '@angular/router';
@NgModule({
imports: [
SharedModule,
RouterModule
],
declarations: [ SignInComponent ],
exports: [SignInComponent]
})
export class AccountModule {}

View File

@ -0,0 +1,10 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'forgot-password',
templateUrl: "forgot-password.component.html"
})
export class ForgotPasswordComponent {
// constructor(private router: Router){}
}

View File

@ -0,0 +1,10 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'reset-password',
templateUrl: "reset-password.component.html"
})
export class ResetPasswordComponent {
// constructor(private router: Router){}
}

View File

@ -0,0 +1,29 @@
<div class="login-wrapper">
<form class="login">
<label class="title">
VMware Harbor<span class="trademark">&#8482;</span>
</label>
<div class="login-group">
<div class="auth-source select">
<select id="login-auth-source-1">
<option>Local Users</option>
<option>Administrator</option>
</select>
</div>
<input class="username" type="text" id="login_username" placeholder="Username">
<input class="password" type="password" id="login_password" placeholder="Password">
<div class="checkbox">
<input type="checkbox" id="rememberme">
<label for="rememberme">
Remember me
</label>
</div>
<div class="error active">
Invalid user name or password
</div>
<button type="submit" class="btn btn-primary" [routerLink]="['/harbor', 'dashboard']">LOG IN</button>
<a href="..." class="signup">Sign up for an account</a>
</div>
</form>
</div>

View File

@ -0,0 +1,10 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'sign-in',
templateUrl: "sign-in.component.html"
})
export class SignInComponent {
// constructor(private router: Router){}
}

View File

@ -0,0 +1,10 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'sign-up',
templateUrl: "sign-up.component.html"
})
export class SignUpComponent {
// constructor(private router: Router){}
}

View File

@ -0,0 +1 @@
<router-outlet></router-outlet>

View File

@ -0,0 +1,8 @@
// Copyright (c) 2016 VMware, Inc. All Rights Reserved.
// This software is released under MIT license.
// The full license information can be found in LICENSE in the root directory of this project.
.clr-icon {
&.clr-clarity-logo {
background-image: url(../images/clarity_logo.svg);
}
}

View File

@ -0,0 +1,46 @@
/* tslint:disable:no-unused-variable */
// import { TestBed, async, ComponentFixture } from '@angular/core/testing';
// import { AppComponent } from './app.component';
// import { HomeComponent } from "./home/home.component";
// import { AboutComponent } from "./about/about.component";
// import { ClarityModule } from "clarity-angular";
// import { ROUTING } from "./app.routing";
// import { APP_BASE_HREF } from "@angular/common";
// describe('AppComponent', () => {
// let fixture: ComponentFixture<any>;
// let compiled: any;
// beforeEach(() => {
// TestBed.configureTestingModule({
// declarations: [
// AppComponent,
// AboutComponent,
// HomeComponent
// ],
// imports: [
// ClarityModule,
// ROUTING
// ],
// providers: [{provide: APP_BASE_HREF, useValue: '/'}]
// });
// fixture = TestBed.createComponent(AppComponent);
// fixture.detectChanges();
// compiled = fixture.nativeElement;
// });
// afterEach(() => {
// fixture.destroy();
// });
// it('should create the app', async(() => {
// expect(compiled).toBeTruthy();
// }));
// });

View File

@ -0,0 +1,12 @@
import { Component } from '@angular/core';
// import { Router } from '@angular/router';
@Component({
selector: 'harbor-app',
templateUrl: 'app.component.html',
styleUrls: []
})
export class AppComponent {
// constructor(private router: Router) {
// }
}

View File

@ -0,0 +1,26 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { ClarityModule } from 'clarity-angular';
import { AppComponent } from './app.component';
import { AccountModule } from './account/account.module';
import { HarborShellModule } from './harbor-shell/harbor.shell.module';
import { HarborRoutingModule } from './harbor-routing.module';
import { SharedModule } from './shared.module';
@NgModule({
declarations: [
AppComponent,
],
imports: [
SharedModule,
AccountModule,
HarborShellModule,
HarborRoutingModule
],
providers: [],
bootstrap: [ AppComponent ]
})
export class AppModule {
}

View File

@ -0,0 +1,27 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { ClarityModule } from 'clarity-angular';
import { AppComponent } from './app.component';
import { AccountModule } from './account/account.module';
import { HarborShellModule } from './harbor-shell/harbor.shell.module';
import { HarborRoutingModule } from './harbor-routing.module';
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
ClarityModule
],
exports: [
BrowserModule,
FormsModule,
HttpModule,
ClarityModule
]
})
export class CoreModule {
}

View File

@ -0,0 +1,54 @@
<h3>Dashboard</h3>
<div class="row">
<div class="col-lg-4 col-md-12 col-sm-12 col-xs-12">
<div class="card">
<div class="card-block">
<h1 class="card-title">Why user Harbor?</h1>
<p class="card-text">
Project Harbor is an enterprise-class registry server, which extends the open source Docker Registry server by adding the functionality usually required by an enterprise, such as security, control, and management. Harbor is primarily designed to be a private registry - providing the needed security and control that enterprises require. It also helps minimize ...
</p>
</div>
<div class="card-footer">
<a href="..." class="btn btn-sm btn-link">View all</a>
</div>
</div>
</div>
<div class="col-lg-4 col-md-12 col-sm-12 col-xs-12">
<div class="card">
<div class="card-block">
<h1 class="card-title">Getting started</h1>
<ul class="list" style="list-style-type: none;">
<li><img src="../../images/Step1.png" style="width: 19%; height: auto;"/><a style="margin: 30px;" href="">Anonymous repository access</a></li>
<li><img src="../../images/Step2.png" style="width: 19%; height: auto;"/><a style="margin: 30px;" href="">Repositories managed by project</a></li>
<li><img src="../../images/Step3.png" style="width: 19%; height: auto;"/><a style="margin: 30px;" href="">Role based access control</a></li>
</ul>
</div>
</div>
</div>
<div class="col-lg-4 col-md-12 col-sm-12 col-xs-12">
<div class="card">
<div class="card-block">
<h1 class="card-title">Activities</h1>
<p class="card-text">
...
</p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-8 col-md-8 col-sm-12 col-xs-12">
<clr-datagrid>
<clr-dg-column>Name</clr-dg-column>
<clr-dg-column>Version</clr-dg-column>
<clr-dg-column>Count</clr-dg-column>
<clr-dg-row *ngFor="let r of repositories">
<clr-dg-cell>{{r.name}}</clr-dg-cell>
<clr-dg-cell>{{r.version}}</clr-dg-cell>
<clr-dg-cell>{{r.count}}</clr-dg-cell>
</clr-dg-row>
<clr-dg-footer>{{repositories.length}} item(s)</clr-dg-footer>
</clr-datagrid>
</div>
</div>

View File

@ -0,0 +1,20 @@
import { Component, OnInit } from '@angular/core';
import { Repository } from '../repository/repository';
@Component({
selector: 'dashboard',
templateUrl: 'dashboard.component.html'
})
export class DashboardComponent implements OnInit {
repositories: Repository[];
ngOnInit(): void {
this.repositories = [
{ name: 'Ubuntu', version: '14.04', count: 1 },
{ name: 'MySQL', version: 'Latest', count: 2 },
{ name: 'Photon', version: '1.0', count: 3 }
];
}
}

View File

@ -0,0 +1,10 @@
import { NgModule } from '@angular/core';
import { DashboardComponent } from './dashboard.component';
import { SharedModule } from '../shared.module';
@NgModule({
imports: [ SharedModule ],
declarations: [ DashboardComponent ],
exports: [ DashboardComponent ]
})
export class DashboardModule {}

View File

@ -0,0 +1,10 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'footer',
templateUrl: "footer.component.html"
})
export class FooterComponent {
// constructor(private router: Router){}
}

View File

@ -0,0 +1,8 @@
import { NgModule } from '@angular/core';
import { FooterComponent } from './footer.component';
@NgModule({
declarations: [ FooterComponent ],
exports: [ FooterComponent ]
})
export class FooterModule {}

View File

@ -0,0 +1,5 @@
<a class="nav-link">
<span class="nav-text">
<clr-icon shape="search"></clr-icon>
</span>
</a>

View File

@ -0,0 +1,10 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'global-search',
templateUrl: "global-search.component.html"
})
export class GlobalSearchComponent {
// constructor(private router: Router){}
}

View File

@ -0,0 +1,10 @@
import { NgModule } from '@angular/core';
import { GlobalSearchComponent } from './global-search.component';
import { SharedModule } from '../shared.module';
@NgModule({
imports: [ SharedModule ],
declarations: [ GlobalSearchComponent ],
exports: [ GlobalSearchComponent ]
})
export class GlobalSearchModule {}

View File

@ -0,0 +1,20 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { SignInComponent } from './account/sign-in.component';
const harborRoutes: Routes = [
{ path: '', redirectTo: '/sign-in', pathMatch: 'full' },
{ path: 'sign-in', component: SignInComponent }
];
@NgModule({
imports: [
RouterModule.forRoot(harborRoutes)
],
exports: [ RouterModule ]
})
export class HarborRoutingModule {
}

View File

@ -0,0 +1,35 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HarborShellComponent } from './harbor-shell.component';
import { DashboardComponent } from '../dashboard/dashboard.component';
import { ProjectComponent } from '../project/project.component';
import { ProjectListComponent } from '../project/project-list.component';
import { ProjectDetailComponent } from '../project-detail/project-detail.component';
import { RepositoryComponent } from '../repository/repository.component';
import { ReplicationComponent } from '../replication/replication.component';
import { MemberComponent } from '../member/member.component';
import { LogComponent } from '../log/log.component';
const harborShellRoutes: Routes = [
{
path: 'harbor',
component: HarborShellComponent,
children: [
{ path: 'dashboard', component: DashboardComponent },
{ path: 'project', component: ProjectComponent }
]
}
];
@NgModule({
imports: [
RouterModule.forChild(harborShellRoutes)
],
exports: [ RouterModule ]
})
export class HarborShellRoutingModule {
}

View File

@ -0,0 +1,40 @@
<clr-main-container>
<clr-modal [(clrModalOpen)]="account_settings_opened">
<h3 class="modal-title">Accout Settings</h3>
<div class="modal-body">
<form>
<section class="form-block">
<div class="form-group">
<label for="account_settings_username" class="col-md-4">Username</label>
<input type="text" class="col-md-8" id="account_settings_username" size="20">
</div>
<div class="form-group">
<label for="account_settings_email" class="col-md-4">Email</label>
<input type="text" class="col-md-8" id="account_settings_email" size="20">
</div>
<div class="form-group">
<label for="account_settings_full_name" class="col-md-4">Full name</label>
<input type="text" class="col-md-8" id="account_settings_full_name" size="20">
</div>
<div class="form-group">
<label for="account_settings_comments" class="col-md-4">Comments</label>
<input type="text" class="col-md-8" id="account_settings_comments" size="20">
</div>
<div class="form-group">
<button type="button" class="col-md-4" class="btn btn-outline">Change Password</button>
</div>
</section>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline" (click)="account_settings_opened = false">Cancel</button>
<button type="button" class="btn btn-primary" (click)="account_settings_opened = false">Ok</button>
</div>
</clr-modal>
<navigator></navigator>
<div class="content-container">
<div class="content-area">
<router-outlet></router-outlet>
</div>
</div>
</clr-main-container>

View File

@ -0,0 +1,10 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'harbor-shell',
templateUrl: 'harbor-shell.component.html'
})
export class HarborShellComponent {
}

View File

@ -0,0 +1,30 @@
import { NgModule } from '@angular/core';
import { NavigatorModule } from '../navigator/navigator.module';
import { GlobalSearchModule } from '../global-search/global-search.module';
import { FooterModule } from '../footer/footer.module';
import { DashboardModule } from '../dashboard/dashboard.module';
import { ProjectModule } from '../project/project.module';
import { ProjectDetailModule } from '../project-detail/project-detail.module';
import { HarborShellRoutingModule } from './harbor-shell-routing.module';
import { HarborShellComponent } from './harbor-shell.component';
import { SharedModule } from '../shared.module';
@NgModule({
imports: [
SharedModule,
GlobalSearchModule,
NavigatorModule,
FooterModule,
DashboardModule,
ProjectModule,
ProjectDetailModule,
HarborShellRoutingModule
],
declarations: [ HarborShellComponent ],
exports: [ HarborShellComponent ]
})
export class HarborShellModule {}

View File

@ -0,0 +1,2 @@
export * from './app.component';
export * from './app.module';

View File

@ -0,0 +1,24 @@
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="row flex-items-xs-between">
<div class="col-md-2 push-md-8">
<input type="text" placeholder="Search for user">
</div>
</div>
<clr-datagrid>
<clr-dg-column>Username</clr-dg-column>
<clr-dg-column>Repository Name</clr-dg-column>
<clr-dg-column>Tag</clr-dg-column>
<clr-dg-column>Operation</clr-dg-column>
<clr-dg-column>Timestamp</clr-dg-column>
<clr-dg-row *ngFor="let l of logs">
<clr-dg-cell>{{l.username}}</clr-dg-cell>
<clr-dg-cell>{{l.repoName}}</clr-dg-cell>
<clr-dg-cell>{{l.tag}}</clr-dg-cell>
<clr-dg-cell>{{l.operation}}</clr-dg-cell>
<clr-dg-cell>{{l.timestamp}}</clr-dg-cell>
</clr-dg-row>
<clr-dg-footer>{{logs.length}} item(s)</clr-dg-footer>
</clr-datagrid>
</div>
</div>

View File

@ -0,0 +1,18 @@
import { Component, OnInit } from '@angular/core';
import { Log } from './log';
@Component({
templateUrl: './log.component.html'
})
export class LogComponent implements OnInit {
logs: Log[];
ngOnInit(): void {
this.logs = [
{ username: 'Admin', repoName: 'project01', tag: '', operation: 'create', timestamp: '2016-12-23 12:05:17' },
{ username: 'Admin', repoName: 'project01/ubuntu', tag: '14.04', operation: 'push', timestamp: '2016-12-30 14:52:23' },
{ username: 'user1', repoName: 'project01/mysql', tag: '5.6', operation: 'pull', timestamp: '2016-12-30 12:12:33' }
];
}
}

View File

@ -0,0 +1,10 @@
import { NgModule } from '@angular/core';
import { LogComponent } from './log.component';
import { SharedModule } from '../shared.module';
@NgModule({
imports: [ SharedModule ],
declarations: [ LogComponent ],
exports: [ LogComponent ]
})
export class LogModule {}

View File

@ -0,0 +1,7 @@
export class Log {
username: string;
repoName: string;
tag: string;
operation: string;
timestamp: string;
}

View File

@ -0,0 +1,35 @@
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="row flex-items-xs-between">
<div class="col-xs-4">
<button class="btn btn-sm">new user</button>
</div>
<div class="col-xs-4">
<input type="text" placeholder="Search for users">
</div>
</div>
<clr-datagrid>
<clr-dg-column>Name</clr-dg-column>
<clr-dg-column>Role</clr-dg-column>
<clr-dg-column>Action</clr-dg-column>
<clr-dg-row *ngFor="let u of members">
<clr-dg-cell>{{u.name}}</clr-dg-cell>
<clr-dg-cell>{{u.role}}</clr-dg-cell>
<clr-dg-cell>
<clr-dropdown [clrMenuPosition]="'bottom-left'">
<button class="btn btn-sm btn-link" clrDropdownToggle>
Actions
<clr-icon shape="caret down"></clr-icon>
</button>
<div class="dropdown-menu">
<a href="javascript:void(0)" clrDropdownItem>Project Admin</a>
<a href="javascript:void(0)" clrDropdownItem>Developer</a>
<a href="javascript:void(0)" clrDropdownItem>Guest</a>
</div>
</clr-dropdown>
</clr-dg-cell>
</clr-dg-row>
<clr-dg-footer>{{members.length}} item(s)</clr-dg-footer>
</clr-datagrid>
</div>
</div>

View File

@ -0,0 +1,18 @@
import { Component, OnInit } from '@angular/core';
import { Member } from './member';
@Component({
templateUrl: 'member.component.html'
})
export class MemberComponent implements OnInit {
members: Member[];
ngOnInit(): void {
this.members = [
{ name: 'Admin', role: 'Sys admin'},
{ name: 'user01', role: 'Project Admin'},
{ name: 'user02', role: 'Developer'},
{ name: 'user03', role: 'Guest'}
];
}
}

View File

@ -0,0 +1,10 @@
import { NgModule } from '@angular/core';
import { MemberComponent } from './member.component';
import { SharedModule } from '../shared.module';
@NgModule({
imports: [ SharedModule ],
declarations: [ MemberComponent ],
exports: [ MemberComponent ]
})
export class MemberModule {}

View File

@ -0,0 +1,4 @@
export class Member {
name: string;
role: string;
}

View File

@ -0,0 +1,40 @@
<clr-header class="header-4 header">
<div class="branding">
<a href="#" class="nav-link">
<clr-icon shape="vm-bug"></clr-icon>
<span class="title">Harbor</span>
</a>
</div>
<div class="divider"></div>
<div class="header-nav">
<a class="nav-link" id="dashboard-link" [routerLink]="['/harbor', 'dashboard']" routerLinkActive="active">
<span class="nav-text">Dashboard</span>
</a>
<a class="nav-link" id="dashboard-link" [routerLink]="['/harbor', 'project']" routerLinkActive="active">
<span class="nav-text">Project</span>
</a>
</div>
<div class="header-actions">
<clr-dropdown class="dropdown bottom-right">
<button class="nav-text" clrDropdownToggle>
Administrator
<clr-icon shape="caret down"></clr-icon>
</button>
<div class="dropdown-menu">
<a href="javascript:void(0)" clrDropdownItem>Add User</a>
<a href="javascript:void(0)" clrDropdownItem (click)="account_settings_opened = true">Account Setting</a>
<a href="javascript:void(0)" clrDropdownItem>About</a>
</div>
</clr-dropdown>
<global-search></global-search>
<clr-dropdown class="dropdown bottom-right">
<button class="nav-text" clrDropdownToggle>
<clr-icon shape="cog"></clr-icon>
</button>
<div class="dropdown-menu">
<a href="javascript:void(0)" clrDropdownItem>Preferences</a>
<a href="javascript:void(0)" clrDropdownItem>Log out</a>
</div>
</clr-dropdown>
</div>
</clr-header>

View File

@ -0,0 +1,10 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'navigator',
templateUrl: "navigator.component.html"
})
export class NavigatorComponent {
// constructor(private router: Router){}
}

View File

@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { NavigatorComponent } from './navigator.component';
import { SharedModule } from '../shared.module';
import { GlobalSearchComponent } from '../global-search/global-search.component';
import { GlobalSearchModule } from '../global-search/global-search.module';
import { RouterModule } from '@angular/router';
@NgModule({
imports: [
SharedModule,
GlobalSearchModule,
RouterModule
],
declarations: [ NavigatorComponent ],
exports: [ NavigatorComponent ]
})
export class NavigatorModule {}

View File

@ -0,0 +1,30 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ProjectDetailComponent } from './project-detail.component';
import { RepositoryComponent } from '../repository/repository.component';
import { ReplicationComponent } from '../replication/replication.component';
import { MemberComponent } from '../member/member.component';
import { LogComponent } from '../log/log.component';
const projectDetailRoutes: Routes = [
{
path: 'projects/:id',
component: ProjectDetailComponent,
children: [
{ path: 'repository', component: RepositoryComponent },
{ path: 'replication', component: ReplicationComponent },
{ path: 'member', component: MemberComponent },
{ path: 'log', component: LogComponent }
]
}
];
@NgModule({
imports: [
RouterModule.forChild(projectDetailRoutes)
],
exports: [ RouterModule ]
})
export class ProjectDetailRoutingModule {}

View File

@ -0,0 +1,19 @@
<navigator></navigator>
<h1 class="display-in-line">Project 01</h1><h6 class="display-in-line project-title">PROJECT</h6>
<nav class="subnav">
<ul class="nav">
<li class="nav-item">
<a class="nav-link" routerLink="repository" routerLinkActive="active">Repositories</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="replication" routerLinkActive="active">Replication</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="member" routerLinkActive="active">Users</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="log" routerLinkActive="active">Logs</a>
</li>
</ul>
</nav>
<router-outlet></router-outlet>

View File

@ -0,0 +1,11 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'project-detail',
templateUrl: "project-detail.component.html",
styleUrls: [ 'project-detail.css' ]
})
export class ProjectDetailComponent {
// constructor(private router: Router){}
}

View File

@ -0,0 +1,11 @@
.display-in-line {
display: inline-block;
}
.project-title {
margin-left: 10px;
}
.pull-right {
float: right !important;
}

View File

@ -0,0 +1,34 @@
import { NgModule } from '@angular/core';
import { NavigatorModule } from '../navigator/navigator.module';
import { GlobalSearchModule } from '../global-search/global-search.module';
import { FooterModule } from '../footer/footer.module';
import { RepositoryModule } from '../repository/repository.module';
import { ReplicationModule } from '../replication/replication.module';
import { MemberModule } from '../member/member.module';
import { LogModule } from '../log/log.module';
import { ProjectDetailComponent } from './project-detail.component';
import { SharedModule } from '../shared.module';
import { ProjectDetailRoutingModule } from './project-detail-routing.module';
@NgModule({
imports: [
SharedModule,
GlobalSearchModule,
NavigatorModule,
FooterModule,
RepositoryModule,
ReplicationModule,
MemberModule,
LogModule,
ProjectDetailRoutingModule
],
declarations: [ ProjectDetailComponent ],
exports: [ ProjectDetailComponent ]
})
export class ProjectDetailModule {}

View File

@ -0,0 +1,19 @@
<clr-datagrid>
<clr-dg-column>Name</clr-dg-column>
<clr-dg-column>Public/Private</clr-dg-column>
<clr-dg-column>Repositories</clr-dg-column>
<clr-dg-column>Creation time</clr-dg-column>
<clr-dg-column>Destination</clr-dg-column>
<clr-dg-column>Owner</clr-dg-column>
<clr-dg-column>Description</clr-dg-column>
<clr-dg-row *ngFor="let p of projects">
<clr-dg-cell><a [routerLink]="['/projects', p.id, 'repository']" >{{p.name}}</a></clr-dg-cell>
<clr-dg-cell>{{p.isPublic ? 'Public': 'Private'}}</clr-dg-cell>
<clr-dg-cell>{{p.repoCount}}</clr-dg-cell>
<clr-dg-cell>{{p.creationTime}}</clr-dg-cell>
<clr-dg-cell>{{p.destination}}</clr-dg-cell>
<clr-dg-cell>{{p.owner}}</clr-dg-cell>
<clr-dg-cell>{{p.description}}</clr-dg-cell>
</clr-dg-row>
<clr-dg-footer>{{projects.length}} item(s)</clr-dg-footer>
</clr-datagrid>

View File

@ -0,0 +1,46 @@
import { Component, OnInit } from '@angular/core';
import { Project } from './project';
@Component({
selector: 'project-list',
templateUrl: 'project-list.component.html'
})
export class ProjectListComponent implements OnInit {
projects: Project[];
ngOnInit(): void {
this.projects = [
{
id: 1,
name: 'Project01',
isPublic: true,
repoCount: 0,
creationTime: '2016-12-29 14:58 PM',
destination: '10.117.4.61',
owner: 'Administrator',
description: 'New updated by Alice.'
},
{
id: 2,
name: 'Project02',
isPublic: false,
repoCount: 2,
creationTime: '2016-12-29 15:28 PM',
destination: '10.117.4.61',
owner: 'Administrator',
description: '--'
},
{
id: 3,
name: 'Project03',
isPublic: true,
repoCount: 5,
creationTime: '2016-12-21 10:25 AM',
destination: '10.117.4.61',
owner: 'Administrator',
description: 'Deprecated'
},
];
}
}

View File

@ -0,0 +1,46 @@
<h3>Projects</h3>
<clr-modal [(clrModalOpen)]="create_project_opened">
<h3 class="modal-title">New Project</h3>
<div class="modal-body">
<form>
<section class="form-block">
<div class="form-group">
<label for="create_project_username" class="col-md-4">Project Name</label>
<input type="text" class="col-md-8" id="create_project_username" size="20">
</div>
<div class="form-group">
<label class="col-md-4">Public</label>
<div class="checkbox-inline">
<input type="checkbox" id="create_project_public">
<label for="create_project_public"></label>
</div>
</div>
</section>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline" (click)="create_project_opened = false">Cancel</button>
<button type="button" class="btn btn-primary" (click)="create_project_opened = false">Ok</button>
</div>
</clr-modal>
<div class="row flex-items-xs-between">
<div class="col-xs-4">
<button class="btn btn-sm" (click)="create_project_opened = true">New Project</button>
</div>
<div class="col-xs-4">
<clr-dropdown [clrMenuPosition]="'bottom-left'">
<button class="btn btn-sm btn-outline-primary" clrDropdownToggle>
My Projects
<clr-icon shape="caret down"></clr-icon>
</button>
<div class="dropdown-menu">
<a href="javascript:void(0)" clrDropdownItem>My Projects</a>
<a href="javascript:void(0)" clrDropdownItem>Public Projects</a>
</div>
</clr-dropdown>
<input type="text" placeholder="Search for projects">
</div>
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<project-list></project-list>
</div>
</div>

View File

@ -0,0 +1,17 @@
import { Component, OnInit } from '@angular/core';
import { Project } from './project';
import { Router } from '@angular/router';
@Component({
selector: 'project',
templateUrl: 'project.component.html',
styleUrls: [ 'project.css' ]
})
export class ProjectComponent implements OnInit {
ngOnInit(): void {
}
}

View File

@ -0,0 +1,3 @@
.my-project-pull-right {
float: right;
}

View File

@ -0,0 +1,18 @@
import { NgModule } from '@angular/core';
import { ProjectComponent } from './project.component';
import { ProjectListComponent } from './project-list.component';
import { SharedModule } from '../shared.module';
import { RouterModule } from '@angular/router';
@NgModule({
imports: [
SharedModule,
RouterModule
],
declarations: [
ProjectComponent,
ProjectListComponent
],
exports: [ ProjectComponent ]
})
export class ProjectModule {}

View File

@ -0,0 +1,10 @@
export class Project {
id: number;
name: string;
isPublic: boolean;
repoCount: number;
creationTime: string;
destination: string;
owner: string;
description: string;
}

View File

@ -0,0 +1,7 @@
export class Job {
name: string;
status: string;
operation: string;
creationTime: string;
endTime: string;
}

View File

@ -0,0 +1,7 @@
export class Policy {
name: string;
status: string;
destination: string;
lastStartTime: string;
description: string;
}

View File

@ -0,0 +1,132 @@
<clr-modal [(clrModalOpen)]="create_policy_opened">
<h3 class="modal-title">Add Policy</h3>
<div class="modal-body">
<form>
<section class="form-block">
<div class="form-group">
<label for="policy_name" class="col-md-4">Name</label>
<input type="text" class="col-md-8" id="policy_name" size="20">
</div>
<div class="form-group">
<label for="policy_description" class="col-md-4">Description</label>
<input type="text" class="col-md-8" id="policy_description" size="20">
</div>
<div class="form-group">
<label class="col-md-4">Enable</label>
<div class="checkbox-inline">
<input type="checkbox" id="policy_enable">
<label for="policy_enable"></label>
</div>
</div>
<div class="form-group">
<label for="destination_name" class="col-md-4">Destination name</label>
<div class="select">
<select id="destination_name">
<option>10.117.5.114</option>
<option>10.117.5.61</option>
</select>
</div>
<div class="checkbox-inline">
<input type="checkbox" id="check_new">
<label for="check_new">New destination</label>
</div>
</div>
<div class="form-group">
<label for="destination_url" class="col-md-4">Destination URL</label>
<input type="text" class="col-md-8" id="destination_url" size="20">
</div>
<div class="form-group">
<label for="destination_username" class="col-md-4">Username</label>
<input type="text" class="col-md-8" id="destination_username" size="20">
</div>
<div class="form-group">
<label for="destination_password" class="col-md-4">Password</label>
<input type="text" class="col-md-8" id="destination_password" size="20">
</div>
</section>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline">Test Connection</button>
<button type="button" class="btn btn-outline" (click)="create_policy_opened = false">Cancel</button>
<button type="button" class="btn btn-primary" (click)="create_policy_opened = false">Ok</button>
</div>
</clr-modal>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="row flex-items-xs-between">
<div class="col-xs-4">
<button class="btn btn-sm" (click)="create_policy_opened = true">New Policy</button>
</div>
<div class="col-xs-4">
<input type="text" placeholder="Search for policies">
</div>
</div>
<clr-datagrid>
<clr-dg-column>Name</clr-dg-column>
<clr-dg-column>Status</clr-dg-column>
<clr-dg-column>Destination</clr-dg-column>
<clr-dg-column>Last start time</clr-dg-column>
<clr-dg-column>Description</clr-dg-column>
<clr-dg-column>Action</clr-dg-column>
<clr-dg-row *ngFor="let p of policies">
<clr-dg-cell>{{p.name}}</clr-dg-cell>
<clr-dg-cell>{{p.status}}</clr-dg-cell>
<clr-dg-cell>{{p.destination}}</clr-dg-cell>
<clr-dg-cell>{{p.lastStartTime}}</clr-dg-cell>
<clr-dg-cell>{{p.description}}</clr-dg-cell>
<clr-dg-cell>
<clr-dropdown [clrMenuPosition]="'bottom-left'">
<button class="btn btn-sm btn-link" clrDropdownToggle>
Actions
<clr-icon shape="caret down"></clr-icon>
</button>
<div class="dropdown-menu">
<a href="javascript:void(0)" clrDropdownItem>Enable</a>
<a href="javascript:void(0)" clrDropdownItem>Disable</a>
</div>
</clr-dropdown>
</clr-dg-cell>
</clr-dg-row>
<clr-dg-footer>{{policies.length}} item(s)</clr-dg-footer>
</clr-datagrid>
<div class="row flex-items-xs-between flex-items-xs-bottom">
<div class="col-xs-4">
<span>Replication Jobs for 'project01/sync_01'</span>
</div>
<div class="col-xs-4">
<clr-dropdown [clrMenuPosition]="'bottom-left'">
<button class="btn btn-sm btn-outline-primary" clrDropdownToggle>
All
<clr-icon shape="caret down"></clr-icon>
</button>
<div class="dropdown-menu">
<a href="javascript:void(0)" clrDropdownItem>Finished</a>
<a href="javascript:void(0)" clrDropdownItem>Running</a>
<a href="javascript:void(0)" clrDropdownItem>Error</a>
<a href="javascript:void(0)" clrDropdownItem>Stopped</a>
<a href="javascript:void(0)" clrDropdownItem>Retrying</a>
</div>
</clr-dropdown>
<input type="text" placeholder="Search for jobs">
</div>
</div>
<clr-datagrid>
<clr-dg-column>Name</clr-dg-column>
<clr-dg-column>Status</clr-dg-column>
<clr-dg-column>Operation</clr-dg-column>
<clr-dg-column>Creation time</clr-dg-column>
<clr-dg-column>End time</clr-dg-column>
<clr-dg-column>Logs</clr-dg-column>
<clr-dg-row *ngFor="let j of jobs">
<clr-dg-cell>{{j.name}}</clr-dg-cell>
<clr-dg-cell>{{j.status}}</clr-dg-cell>
<clr-dg-cell>{{j.operation}}</clr-dg-cell>
<clr-dg-cell>{{j.creationTime}}</clr-dg-cell>
<clr-dg-cell>{{j.endTime}}</clr-dg-cell>
<clr-dg-cell></clr-dg-cell>
</clr-dg-row>
<clr-dg-footer>{{jobs.length}} item(s)</clr-dg-footer>
</clr-datagrid>
</div>
</div>

View File

@ -0,0 +1,24 @@
import { Component, OnInit } from '@angular/core';
import { Policy } from './policy';
import { Job } from './job';
@Component({
selector: 'replicaton',
templateUrl: 'replication.component.html'
})
export class ReplicationComponent implements OnInit {
policies: Policy[];
jobs: Job[];
ngOnInit(): void {
this.policies = [
{ name: 'sync_01', status: 'Disabled', destination: '10.117.5.135', lastStartTime: '2016-12-21 17:52:35', description: 'test'},
{ name: 'sync_02', status: 'Enabled', destination: '10.117.5.117', lastStartTime: '2016-12-21 12:22:47', description: 'test'},
];
this.jobs = [
{ name: 'project01/ubuntu:14.04', status: 'Finished', operation: 'Transfer', creationTime: '2016-12-21 17:53:50', endTime: '2016-12-21 17:55:01'},
{ name: 'project01/mysql:5.6', status: 'Finished', operation: 'Transfer', creationTime: '2016-12-21 17:54:20', endTime: '2016-12-21 17:55:05'},
{ name: 'project01/photon:latest', status: 'Finished', operation: 'Transfer', creationTime: '2016-12-21 17:54:50', endTime: '2016-12-21 17:55:15'}
];
}
}

View File

@ -0,0 +1,10 @@
import { NgModule } from '@angular/core';
import { ReplicationComponent } from './replication.component';
import { SharedModule } from '../shared.module';
@NgModule({
imports: [ SharedModule ],
declarations: [ ReplicationComponent ],
exports: [ ReplicationComponent ]
})
export class ReplicationModule {}

View File

@ -0,0 +1,9 @@
export class Repo {
name: string;
status: string;
tag: string;
author: string;
dockerVersion: string;
created: string;
pullCommand: string;
}

View File

@ -0,0 +1,38 @@
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="row flex-items-lg-right">
<div class="col-lg-3 col-md-3 col-sm-12 col-xs-12">
<clr-dropdown [clrMenuPosition]="'bottom-left'">
<button class="btn btn-sm btn-outline-primary" clrDropdownToggle>
My Projects
<clr-icon shape="caret down"></clr-icon>
</button>
<div class="dropdown-menu">
<a href="#/project" clrDropdownItem>My Projects</a>
<a href="#/project" clrDropdownItem>Public Projects</a>
</div>
</clr-dropdown>
<input type="text" placeholder="Search for projects">
</div>
</div>
<clr-datagrid>
<clr-dg-column>Name</clr-dg-column>
<clr-dg-column>Status</clr-dg-column>
<clr-dg-column>Tag</clr-dg-column>
<clr-dg-column>Author</clr-dg-column>
<clr-dg-column>Docker version</clr-dg-column>
<clr-dg-column>Created</clr-dg-column>
<clr-dg-column>Pull Command</clr-dg-column>
<clr-dg-row *ngFor="let r of repos">
<clr-dg-cell>{{r.name}}</clr-dg-cell>
<clr-dg-cell>{{r.status}}</clr-dg-cell>
<clr-dg-cell>{{r.tag}}</clr-dg-cell>
<clr-dg-cell>{{r.author}}</clr-dg-cell>
<clr-dg-cell>{{r.dockerVersion}}</clr-dg-cell>
<clr-dg-cell>{{r.created}}</clr-dg-cell>
<clr-dg-cell>{{r.pullCommand}}</clr-dg-cell>
</clr-dg-row>
<clr-dg-footer>{{repos.length}} item(s)</clr-dg-footer>
</clr-datagrid>
</div>
</div>

View File

@ -0,0 +1,18 @@
import { Component, OnInit } from '@angular/core';
import { Repo } from './repo';
@Component({
selector: 'repository',
templateUrl: 'repository.component.html'
})
export class RepositoryComponent implements OnInit {
repos: Repo[];
ngOnInit(): void {
this.repos = [
{ name: 'ubuntu', status: 'ready', tag: '14.04', author: 'Admin', dockerVersion: '1.10.1', created: '2016-10-10', pullCommand: 'docker pull 10.117.5.61/project01/ubuntu:14.04' },
{ name: 'mysql', status: 'ready', tag: '5.6', author: 'docker', dockerVersion: '1.11.2', created: '2016-09-23', pullCommand: 'docker pull 10.117.5.61/project01/mysql:5.6' },
{ name: 'photon', status: 'ready', tag: 'latest', author: 'Admin', dockerVersion: '1.10.1', created: '2016-11-10', pullCommand: 'docker pull 10.117.5.61/project01/photon:latest' },
];
}
}

View File

@ -0,0 +1,10 @@
import { NgModule } from '@angular/core';
import { RepositoryComponent } from './repository.component';
import { SharedModule } from '../shared.module';
@NgModule({
imports: [ SharedModule ],
declarations: [ RepositoryComponent ],
exports: [ RepositoryComponent ]
})
export class RepositoryModule {}

View File

@ -0,0 +1,5 @@
export class Repository {
name:string;
version:string;
count:number;
}

View File

@ -0,0 +1,8 @@
import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
export class AuthGuard implements CanActivate {
canActivate() {
return true;
}
}

View File

@ -0,0 +1,14 @@
import { NgModule } from '@angular/core';
import { CoreModule } from './core.module';
@NgModule({
imports: [
CoreModule
],
exports: [
CoreModule
]
})
export class SharedModule {
}

View File

@ -0,0 +1,3 @@
export const environment = {
production: true
};

View File

@ -0,0 +1,8 @@
// The file contents for the current environment will overwrite these during build.
// The build system defaults to the dev environment which uses `environment.ts`, but if you do
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
// The list of which env maps to which file can be found in `angular-cli.json`.
export const environment = {
production: false
};

BIN
harbor-app/src/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
~ Copyright (c) 2016 VMware, Inc. All Rights Reserved.
~ This software is released under MIT license.
~ The full license information can be found in LICENSE in the root directory of this project.
-->
<svg width="36px" height="36px" viewBox="0 0 36 36" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 40.3 (33839) - http://www.bohemiancoding.com/sketch -->
<title>logo</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="logo" transform="translate(0.000000, 4.500000)">
<g id="large" transform="translate(0.000000, 0.044118)">
<polyline id="Fill-3" fill="#0095D3" points="24.7018129 0.0388840336 35.979641 6.71768066 35.9614589 20.2811697 24.7018129 26.9417748 18.0173463 22.9707846 29.6688177 16.4295126 29.6688177 10.5321277 24.9216504 7.92742184 18.0321077 3.99030785"></polyline>
<polyline id="Fill-4" fill="#F38B00" points="11.3313965 0.0388840336 0.0535685039 6.71768066 0.0717505512 20.2811697 11.3313965 26.9417748 18.0166889 22.970061 7.35448694 16.4295126 7.35448694 10.5321277 18.0324642 3.98991663"></polyline>
<polyline id="Fill-5" fill="#004B70" points="18.017374 22.9708988 11.4990488 18.9719838 18.0212495 15.1272387 24.9510827 19.0786297"></polyline>
<polyline id="Fill-6" fill="#98441E" points="18.0314053 3.98921729 11.5267517 7.97364692 18.0439938 11.8578324 24.9058951 7.91831944"></polyline>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

13
harbor-app/src/index.html Normal file
View File

@ -0,0 +1,13 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Clarity Seed App</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico?v=2">
</head>
<body>
<harbor-app>Loading...</harbor-app>
</body>
</html>

12
harbor-app/src/main.ts Normal file
View File

@ -0,0 +1,12 @@
import './polyfills.ts';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { environment } from './environments/environment';
import { AppModule } from './app/';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule);

View File

@ -0,0 +1,22 @@
// This file includes polyfills needed by Angular 2 and is loaded before
// the app. You can add your own extra polyfills to this file.
import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/set';
import 'core-js/es6/reflect';
import 'core-js/es7/reflect';
import 'zone.js/dist/zone';

View File

@ -0,0 +1 @@
/* You can add global styles to this file, and also import other style files */

32
harbor-app/src/test.ts Normal file
View File

@ -0,0 +1,32 @@
import './polyfills.ts';
import 'zone.js/dist/long-stack-trace-zone';
import 'zone.js/dist/proxy.js';
import 'zone.js/dist/sync-test';
import 'zone.js/dist/jasmine-patch';
import 'zone.js/dist/async-test';
import 'zone.js/dist/fake-async-test';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any.
declare var __karma__: any;
declare var require: any;
// Prevent Karma from running prematurely.
__karma__.loaded = function () {};
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Then we find all the tests.
let context = require.context('./', true, /\.spec\.ts/);
// And load the modules.
context.keys().map(context);
// Finally, start Karma to run the tests.
__karma__.start();

View File

@ -0,0 +1,25 @@
{
"compilerOptions": {
"baseUrl": "",
"declaration": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": [
"es6",
"dom"
],
"mapRoot": "./",
"module": "commonjs",
"moduleResolution": "node",
"outDir": "../dist/out-tsc",
"sourceMap": true,
"target": "es5",
"typeRoots": [
"../node_modules/@types"
]
},
"exclude": [
"node_modules",
"dist"
]
}

2
harbor-app/src/typings.d.ts vendored Normal file
View File

@ -0,0 +1,2 @@
// Typings reference file, you can add your own global typings here
// https://www.typescriptlang.org/docs/handbook/writing-declaration-files.html

114
harbor-app/tslint.json Normal file
View File

@ -0,0 +1,114 @@
{
"rulesDirectory": [
"node_modules/codelyzer"
],
"rules": {
"class-name": true,
"comment-format": [
true,
"check-space"
],
"curly": true,
"eofline": true,
"forin": true,
"indent": [
true,
"spaces"
],
"label-position": true,
"label-undefined": true,
"max-line-length": [
true,
140
],
"member-access": false,
"member-ordering": [
true,
"static-before-instance",
"variables-before-functions"
],
"no-arg": true,
"no-bitwise": true,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-construct": true,
"no-debugger": true,
"no-duplicate-key": true,
"no-duplicate-variable": true,
"no-empty": false,
"no-eval": true,
"no-inferrable-types": true,
"no-shadowed-variable": true,
"no-string-literal": false,
"no-switch-case-fall-through": true,
"no-trailing-whitespace": true,
"no-unused-expression": true,
"no-unused-variable": true,
"no-unreachable": true,
"no-use-before-declare": true,
"no-var-keyword": true,
"object-literal-sort-keys": false,
"one-line": [
true,
"check-open-brace",
"check-catch",
"check-else",
"check-whitespace"
],
"quotemark": [
true,
"single"
],
"radix": true,
"semicolon": [
"always"
],
"triple-equals": [
true,
"allow-null-check"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"variable-name": false,
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
],
"directive-selector-prefix": [true, "app"],
"component-selector-prefix": [true, "app"],
"directive-selector-name": [true, "camelCase"],
"component-selector-name": [true, "kebab-case"],
"directive-selector-type": [true, "attribute"],
"component-selector-type": [true, "element"],
"use-input-property-decorator": true,
"use-output-property-decorator": true,
"use-host-property-decorator": true,
"no-input-rename": true,
"no-output-rename": true,
"use-life-cycle-interface": true,
"use-pipe-transform-interface": true,
"component-class-suffix": true,
"directive-class-suffix": true,
"templates-use-public": true,
"invoke-injectable": true
}
}

5
harbor-app/typings.json Normal file
View File

@ -0,0 +1,5 @@
{
"globalDependencies": {
"es6-shim": "registry:dt/es6-shim#0.31.2+20160602141504"
}
}

Some files were not shown because too many files have changed in this diff Show More