mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-23 00:57:44 +01:00
Harbor Clarity UI integration.
This commit is contained in:
parent
09dc6909ae
commit
3c112f2a2c
11
.gitignore
vendored
11
.gitignore
vendored
@ -9,3 +9,14 @@ src/jobservice/jobservice
|
||||
src/common/dao/dao.test
|
||||
*.pyc
|
||||
jobservice/test
|
||||
|
||||
make/dev/nodeclarity/coverage/
|
||||
make/dev/nodeclarity/dist/
|
||||
make/dev/nodeclarity/html-report/
|
||||
make/dev/nodeclarity/node_modules/
|
||||
make/dev/nodeclarity/typings/
|
||||
**/*npm-debug.log.*
|
||||
**/*yarn-error.log.*
|
||||
.idea/
|
||||
.DS_Store
|
||||
|
||||
|
@ -111,3 +111,12 @@ services:
|
||||
options:
|
||||
syslog-address: "tcp://127.0.0.1:1514"
|
||||
tag: "proxy"
|
||||
nodeclarity:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: make/dev/nodeclarity/Dockerfile
|
||||
volumes:
|
||||
- ../../src/ui/static/dist:/clarity-seed/dist
|
||||
- ../../src/ui/static/app:/clarity-seed/src/app
|
||||
depends_on:
|
||||
- ui
|
||||
|
14
make/dev/nodeclarity/Dockerfile
Normal file
14
make/dev/nodeclarity/Dockerfile
Normal file
@ -0,0 +1,14 @@
|
||||
FROM reg-bj.eng.vmware.com/sharedrepo/harbor-clarity-base:0.8.0
|
||||
|
||||
|
||||
COPY make/dev/nodeclarity/clarity-seed /clarity-seed
|
||||
COPY make/dev/nodeclarity/index.html /clarity-seed
|
||||
COPY make/dev/nodeclarity/entrypoint.sh /clarity-seed
|
||||
|
||||
WORKDIR /clarity-seed
|
||||
|
||||
RUN chmod u+x entrypoint.sh
|
||||
|
||||
VOLUME ["/clarity-seed/src/app", "/clarity-seed/dist"]
|
||||
|
||||
ENTRYPOINT ["/clarity-seed/entrypoint.sh"]
|
20
make/dev/nodeclarity/clarity-seed/.editorconfig
Normal file
20
make/dev/nodeclarity/clarity-seed/.editorconfig
Normal 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
make/dev/nodeclarity/clarity-seed/.gitignore
vendored
Normal file
9
make/dev/nodeclarity/clarity-seed/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
coverage/
|
||||
dist/
|
||||
html-report/
|
||||
node_modules/
|
||||
typings/
|
||||
**/*npm-debug.log.*
|
||||
**/*yarn-error.log.*
|
||||
.idea/
|
||||
.DS_Store
|
10
make/dev/nodeclarity/clarity-seed/.travis.yml
Normal file
10
make/dev/nodeclarity/clarity-seed/.travis.yml
Normal file
@ -0,0 +1,10 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "6.9"
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.8
|
19
make/dev/nodeclarity/clarity-seed/CODE_OF_CONDUCT.md
Normal file
19
make/dev/nodeclarity/clarity-seed/CODE_OF_CONDUCT.md
Normal 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
make/dev/nodeclarity/clarity-seed/CONTRIBUTING.md
Normal file
113
make/dev/nodeclarity/clarity-seed/CONTRIBUTING.md
Normal 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
|
@ -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.
|
||||
|
||||
|
@ -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
make/dev/nodeclarity/clarity-seed/README.md
Normal file
121
make/dev/nodeclarity/clarity-seed/README.md
Normal 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).
|
67
make/dev/nodeclarity/clarity-seed/angular-cli-2.json
Normal file
67
make/dev/nodeclarity/clarity-seed/angular-cli-2.json
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
67
make/dev/nodeclarity/clarity-seed/angular-cli.json
Normal file
67
make/dev/nodeclarity/clarity-seed/angular-cli.json
Normal 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"
|
||||
],
|
||||
"environmentSource": "environments/environment.ts",
|
||||
"environments": {
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
17
make/dev/nodeclarity/clarity-seed/e2e/app.e2e-spec.ts
Normal file
17
make/dev/nodeclarity/clarity-seed/e2e/app.e2e-spec.ts
Normal 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
make/dev/nodeclarity/clarity-seed/e2e/app.po.ts
Normal file
13
make/dev/nodeclarity/clarity-seed/e2e/app.po.ts
Normal 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();
|
||||
}
|
||||
}
|
25
make/dev/nodeclarity/clarity-seed/e2e/tsconfig.json
Normal file
25
make/dev/nodeclarity/clarity-seed/e2e/tsconfig.json
Normal 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
make/dev/nodeclarity/clarity-seed/karma.conf.js
Normal file
44
make/dev/nodeclarity/clarity-seed/karma.conf.js
Normal 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
make/dev/nodeclarity/clarity-seed/logo.png
Normal file
BIN
make/dev/nodeclarity/clarity-seed/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
45
make/dev/nodeclarity/clarity-seed/npm-debug.log
Normal file
45
make/dev/nodeclarity/clarity-seed/npm-debug.log
Normal file
@ -0,0 +1,45 @@
|
||||
0 info it worked if it ends with ok
|
||||
1 verbose cli [ '/usr/local/bin/node', '/usr/local/bin/npm', 'start' ]
|
||||
2 info using npm@4.1.2
|
||||
3 info using node@v7.5.0
|
||||
4 verbose run-script [ 'prestart', 'start', 'poststart' ]
|
||||
5 info lifecycle clarity-seed@0.8.0~prestart: clarity-seed@0.8.0
|
||||
6 silly lifecycle clarity-seed@0.8.0~prestart: no script for prestart, continuing
|
||||
7 info lifecycle clarity-seed@0.8.0~start: clarity-seed@0.8.0
|
||||
8 verbose lifecycle clarity-seed@0.8.0~start: unsafe-perm in lifecycle true
|
||||
9 verbose lifecycle clarity-seed@0.8.0~start: PATH: /usr/local/lib/node_modules/npm/bin/node-gyp-bin:/usr/src/clarity-seed/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
10 verbose lifecycle clarity-seed@0.8.0~start: CWD: /usr/src/clarity-seed
|
||||
11 silly lifecycle clarity-seed@0.8.0~start: Args: [ '-c', 'ng serve' ]
|
||||
12 silly lifecycle clarity-seed@0.8.0~start: Returned: code: 1 signal: null
|
||||
13 info lifecycle clarity-seed@0.8.0~start: Failed to exec start script
|
||||
14 verbose stack Error: clarity-seed@0.8.0 start: `ng serve`
|
||||
14 verbose stack Exit status 1
|
||||
14 verbose stack at EventEmitter.<anonymous> (/usr/local/lib/node_modules/npm/lib/utils/lifecycle.js:279:16)
|
||||
14 verbose stack at emitTwo (events.js:106:13)
|
||||
14 verbose stack at EventEmitter.emit (events.js:192:7)
|
||||
14 verbose stack at ChildProcess.<anonymous> (/usr/local/lib/node_modules/npm/lib/utils/spawn.js:40:14)
|
||||
14 verbose stack at emitTwo (events.js:106:13)
|
||||
14 verbose stack at ChildProcess.emit (events.js:192:7)
|
||||
14 verbose stack at maybeClose (internal/child_process.js:890:16)
|
||||
14 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:226:5)
|
||||
15 verbose pkgid clarity-seed@0.8.0
|
||||
16 verbose cwd /usr/src/clarity-seed
|
||||
17 error Linux 4.4.0-62-generic
|
||||
18 error argv "/usr/local/bin/node" "/usr/local/bin/npm" "start"
|
||||
19 error node v7.5.0
|
||||
20 error npm v4.1.2
|
||||
21 error code ELIFECYCLE
|
||||
22 error clarity-seed@0.8.0 start: `ng serve`
|
||||
22 error Exit status 1
|
||||
23 error Failed at the clarity-seed@0.8.0 start script 'ng serve'.
|
||||
23 error Make sure you have the latest version of node.js and npm installed.
|
||||
23 error If you do, this is most likely a problem with the clarity-seed package,
|
||||
23 error not with npm itself.
|
||||
23 error Tell the author that this fails on your system:
|
||||
23 error ng serve
|
||||
23 error You can get information on how to open an issue for this project with:
|
||||
23 error npm bugs clarity-seed
|
||||
23 error Or if that isn't available, you can get their info via:
|
||||
23 error npm owner ls clarity-seed
|
||||
23 error There is likely additional logging output above.
|
||||
24 verbose exit [ 1, true ]
|
58
make/dev/nodeclarity/clarity-seed/package.json
Normal file
58
make/dev/nodeclarity/clarity-seed/package.json
Normal 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",
|
||||
"lint": "tslint \"src/**/*.ts\"",
|
||||
"test": "ng test --single-run",
|
||||
"pree2e": "webdriver-manager update",
|
||||
"e2e": "protractor"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/cli": "^1.0.0-beta.30",
|
||||
"@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",
|
||||
"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"
|
||||
}
|
||||
}
|
32
make/dev/nodeclarity/clarity-seed/protractor.config.js
Normal file
32
make/dev/nodeclarity/clarity-seed/protractor.config.js
Normal 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());
|
||||
}
|
||||
};
|
1
make/dev/nodeclarity/clarity-seed/src/app
Symbolic link
1
make/dev/nodeclarity/clarity-seed/src/app
Symbolic link
@ -0,0 +1 @@
|
||||
../../app/
|
@ -0,0 +1,3 @@
|
||||
export const environment = {
|
||||
production: true
|
||||
};
|
@ -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
make/dev/nodeclarity/clarity-seed/src/favicon.ico
Normal file
BIN
make/dev/nodeclarity/clarity-seed/src/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
@ -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
make/dev/nodeclarity/clarity-seed/src/index.html
Normal file
13
make/dev/nodeclarity/clarity-seed/src/index.html
Normal 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>
|
||||
<my-app>Loading...</my-app>
|
||||
</body>
|
||||
</html>
|
12
make/dev/nodeclarity/clarity-seed/src/main.ts
Normal file
12
make/dev/nodeclarity/clarity-seed/src/main.ts
Normal 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);
|
22
make/dev/nodeclarity/clarity-seed/src/polyfills.ts
Normal file
22
make/dev/nodeclarity/clarity-seed/src/polyfills.ts
Normal 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';
|
||||
|
1
make/dev/nodeclarity/clarity-seed/src/styles.css
Normal file
1
make/dev/nodeclarity/clarity-seed/src/styles.css
Normal file
@ -0,0 +1 @@
|
||||
/* You can add global styles to this file, and also import other style files */
|
32
make/dev/nodeclarity/clarity-seed/src/test.ts
Normal file
32
make/dev/nodeclarity/clarity-seed/src/test.ts
Normal 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();
|
33
make/dev/nodeclarity/clarity-seed/src/tsconfig.json
Normal file
33
make/dev/nodeclarity/clarity-seed/src/tsconfig.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"rootDir": "../",
|
||||
"baseUrl": "",
|
||||
"declaration": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"lib": [
|
||||
"es6",
|
||||
"dom"
|
||||
],
|
||||
"mapRoot": "src",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"outDir": "dist/out-tsc",
|
||||
"sourceMap": true,
|
||||
"target": "es5",
|
||||
"typeRoots": [
|
||||
"node_modules/@types"
|
||||
],
|
||||
"types": [
|
||||
"jasmine",
|
||||
"core-js",
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"test.ts"
|
||||
]
|
||||
}
|
2
make/dev/nodeclarity/clarity-seed/src/typings.d.ts
vendored
Normal file
2
make/dev/nodeclarity/clarity-seed/src/typings.d.ts
vendored
Normal 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
make/dev/nodeclarity/clarity-seed/tslint.json
Normal file
114
make/dev/nodeclarity/clarity-seed/tslint.json
Normal 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
make/dev/nodeclarity/clarity-seed/typings.json
Normal file
5
make/dev/nodeclarity/clarity-seed/typings.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"globalDependencies": {
|
||||
"es6-shim": "registry:dt/es6-shim#0.31.2+20160602141504"
|
||||
}
|
||||
}
|
5688
make/dev/nodeclarity/clarity-seed/yarn.lock
Normal file
5688
make/dev/nodeclarity/clarity-seed/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
4
make/dev/nodeclarity/entrypoint.sh
Normal file
4
make/dev/nodeclarity/entrypoint.sh
Normal file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
ng build
|
||||
cp index.html dist/index.html
|
||||
|
13
make/dev/nodeclarity/index.html
Normal file
13
make/dev/nodeclarity/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Clarity Seed App</title>
|
||||
<base href="/ng">
|
||||
<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>
|
||||
<script type="text/javascript" src="/ng/inline.bundle.js"></script><script type="text/javascript" src="/ng/scripts.bundle.js"></script><script type="text/javascript" src="/ng/styles.bundle.js"></script><script type="text/javascript" src="/ng/vendor.bundle.js"></script><script type="text/javascript" src="/ng/main.bundle.js"></script></body>
|
||||
</html>
|
@ -28,6 +28,9 @@ func initRouters() {
|
||||
|
||||
beego.SetStaticPath("static/resources", "static/resources")
|
||||
beego.SetStaticPath("static/vendors", "static/vendors")
|
||||
beego.SetStaticPath("/ng", "static/dist")
|
||||
beego.SetStaticPath("/ng/harbor/dashboard", "static/dist")
|
||||
beego.SetStaticPath("/ng/harbor/projects", "static/dist")
|
||||
|
||||
//Page Controllers:
|
||||
beego.Router("/", &controllers.IndexController{})
|
||||
|
15
src/ui/static/app/account/account.module.ts
Normal file
15
src/ui/static/app/account/account.module.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { SignInComponent } from './sign-in/sign-in.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
SharedModule,
|
||||
RouterModule
|
||||
],
|
||||
declarations: [SignInComponent],
|
||||
exports: [SignInComponent]
|
||||
})
|
||||
export class AccountModule { }
|
10
src/ui/static/app/account/forgot-password.component.ts
Normal file
10
src/ui/static/app/account/forgot-password.component.ts
Normal 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){}
|
||||
}
|
10
src/ui/static/app/account/reset-password.component.ts
Normal file
10
src/ui/static/app/account/reset-password.component.ts
Normal 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){}
|
||||
}
|
15
src/ui/static/app/account/sign-in/sign-in-credential.ts
Normal file
15
src/ui/static/app/account/sign-in/sign-in-credential.ts
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
/**
|
||||
* Declare class for store the sign in data,
|
||||
* two prperties:
|
||||
* principal: The username used to sign in
|
||||
* password: The password used to sign in
|
||||
*
|
||||
* @export
|
||||
* @class SignInCredential
|
||||
*/
|
||||
|
||||
export class SignInCredential {
|
||||
principal: string;
|
||||
password: string;
|
||||
}
|
7
src/ui/static/app/account/sign-in/sign-in.component.css
Normal file
7
src/ui/static/app/account/sign-in/sign-in.component.css
Normal file
@ -0,0 +1,7 @@
|
||||
.progress-size-small {
|
||||
height: 0.5em !important;
|
||||
}
|
||||
|
||||
.visibility-hidden {
|
||||
visibility: hidden;
|
||||
}
|
39
src/ui/static/app/account/sign-in/sign-in.component.html
Normal file
39
src/ui/static/app/account/sign-in/sign-in.component.html
Normal file
@ -0,0 +1,39 @@
|
||||
<div class="login-wrapper">
|
||||
<form #signInForm="ngForm" class="login">
|
||||
<label class="title">
|
||||
VMware Harbor<span class="trademark">™</span>
|
||||
</label>
|
||||
<div class="login-group">
|
||||
<label for="username" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-top-left" [class.invalid]="userNameInput.invalid && (userNameInput.dirty || userNameInput.touched)">
|
||||
<input class="username" type="text" required
|
||||
[(ngModel)]="signInCredential.principal"
|
||||
name="login_username" id="login_username" placeholder="Username"
|
||||
#userNameInput='ngModel'>
|
||||
<span class="tooltip-content">
|
||||
Username is required!
|
||||
</span>
|
||||
</label>
|
||||
<label for="username" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-top-left" [class.invalid]="passwordInput.invalid && (passwordInput.dirty || passwordInput.touched)">
|
||||
<input class="password" type="password" required
|
||||
[(ngModel)]="signInCredential.password"
|
||||
name="login_password" id="login_password" placeholder="Password"
|
||||
#passwordInput="ngModel">
|
||||
<span class="tooltip-content">
|
||||
Password is required!
|
||||
</span>
|
||||
</label>
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" id="rememberme">
|
||||
<label for="rememberme">
|
||||
Remember me
|
||||
</label>
|
||||
</div>
|
||||
<div [class.visibility-hidden]="signInStatus != statusError" class="error active">
|
||||
Invalid user name or password
|
||||
</div>
|
||||
<button [class.visibility-hidden]="signInStatus === statusOnGoing" [disabled]="signInStatus === statusOnGoing" type="submit" class="btn btn-primary" (click)="signIn()">LOG IN</button>
|
||||
<div [class.visibility-hidden]="signInStatus != statusOnGoing" class="progress loop progress-size-small"><progress></progress></div>
|
||||
<a href="javascript:void(0)" class="signup" (click)="signUp()">Sign up for an account</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
131
src/ui/static/app/account/sign-in/sign-in.component.ts
Normal file
131
src/ui/static/app/account/sign-in/sign-in.component.ts
Normal file
@ -0,0 +1,131 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Input, ViewChild, AfterViewChecked } from '@angular/core';
|
||||
import { NgForm } from '@angular/forms';
|
||||
|
||||
import { SignInService } from './sign-in.service';
|
||||
import { SignInCredential } from './sign-in-credential'
|
||||
import { SessionService } from '../../shared/session.service';
|
||||
|
||||
//Define status flags for signing in states
|
||||
export const signInStatusNormal = 0;
|
||||
export const signInStatusOnGoing = 1;
|
||||
export const signInStatusError = -1;
|
||||
|
||||
@Component({
|
||||
selector: 'sign-in',
|
||||
templateUrl: "sign-in.component.html",
|
||||
styleUrls: ['sign-in.component.css'],
|
||||
|
||||
providers: [SignInService]
|
||||
})
|
||||
|
||||
export class SignInComponent implements AfterViewChecked {
|
||||
//Form reference
|
||||
signInForm: NgForm;
|
||||
@ViewChild('signInForm') currentForm: NgForm;
|
||||
|
||||
//Status flag
|
||||
signInStatus: number = 0;
|
||||
|
||||
//Initialize sign in credential
|
||||
@Input() signInCredential: SignInCredential = {
|
||||
principal: "",
|
||||
password: ""
|
||||
};
|
||||
|
||||
constructor(
|
||||
private signInService: SignInService,
|
||||
private router: Router,
|
||||
private session: SessionService
|
||||
) { }
|
||||
|
||||
//For template accessing
|
||||
get statusError(): number {
|
||||
return signInStatusError;
|
||||
}
|
||||
|
||||
get statusOnGoing(): number {
|
||||
return signInStatusOnGoing;
|
||||
}
|
||||
|
||||
//Validate the related fields
|
||||
private validate(): boolean {
|
||||
return true;
|
||||
//return this.signInForm.valid;
|
||||
}
|
||||
|
||||
//General error handler
|
||||
private handleError(error) {
|
||||
//Set error status
|
||||
this.signInStatus = signInStatusError;
|
||||
|
||||
let message = error.status ? error.status + ":" + error.statusText : error;
|
||||
console.error("An error occurred when signing in:", message);
|
||||
}
|
||||
|
||||
//Hande form values changes
|
||||
private formChanged() {
|
||||
if (this.currentForm === this.signInForm) {
|
||||
return;
|
||||
}
|
||||
this.signInForm = this.currentForm;
|
||||
if (this.signInForm) {
|
||||
this.signInForm.valueChanges
|
||||
.subscribe(data => {
|
||||
this.updateState();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Implement interface
|
||||
//Watch the view change only when view is in error state
|
||||
ngAfterViewChecked() {
|
||||
if (this.signInStatus === signInStatusError) {
|
||||
this.formChanged();
|
||||
}
|
||||
}
|
||||
|
||||
//Update the status if we have done some changes
|
||||
updateState(): void {
|
||||
if (this.signInStatus === signInStatusError) {
|
||||
this.signInStatus = signInStatusNormal; //reset
|
||||
}
|
||||
}
|
||||
|
||||
//Trigger the signin action
|
||||
signIn(): void {
|
||||
//Should validate input firstly
|
||||
if (!this.validate()) {
|
||||
console.info("return");
|
||||
return;
|
||||
}
|
||||
|
||||
//Start signing in progress
|
||||
this.signInStatus = signInStatusOnGoing;
|
||||
|
||||
//Call the service to send out the http request
|
||||
this.signInService.signIn(this.signInCredential)
|
||||
.then(() => {
|
||||
//Set status
|
||||
this.signInStatus = signInStatusNormal;
|
||||
|
||||
//Validate the sign-in session
|
||||
this.session.retrieveUser()
|
||||
.then(() => {
|
||||
//Routing to the right location
|
||||
let nextRoute = ["/harbor", "dashboard"];
|
||||
this.router.navigate(nextRoute);
|
||||
})
|
||||
.catch(this.handleError);
|
||||
})
|
||||
.catch(this.handleError);
|
||||
}
|
||||
|
||||
//Help user navigate to the sign up
|
||||
signUp(): void {
|
||||
let nextRoute = ["/harbor", "signup"];
|
||||
this.router.navigate(nextRoute);
|
||||
}
|
||||
}
|
42
src/ui/static/app/account/sign-in/sign-in.service.ts
Normal file
42
src/ui/static/app/account/sign-in/sign-in.service.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Headers, Http, URLSearchParams } from '@angular/http';
|
||||
import 'rxjs/add/operator/toPromise';
|
||||
|
||||
import { SignInCredential } from './sign-in-credential';
|
||||
|
||||
const url_prefix = '';
|
||||
const signInUrl = url_prefix + '/login';
|
||||
/**
|
||||
*
|
||||
* Define a service to provide sign in methods
|
||||
*
|
||||
* @export
|
||||
* @class SignInService
|
||||
*/
|
||||
@Injectable()
|
||||
export class SignInService {
|
||||
private headers = new Headers({
|
||||
"Content-Type": 'application/x-www-form-urlencoded'
|
||||
});
|
||||
|
||||
constructor(private http: Http) {}
|
||||
|
||||
//Handle the related exceptions
|
||||
private handleError(error: any): Promise<any>{
|
||||
return Promise.reject(error.message || error);
|
||||
}
|
||||
|
||||
//Submit signin form to backend (NOT restful service)
|
||||
signIn(signInCredential: SignInCredential): Promise<any>{
|
||||
//Build the form package
|
||||
const body = new URLSearchParams();
|
||||
body.set('principal', signInCredential.principal);
|
||||
body.set('password', signInCredential.password);
|
||||
|
||||
//Trigger Http
|
||||
return this.http.post(signInUrl, body.toString(), { headers: this.headers })
|
||||
.toPromise()
|
||||
.then(()=>null)
|
||||
.catch(this.handleError);
|
||||
}
|
||||
}
|
1
src/ui/static/app/account/sign-up.component.html
Normal file
1
src/ui/static/app/account/sign-up.component.html
Normal file
@ -0,0 +1 @@
|
||||
<p>Placeholder for signup</p>
|
10
src/ui/static/app/account/sign-up.component.ts
Normal file
10
src/ui/static/app/account/sign-up.component.ts
Normal 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){}
|
||||
}
|
1
src/ui/static/app/app.component.html
Normal file
1
src/ui/static/app/app.component.html
Normal file
@ -0,0 +1 @@
|
||||
<router-outlet></router-outlet>
|
8
src/ui/static/app/app.component.scss
Normal file
8
src/ui/static/app/app.component.scss
Normal 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);
|
||||
}
|
||||
}
|
46
src/ui/static/app/app.component.spec.ts
Normal file
46
src/ui/static/app/app.component.spec.ts
Normal 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();
|
||||
// }));
|
||||
|
||||
|
||||
// });
|
12
src/ui/static/app/app.component.ts
Normal file
12
src/ui/static/app/app.component.ts
Normal 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) {
|
||||
// }
|
||||
}
|
28
src/ui/static/app/app.module.ts
Normal file
28
src/ui/static/app/app.module.ts
Normal file
@ -0,0 +1,28 @@
|
||||
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 { BaseModule } from './base/base.module';
|
||||
|
||||
import { HarborRoutingModule } from './harbor-routing.module';
|
||||
import { CoreModule } from './core/core.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
],
|
||||
imports: [
|
||||
CoreModule,
|
||||
AccountModule,
|
||||
BaseModule,
|
||||
HarborRoutingModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
25
src/ui/static/app/base/base-routing.module.ts
Normal file
25
src/ui/static/app/base/base-routing.module.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { HarborShellComponent } from './harbor-shell/harbor-shell.component';
|
||||
|
||||
import { DashboardComponent } from '../dashboard/dashboard.component';
|
||||
import { ProjectComponent } from '../project/project.component';
|
||||
|
||||
const baseRoutes: Routes = [
|
||||
{
|
||||
path: 'harbor', component: HarborShellComponent,
|
||||
children: [
|
||||
{ path: 'dashboard', component: DashboardComponent },
|
||||
{ path: 'projects', component: ProjectComponent }
|
||||
]
|
||||
}];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild(baseRoutes)
|
||||
],
|
||||
exports: [ RouterModule ]
|
||||
})
|
||||
export class BaseRoutingModule {
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
<clr-dropdown [clrMenuPosition]="'bottom-right'">
|
||||
<button class="nav-text" clrDropdownToggle>
|
||||
<!--<clr-icon shape="user" class="is-inverse" size="24"></clr-icon>-->
|
||||
<span>Administrator</span>
|
||||
<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>Account Setting</a>
|
||||
<a href="javascript:void(0)" clrDropdownItem>About</a>
|
||||
</div>
|
||||
</clr-dropdown>
|
@ -0,0 +1,16 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: "base-settings",
|
||||
templateUrl: "base-settings.component.html"
|
||||
})
|
||||
|
||||
/**
|
||||
* Component to handle the account settings
|
||||
*/
|
||||
export class BaseSettingsComponent implements OnInit {
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
35
src/ui/static/app/base/base.module.ts
Normal file
35
src/ui/static/app/base/base.module.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
|
||||
import { DashboardModule } from '../dashboard/dashboard.module';
|
||||
import { ProjectModule } from '../project/project.module';
|
||||
import { UserModule } from '../user/user.module';
|
||||
|
||||
import { NavigatorComponent } from './navigator/navigator.component';
|
||||
import { GlobalSearchComponent } from './global-search/global-search.component';
|
||||
import { FooterComponent } from './footer/footer.component';
|
||||
import { HarborShellComponent } from './harbor-shell/harbor-shell.component';
|
||||
import { BaseSettingsComponent } from './base-settings/base-settings.component';
|
||||
|
||||
import { BaseRoutingModule } from './base-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
SharedModule,
|
||||
DashboardModule,
|
||||
ProjectModule,
|
||||
UserModule,
|
||||
BaseRoutingModule
|
||||
],
|
||||
declarations: [
|
||||
NavigatorComponent,
|
||||
GlobalSearchComponent,
|
||||
BaseSettingsComponent,
|
||||
FooterComponent,
|
||||
HarborShellComponent
|
||||
],
|
||||
exports: [ HarborShellComponent ]
|
||||
})
|
||||
export class BaseModule {
|
||||
|
||||
}
|
0
src/ui/static/app/base/footer/footer.component.html
Normal file
0
src/ui/static/app/base/footer/footer.component.html
Normal file
10
src/ui/static/app/base/footer/footer.component.ts
Normal file
10
src/ui/static/app/base/footer/footer.component.ts
Normal 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){}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
<a class="nav-link">
|
||||
<span class="nav-text">
|
||||
<clr-icon shape="search"></clr-icon>
|
||||
</span>
|
||||
</a>
|
@ -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){}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
<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>
|
||||
<global-message></global-message>
|
||||
<div class="content-container">
|
||||
<div class="content-area">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
</div>
|
||||
</clr-main-container>
|
@ -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 {
|
||||
|
||||
}
|
41
src/ui/static/app/base/navigator/navigator.component.html
Normal file
41
src/ui/static/app/base/navigator/navigator.component.html
Normal file
@ -0,0 +1,41 @@
|
||||
<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', 'projects']" routerLinkActive="active">
|
||||
<span class="nav-text">Project</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<clr-dropdown [clrMenuPosition]="'bottom-right'">
|
||||
<!--<clr-icon shape="user" class="is-inverse" size="24"></clr-icon>-->
|
||||
<button class="nav-text" clrDropdownToggle>
|
||||
<span>Administrator</span>
|
||||
<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>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>
|
10
src/ui/static/app/base/navigator/navigator.component.ts
Normal file
10
src/ui/static/app/base/navigator/navigator.component.ts
Normal 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){}
|
||||
}
|
22
src/ui/static/app/core/core.module.ts
Normal file
22
src/ui/static/app/core/core.module.ts
Normal file
@ -0,0 +1,22 @@
|
||||
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';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpModule,
|
||||
ClarityModule.forRoot()
|
||||
],
|
||||
exports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpModule,
|
||||
ClarityModule
|
||||
]
|
||||
})
|
||||
export class CoreModule {
|
||||
}
|
54
src/ui/static/app/dashboard/dashboard.component.html
Normal file
54
src/ui/static/app/dashboard/dashboard.component.html
Normal 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>
|
20
src/ui/static/app/dashboard/dashboard.component.ts
Normal file
20
src/ui/static/app/dashboard/dashboard.component.ts
Normal 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 }
|
||||
];
|
||||
}
|
||||
|
||||
}
|
10
src/ui/static/app/dashboard/dashboard.module.ts
Normal file
10
src/ui/static/app/dashboard/dashboard.module.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { DashboardComponent } from './dashboard.component';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [ SharedModule ],
|
||||
declarations: [ DashboardComponent ],
|
||||
exports: [ DashboardComponent ]
|
||||
})
|
||||
export class DashboardModule {}
|
7
src/ui/static/app/global-message/message.component.html
Normal file
7
src/ui/static/app/global-message/message.component.html
Normal file
@ -0,0 +1,7 @@
|
||||
<clr-alert [clrAlertType]="'alert-danger'" [clrAlertAppLevel]="true" [(clrAlertClosed)]="!globalMessageOpened" (clrAlertClosedChange)="onClose()">
|
||||
<div class="alert-item">
|
||||
<span class="alert-text">
|
||||
{{globalMessage}}
|
||||
</span>
|
||||
</div>
|
||||
</clr-alert>
|
26
src/ui/static/app/global-message/message.component.ts
Normal file
26
src/ui/static/app/global-message/message.component.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { MessageService } from './message.service';
|
||||
|
||||
@Component({
|
||||
selector: 'global-message',
|
||||
templateUrl: 'message.component.html'
|
||||
})
|
||||
export class MessageComponent {
|
||||
|
||||
globalMessageOpened: boolean;
|
||||
globalMessage: string;
|
||||
|
||||
constructor(messageService: MessageService) {
|
||||
messageService.messageAnnounced$.subscribe(
|
||||
message=>{
|
||||
this.globalMessageOpened = true;
|
||||
this.globalMessage = message;
|
||||
console.log('received message:' + message);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
onClose() {
|
||||
this.globalMessageOpened = false;
|
||||
}
|
||||
}
|
14
src/ui/static/app/global-message/message.service.ts
Normal file
14
src/ui/static/app/global-message/message.service.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
|
||||
@Injectable()
|
||||
export class MessageService {
|
||||
|
||||
private messageAnnouncedSource = new Subject<string>();
|
||||
|
||||
messageAnnounced$ = this.messageAnnouncedSource.asObservable();
|
||||
|
||||
announceMessage(message: string) {
|
||||
this.messageAnnouncedSource.next(message);
|
||||
}
|
||||
}
|
20
src/ui/static/app/harbor-routing.module.ts
Normal file
20
src/ui/static/app/harbor-routing.module.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { SignInComponent } from './account/sign-in/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 {
|
||||
|
||||
}
|
2
src/ui/static/app/index.ts
Normal file
2
src/ui/static/app/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './app.component';
|
||||
export * from './app.module';
|
24
src/ui/static/app/log/audit-log.component.html
Normal file
24
src/ui/static/app/log/audit-log.component.html
Normal 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 auditLogs">
|
||||
<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>{{auditLogs.length}} item(s)</clr-dg-footer>
|
||||
</clr-datagrid>
|
||||
</div>
|
||||
</div>
|
18
src/ui/static/app/log/audit-log.component.ts
Normal file
18
src/ui/static/app/log/audit-log.component.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { AuditLog } from './audit-log';
|
||||
|
||||
@Component({
|
||||
templateUrl: './audit-log.component.html'
|
||||
})
|
||||
export class AuditLogComponent implements OnInit {
|
||||
|
||||
auditLogs: AuditLog[];
|
||||
|
||||
ngOnInit(): void {
|
||||
this.auditLogs = [
|
||||
{ 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' }
|
||||
];
|
||||
}
|
||||
}
|
7
src/ui/static/app/log/audit-log.ts
Normal file
7
src/ui/static/app/log/audit-log.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export class AuditLog {
|
||||
username: string;
|
||||
repoName: string;
|
||||
tag: string;
|
||||
operation: string;
|
||||
timestamp: string;
|
||||
}
|
10
src/ui/static/app/log/log.module.ts
Normal file
10
src/ui/static/app/log/log.module.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { AuditLogComponent } from './audit-log.component';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [ SharedModule ],
|
||||
declarations: [ AuditLogComponent ],
|
||||
exports: [ AuditLogComponent ]
|
||||
})
|
||||
export class LogModule {}
|
@ -0,0 +1,11 @@
|
||||
<clr-dropdown [clrMenuPosition]="'bottom-right'" [clrCloseMenuOnItemClick]="true">
|
||||
<button clrDropdownToggle>
|
||||
<clr-icon shape="ellipses-vertical"></clr-icon>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a href="javascript:void(0)" clrDropdownItem>New Policy</a>
|
||||
<a href="javascript:void(0)" clrDropdownItem (click)="toggle()">Make {{project.public === 0 ? 'Public' : 'Private'}} </a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="javascript:void(0)" clrDropdownItem (click)="delete()">Delete</a>
|
||||
</div>
|
||||
</clr-dropdown>
|
@ -0,0 +1,30 @@
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { Project } from '../project';
|
||||
import { ProjectService } from '../project.service';
|
||||
|
||||
@Component({
|
||||
selector: 'action-project',
|
||||
templateUrl: 'action-project.component.html'
|
||||
})
|
||||
export class ActionProjectComponent {
|
||||
|
||||
@Output() togglePublic = new EventEmitter<Project>();
|
||||
@Output() deleteProject = new EventEmitter<Project>();
|
||||
|
||||
@Input() project: Project;
|
||||
|
||||
constructor(private projectService: ProjectService) {}
|
||||
|
||||
toggle() {
|
||||
if(this.project) {
|
||||
this.project.public === 0 ? this.project.public = 1 : this.project.public = 0;
|
||||
this.togglePublic.emit(this.project);
|
||||
}
|
||||
}
|
||||
|
||||
delete() {
|
||||
if(this.project) {
|
||||
this.deleteProject.emit(this.project);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
<clr-modal [(clrModalOpen)]="createProjectOpened">
|
||||
<h3 class="modal-title">New Project</h3>
|
||||
<div class="modal-body">
|
||||
<form>
|
||||
<section class="form-block">
|
||||
<div class="form-group">
|
||||
<label for="create_project_name" class="col-md-4">Project Name</label>
|
||||
<label for="create_project_name" aria-haspopup="true" role="tooltip" [class.invalid]="hasError" [class.valid]="!hasError" class="tooltip tooltip-validation tooltip-sm tooltip-bottom-right">
|
||||
<input type="text" id="create_project_name" [(ngModel)]="project.name" name="name" size="20" (keyup)="hasError=false;">
|
||||
<span class="tooltip-content">
|
||||
{{errorMessage}}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-4">Public</label>
|
||||
<div class="checkbox-inline">
|
||||
<input type="checkbox" id="create_project_public" [(ngModel)]="project.public" name="public">
|
||||
<label for="create_project_public"></label>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline" (click)="createProjectOpened = false">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" (click)="onSubmit()">Ok</button>
|
||||
</div>
|
||||
</clr-modal>
|
@ -0,0 +1,57 @@
|
||||
import { Component, EventEmitter, Output } from '@angular/core';
|
||||
import { Response } from '@angular/http';
|
||||
|
||||
import { Project } from '../project';
|
||||
import { ProjectService } from '../project.service';
|
||||
|
||||
import { MessageService } from '../../global-message/message.service';
|
||||
|
||||
@Component({
|
||||
selector: 'create-project',
|
||||
templateUrl: 'create-project.component.html',
|
||||
styleUrls: [ 'create-project.css' ]
|
||||
})
|
||||
export class CreateProjectComponent {
|
||||
|
||||
project: Project = new Project();
|
||||
createProjectOpened: boolean;
|
||||
|
||||
errorMessage: string;
|
||||
hasError: boolean;
|
||||
|
||||
@Output() create = new EventEmitter<boolean>();
|
||||
|
||||
constructor(private projectService: ProjectService, private messageService: MessageService) {}
|
||||
|
||||
onSubmit() {
|
||||
this.hasError = false;
|
||||
this.projectService
|
||||
.createProject(this.project.name, this.project.public ? 1 : 0)
|
||||
.subscribe(
|
||||
status=>{
|
||||
this.create.emit(true);
|
||||
this.createProjectOpened = false;
|
||||
},
|
||||
error=>{
|
||||
this.hasError = true;
|
||||
if (error instanceof Response) {
|
||||
switch(error.status) {
|
||||
case 409:
|
||||
this.errorMessage = 'Project name already exists.'; break;
|
||||
case 400:
|
||||
this.errorMessage = 'Project name is illegal.'; break;
|
||||
default:
|
||||
this.errorMessage = 'Unknown error for project name.';
|
||||
this.messageService.announceMessage(this.errorMessage);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
newProject() {
|
||||
this.hasError = false;
|
||||
this.project = new Project();
|
||||
this.createProjectOpened = true;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
<clr-dropdown [clrMenuPosition]="'bottom-left'">
|
||||
<button class="btn btn-sm btn-link" clrDropdownToggle>
|
||||
{{currentType.value}}
|
||||
<clr-icon shape="caret down"></clr-icon>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a href="javascript:void(0)" clrDropdownItem *ngFor="let p of types" (click)="doFilter(p.key)">{{p.value}}</a>
|
||||
</div>
|
||||
</clr-dropdown>
|
@ -0,0 +1,23 @@
|
||||
import { Component, Output, EventEmitter } from '@angular/core';
|
||||
|
||||
export const projectTypes = [
|
||||
{ 'key' : 0, 'value': 'My Projects' },
|
||||
{ 'key' : 1, 'value': 'Public Projects'}
|
||||
];
|
||||
|
||||
@Component({
|
||||
selector: 'filter-project',
|
||||
templateUrl: 'filter-project.component.html'
|
||||
})
|
||||
export class FilterProjectComponent {
|
||||
|
||||
@Output() filter = new EventEmitter<number>();
|
||||
types = projectTypes;
|
||||
currentType = projectTypes[0];
|
||||
|
||||
doFilter(type: number) {
|
||||
console.log('Filtered projects by:' + type);
|
||||
this.currentType = projectTypes.find(item=>item.key === type);
|
||||
this.filter.emit(type);
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<clr-datagrid [(clrDgSelected)]="selected">
|
||||
<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>Description</clr-dg-column>
|
||||
<clr-dg-row *clrDgItems="let p of projects" [clrDgItem]="p" [(clrDgSelected)]="p.selected">
|
||||
<!--<clr-dg-action-overflow>
|
||||
<button class="action-item" (click)="onEdit(p)">Edit</button>
|
||||
<button class="action-item" (click)="onDelete(p)">Delete</button>
|
||||
</clr-dg-action-overflow>-->
|
||||
<clr-dg-cell><a [routerLink]="['/harbor', 'projects', p.id, 'repository']" >{{p.name}}</a></clr-dg-cell>
|
||||
<clr-dg-cell>{{p.public == 1 ? 'Public': 'Private'}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{p.repo_count}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{p.creation_time}}</clr-dg-cell>
|
||||
<clr-dg-cell>
|
||||
{{p.description}}
|
||||
<span style="float: right;">
|
||||
<action-project (togglePublic)="toggleProject($event)" (deleteProject)="deleteProject($event)" [project]="p"></action-project>
|
||||
</span>
|
||||
</clr-dg-cell>
|
||||
|
||||
|
||||
|
||||
</clr-dg-row>
|
||||
<clr-dg-footer>{{ (projects ? projects.length : 0) }} item(s)</clr-dg-footer>
|
||||
</clr-datagrid>
|
@ -0,0 +1,61 @@
|
||||
import { Component, EventEmitter, Output } from '@angular/core';
|
||||
import { Project } from '../project';
|
||||
import { ProjectService } from '../project.service';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'list-project',
|
||||
templateUrl: 'list-project.component.html'
|
||||
})
|
||||
export class ListProjectComponent {
|
||||
|
||||
projects: Project[];
|
||||
errorMessage: string;
|
||||
|
||||
selected = [];
|
||||
|
||||
@Output() actionPerform = new EventEmitter<boolean>();
|
||||
|
||||
constructor(private projectService: ProjectService) {}
|
||||
|
||||
retrieve(name: string, isPublic: number): void {
|
||||
this.projectService
|
||||
.listProjects(name, isPublic)
|
||||
.subscribe(
|
||||
response => this.projects = response,
|
||||
error => this.errorMessage = <any>error);
|
||||
}
|
||||
|
||||
toggleProject(p: Project) {
|
||||
this.projectService
|
||||
.toggleProjectPublic(p.project_id, p.public)
|
||||
.subscribe(
|
||||
response=>console.log(response),
|
||||
error=>console.log(error)
|
||||
);
|
||||
}
|
||||
|
||||
deleteProject(p: Project) {
|
||||
this.projectService
|
||||
.deleteProject(p.project_id)
|
||||
.subscribe(
|
||||
response=>{
|
||||
console.log(response);
|
||||
this.actionPerform.emit(true);
|
||||
},
|
||||
error=>console.log(error)
|
||||
);
|
||||
}
|
||||
|
||||
deleteSelectedProjects() {
|
||||
this.selected.forEach(p=>this.deleteProject(p));
|
||||
}
|
||||
|
||||
onEdit(p: Project) {
|
||||
|
||||
}
|
||||
|
||||
onDelete(p: Project) {
|
||||
|
||||
}
|
||||
}
|
35
src/ui/static/app/project/member/member.component.html
Normal file
35
src/ui/static/app/project/member/member.component.html
Normal 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>
|
18
src/ui/static/app/project/member/member.component.ts
Normal file
18
src/ui/static/app/project/member/member.component.ts
Normal 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'}
|
||||
];
|
||||
}
|
||||
}
|
4
src/ui/static/app/project/member/member.ts
Normal file
4
src/ui/static/app/project/member/member.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export class Member {
|
||||
name: string;
|
||||
role: string;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<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>
|
@ -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){}
|
||||
}
|
11
src/ui/static/app/project/project-detail/project-detail.css
Normal file
11
src/ui/static/app/project/project-detail/project-detail.css
Normal file
@ -0,0 +1,11 @@
|
||||
.display-in-line {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.project-title {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.pull-right {
|
||||
float: right !important;
|
||||
}
|
38
src/ui/static/app/project/project-routing.module.ts
Normal file
38
src/ui/static/app/project/project-routing.module.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { HarborShellComponent} from '../base/harbor-shell/harbor-shell.component';
|
||||
import { ProjectComponent } from './project.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 { AuditLogComponent } from '../log/audit-log.component';
|
||||
|
||||
const projectRoutes: Routes = [
|
||||
{ path: 'harbor',
|
||||
component: HarborShellComponent,
|
||||
children: [
|
||||
{ path: 'projects', component: ProjectComponent },
|
||||
{
|
||||
path: 'projects/:id',
|
||||
component: ProjectDetailComponent,
|
||||
children: [
|
||||
{ path: 'repository', component: RepositoryComponent },
|
||||
{ path: 'replication', component: ReplicationComponent },
|
||||
{ path: 'member', component: MemberComponent },
|
||||
{ path: 'log', component: AuditLogComponent }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild(projectRoutes)
|
||||
],
|
||||
exports: [ RouterModule ]
|
||||
})
|
||||
export class ProjectRoutingModule {}
|
15
src/ui/static/app/project/project.component.html
Normal file
15
src/ui/static/app/project/project.component.html
Normal file
@ -0,0 +1,15 @@
|
||||
<h3>Projects</h3>
|
||||
<div class="row flex-items-xs-between">
|
||||
<div class="col-xs-4">
|
||||
<button class="btn btn-link" (click)="openModal()"><clr-icon shape="add"></clr-icon>New Project</button>
|
||||
<button class="btn btn-link" (click)="deleteSelectedProjects()"><clr-icon shape="close"></clr-icon>Delete</button>
|
||||
<create-project (create)="createProject($event)" (openModal)="openModal($event)"></create-project>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<filter-project (filter)="filterProjects($event)"></filter-project>
|
||||
<search-project (search)="searchProjects($event)"></search-project>
|
||||
</div>
|
||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||
<list-project (actionPerform)="actionPerform($event)"></list-project>
|
||||
</div>
|
||||
</div>
|
56
src/ui/static/app/project/project.component.ts
Normal file
56
src/ui/static/app/project/project.component.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { ListProjectComponent } from './list-project/list-project.component';
|
||||
import { CreateProjectComponent } from './create-project/create-project.component';
|
||||
|
||||
@Component({
|
||||
selector: 'project',
|
||||
templateUrl: 'project.component.html',
|
||||
styleUrls: [ 'project.css' ]
|
||||
})
|
||||
export class ProjectComponent implements OnInit {
|
||||
|
||||
@ViewChild(ListProjectComponent)
|
||||
listProjects: ListProjectComponent;
|
||||
|
||||
@ViewChild(CreateProjectComponent)
|
||||
creationProject: CreateProjectComponent;
|
||||
|
||||
lastFilteredType: number = 0;
|
||||
|
||||
openModal(): void {
|
||||
this.creationProject.newProject();
|
||||
}
|
||||
|
||||
deleteSelectedProjects(): void {
|
||||
this.listProjects.deleteSelectedProjects();
|
||||
}
|
||||
|
||||
createProject(created: boolean): void {
|
||||
console.log('Project has been created:' + created);
|
||||
this.listProjects.retrieve('', 0);
|
||||
}
|
||||
|
||||
filterProjects(type: number): void {
|
||||
this.lastFilteredType = type;
|
||||
this.listProjects.retrieve('', type);
|
||||
console.log('Projects were filtered by:' + type);
|
||||
|
||||
}
|
||||
|
||||
searchProjects(projectName: string): void {
|
||||
console.log('Search for project name:' + projectName);
|
||||
this.listProjects.retrieve(projectName, this.lastFilteredType);
|
||||
}
|
||||
|
||||
actionPerform(performed: boolean): void {
|
||||
this.listProjects.retrieve('', 0);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.listProjects.retrieve('', 0);
|
||||
}
|
||||
|
||||
}
|
3
src/ui/static/app/project/project.css
Normal file
3
src/ui/static/app/project/project.css
Normal file
@ -0,0 +1,3 @@
|
||||
.my-project-pull-right {
|
||||
float: right;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user