mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-22 00:27:44 +01:00
Merge pull request #5848 from ninjadq/angular6
Frontend upgrade to angular6 and harbor portal refactor to a single container.
This commit is contained in:
commit
62cdccc5dd
19
.gitignore
vendored
19
.gitignore
vendored
@ -24,11 +24,11 @@ src/ui/static/styles.css
|
||||
src/ui/static/i18n
|
||||
src/ui/static/shapes
|
||||
|
||||
src/ui_ng/coverage/
|
||||
src/ui_ng/dist/
|
||||
src/ui_ng/html-report/
|
||||
src/ui_ng/node_modules/
|
||||
src/ui_ng/typings/
|
||||
src/portal/coverage/
|
||||
src/portal/dist/
|
||||
src/portal/html-report/
|
||||
src/portal/node_modules/
|
||||
src/portal/typings/
|
||||
**/*npm-debug.log.*
|
||||
**/*yarn-error.log.*
|
||||
.idea/
|
||||
@ -39,16 +39,11 @@ src/ui_ng/typings/
|
||||
**/ssl/
|
||||
**/proxy.config.json
|
||||
|
||||
src/ui_ng/src/**/*.js
|
||||
src/ui_ng/src/**/*.js.map
|
||||
src/ui_ng/src/**/*.json
|
||||
src/portal/src/**/*.js
|
||||
src/portal/src/**/*.js.map
|
||||
|
||||
**/npm*.log
|
||||
|
||||
src/ui_ng/aot/**/*.js
|
||||
src/ui_ng/aot/**/*.js.map
|
||||
src/ui_ng/aot/**/*.json
|
||||
|
||||
**/*ngsummary.json
|
||||
**/*ngfactory.ts
|
||||
**/aot
|
||||
|
33
.travis.yml
33
.travis.yml
@ -28,14 +28,25 @@ env:
|
||||
REG_VERSION: v2.6.2
|
||||
UI_BUILDER_VERSION: 1.6.0
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- google-chrome
|
||||
packages:
|
||||
- google-chrome-stable
|
||||
- google-chrome-beta
|
||||
|
||||
before_install:
|
||||
- sudo ./tests/hostcfg.sh
|
||||
- sudo ./tests/generateCerts.sh
|
||||
- sudo ./make/prepare
|
||||
- sudo mkdir -p "/data/redis"
|
||||
- sudo mkdir -p /etc/ui/ca/ && sudo mv ./tests/ca.crt /etc/ui/ca/
|
||||
- sudo mkdir -p /harbor && sudo mv ./VERSION /harbor/UIVERSION
|
||||
- sudo ./tests/testprepare.sh
|
||||
- export CHROME_BIN=chromium-browser
|
||||
- export DISPLAY=:99.0
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
- sudo ./tests/hostcfg.sh
|
||||
- sudo ./tests/generateCerts.sh
|
||||
- sudo ./make/prepare
|
||||
- sudo mkdir -p "/data/redis"
|
||||
- sudo mkdir -p /etc/ui/ca/ && sudo mv ./tests/ca.crt /etc/ui/ca/
|
||||
- sudo mkdir -p /harbor && sudo mv ./VERSION /harbor/UIVERSION
|
||||
- sudo ./tests/testprepare.sh
|
||||
|
||||
install:
|
||||
- sudo apt-get update && sudo apt-get install -y libldap2-dev
|
||||
@ -58,6 +69,11 @@ install:
|
||||
- sudo service postgresql stop
|
||||
|
||||
before_script:
|
||||
- cd src/portal
|
||||
- npm install -g -q --no-progress angular-cli
|
||||
- npm install -g -q --no-progress karma
|
||||
- npm install -q --no-progress
|
||||
- npm run build_lib && npm run link_lib && cd ../..
|
||||
- export POSTGRESQL_HOST=$IP
|
||||
- export REGISTRY_URL=$IP:5000
|
||||
- echo $REGISTRY_URL
|
||||
@ -70,8 +86,7 @@ before_script:
|
||||
- sudo mkdir -p ./make/common/config/registry/ && sudo mv ./tests/reg_config.yml ./make/common/config/registry/config.yml
|
||||
|
||||
script:
|
||||
- sudo make run_clarity_ut CLARITYIMAGE=goharbor/harbor-clarity-ui-builder:${UI_BUILDER_VERSION}
|
||||
- cat ./src/ui_ng/npm-ut-test-results
|
||||
- cd src/portal && npm run lint && npm run lint:lib && npm run test && cd ../..
|
||||
- sudo docker-compose -f ./make/docker-compose.test.yml up -d
|
||||
- make go_check
|
||||
- ./tests/pushimage.sh
|
||||
|
@ -93,9 +93,9 @@ The folder graph below shows the structure of the source code folder `harbor/src
|
||||
│ ├── static
|
||||
│ ├── utils
|
||||
│ └── views
|
||||
├── ui_ng # The code of harbor web UI
|
||||
├── portal # The code of harbor web UI
|
||||
│ ├── e2e
|
||||
│ ├── lib # Source code of harbor-ui npm library which includes the main UI components of web UI
|
||||
│ ├── lib # Source code of @harbor/ui npm library which includes the main UI components of web UI
|
||||
│ └── src # General web page UI code of Harbor
|
||||
└── vendor # Go code dependencies
|
||||
├── github.com
|
||||
@ -134,11 +134,11 @@ Harbor web UI is built based on [Clarity](https://vmware.github.io/clarity/) and
|
||||
**Npm Package Dependency:** Run the following commands to restore the package dependencies.
|
||||
```
|
||||
#For the web UI
|
||||
cd $REPO_DIR/src/ui_ng
|
||||
cd $REPO_DIR/src/portal
|
||||
npm install
|
||||
|
||||
#For the UI library
|
||||
cd $REPO_DIR/src/ui_ng/lib
|
||||
cd $REPO_DIR/src/portal/lib
|
||||
npm install
|
||||
```
|
||||
|
||||
@ -213,7 +213,7 @@ go test -v ./...
|
||||
|
||||
Run UI library test cases:
|
||||
```
|
||||
#cd #working_dir/src/ui_ng/lib
|
||||
#cd #working_dir/src/portal/lib
|
||||
npm run test
|
||||
```
|
||||
|
||||
|
53
Makefile
53
Makefile
@ -68,7 +68,7 @@ MAKEDEVPATH=$(MAKEPATH)/dev
|
||||
SRCPATH=./src
|
||||
TOOLSPATH=$(BUILDPATH)/tools
|
||||
UIPATH=$(BUILDPATH)/src/ui
|
||||
UINGPATH=$(BUILDPATH)/src/ui_ng
|
||||
UINGPATH=$(BUILDPATH)/src/portal
|
||||
GOBASEPATH=/go/src/github.com/goharbor
|
||||
CHECKENVCMD=checkenv.sh
|
||||
|
||||
@ -79,8 +79,6 @@ DEVFLAG=true
|
||||
NOTARYFLAG=false
|
||||
CLAIRFLAG=false
|
||||
HTTPPROXY=
|
||||
REBUILDCLARITYFLAG=false
|
||||
NEWCLARITYVERSION=
|
||||
BUILDBIN=false
|
||||
MIGRATORFLAG=false
|
||||
# enable/disable chart repo supporting
|
||||
@ -104,15 +102,10 @@ CLAIRVERSION=v2.0.5
|
||||
CLAIRDBVERSION=$(VERSIONTAG)
|
||||
MIGRATORVERSION=$(VERSIONTAG)
|
||||
REDISVERSION=$(VERSIONTAG)
|
||||
|
||||
# version of chartmuseum
|
||||
CHARTMUSEUMVERSION=v0.7.1
|
||||
|
||||
#clarity parameters
|
||||
CLARITYIMAGE=goharbor/harbor-clarity-ui-builder[:tag]
|
||||
CLARITYSEEDPATH=/harbor_src
|
||||
CLARITYUTPATH=${CLARITYSEEDPATH}/ui_ng/lib
|
||||
CLARITYBUILDSCRIPT=/entrypoint.sh
|
||||
|
||||
# docker parameters
|
||||
DOCKERCMD=$(shell which docker)
|
||||
DOCKERBUILD=$(DOCKERCMD) build
|
||||
@ -179,15 +172,14 @@ MAKEFILEPATH_PHOTON=$(MAKEPATH)/photon
|
||||
|
||||
# common dockerfile
|
||||
DOCKERFILEPATH_COMMON=$(MAKEPATH)/common
|
||||
DOCKERFILE_CLARITY=$(MAKEPATH)/dev/nodeclarity/Dockerfile
|
||||
|
||||
# docker image name
|
||||
DOCKERIMAGENAME_ADMINSERVER=goharbor/harbor-adminserver
|
||||
DOCKERIMAGENAME_PORTAL=goharbor/harbor-portal
|
||||
DOCKERIMAGENAME_UI=goharbor/harbor-ui
|
||||
DOCKERIMAGENAME_JOBSERVICE=goharbor/harbor-jobservice
|
||||
DOCKERIMAGENAME_LOG=goharbor/harbor-log
|
||||
DOCKERIMAGENAME_DB=goharbor/harbor-db
|
||||
DOCKERIMAGENAME_CLARITY=goharbor/harbor-clarity-ui-builder
|
||||
DOCKERIMAGENAME_CHART_SERVER=goharbor/chartmuseum-photon
|
||||
DOCKERIMAGENAME_REGCTL=goharbor/harbor-registryctl
|
||||
|
||||
@ -218,6 +210,7 @@ REGISTRYPASSWORD=default
|
||||
|
||||
# cmds
|
||||
DOCKERSAVE_PARA=$(DOCKERIMAGENAME_ADMINSERVER):$(VERSIONTAG) \
|
||||
$(DOCKERIMAGENAME_PORTAL):$(VERSIONTAG) \
|
||||
$(DOCKERIMAGENAME_UI):$(VERSIONTAG) \
|
||||
$(DOCKERIMAGENAME_LOG):$(VERSIONTAG) \
|
||||
$(DOCKERIMAGENAME_DB):$(VERSIONTAG) \
|
||||
@ -271,15 +264,6 @@ version:
|
||||
check_environment:
|
||||
@$(MAKEPATH)/$(CHECKENVCMD)
|
||||
|
||||
compile_clarity:
|
||||
@echo "compiling binary for clarity ui..."
|
||||
@if [ "$(HTTPPROXY)" != "" ] ; then \
|
||||
$(DOCKERCMD) run --rm -v $(BUILDPATH)/src:$(CLARITYSEEDPATH) $(CLARITYIMAGE) $(SHELL) $(CLARITYBUILDSCRIPT) -p $(HTTPPROXY); \
|
||||
else \
|
||||
$(DOCKERCMD) run --rm -v $(BUILDPATH)/src:$(CLARITYSEEDPATH) $(CLARITYIMAGE) $(SHELL) $(CLARITYBUILDSCRIPT); \
|
||||
fi
|
||||
@echo "Done."
|
||||
|
||||
compile_adminserver:
|
||||
@echo "compiling binary for adminserver (golang image)..."
|
||||
@echo $(GOBASEPATH)
|
||||
@ -304,7 +288,7 @@ compile_registryctl:
|
||||
@$(DOCKERCMD) run --rm -v $(BUILDPATH):$(GOBUILDPATH) -w $(GOBUILDPATH_REGISTRYCTL) $(GOBUILDIMAGE) $(GOIMAGEBUILD) -o $(GOBUILDMAKEPATH_REGISTRYCTL)/$(REGISTRYCTLBINARYNAME)
|
||||
@echo "Done."
|
||||
|
||||
compile:check_environment compile_clarity compile_adminserver compile_ui compile_jobservice compile_registryctl
|
||||
compile:check_environment compile_adminserver compile_ui compile_jobservice compile_registryctl
|
||||
|
||||
prepare:
|
||||
@echo "preparing..."
|
||||
@ -382,28 +366,6 @@ package_offline: compile version build modify_sourcefiles modify_composefile
|
||||
@rm -rf $(HARBORPKG)
|
||||
@echo "Done."
|
||||
|
||||
refresh_clarity_builder:
|
||||
@if [ "$(REBUILDCLIATRYFLAG)" = "true" ] ; then \
|
||||
echo "set http proxy.."; \
|
||||
if [ "$(HTTPPROXY)" != "" ] ; then \
|
||||
$(SEDCMD) -i 's/__proxy__/--proxy $(HTTPPROXY)/g' $(DOCKERFILE_CLARITY) ; \
|
||||
else \
|
||||
$(SEDCMD) -i 's/__proxy__/ /g' $(DOCKERFILE_CLARITY) ; \
|
||||
fi ; \
|
||||
echo "build new clarity image.."; \
|
||||
$(DOCKERBUILD) -f $(DOCKERFILE_CLARITY) -t $(DOCKERIMAGENAME_CLARITY):$(NEWCLARITYVERSION) . ; \
|
||||
echo "push clarity image.."; \
|
||||
$(DOCKERTAG) $(DOCKERIMAGENAME_CLARITY):$(NEWCLARITYVERSION) $(DOCKERIMAGENAME_CLARITY):$(NEWCLARITYVERSION); \
|
||||
$(PUSHSCRIPTPATH)/$(PUSHSCRIPTNAME) $(REGISTRYSERVER)$(DOCKERIMAGENAME_CLARITY):$(NEWCLARITYVERSION) \
|
||||
$(REGISTRYUSER) $(REGISTRYPASSWORD) $(REGISTRYSERVER); \
|
||||
echo "remove local clarity image.."; \
|
||||
$(DOCKERRMIMAGE) $(REGISTRYSERVER)$(DOCKERIMAGENAME_ADMINSERVER):$(NEWCLARITYVERSION); \
|
||||
fi
|
||||
|
||||
run_clarity_ut:
|
||||
@echo "run clarity ut ..."
|
||||
@$(DOCKERCMD) run --rm -v $(UINGPATH):$(CLARITYSEEDPATH) -v $(BUILDPATH)/tests:$(CLARITYSEEDPATH)/tests $(CLARITYIMAGE) $(SHELL) $(CLARITYSEEDPATH)/tests/run-clarity-ut.sh
|
||||
|
||||
gosec:
|
||||
#go get github.com/securego/gosec/cmd/gosec
|
||||
#go get github.com/dghubble/sling
|
||||
@ -444,6 +406,11 @@ pushimage:
|
||||
$(REGISTRYUSER) $(REGISTRYPASSWORD) $(REGISTRYSERVER)
|
||||
@$(DOCKERRMIMAGE) $(REGISTRYSERVER)$(DOCKERIMAGENAME_ADMINSERVER):$(VERSIONTAG)
|
||||
|
||||
@$(DOCKERTAG) $(DOCKERIMAGENAME_PORTAL):$(VERSIONTAG) $(REGISTRYSERVER)$(DOCKERIMAGENAME_PORTAL):$(VERSIONTAG)
|
||||
@$(PUSHSCRIPTPATH)/$(PUSHSCRIPTNAME) $(REGISTRYSERVER)$(DOCKERIMAGENAME_PORTAL):$(VERSIONTAG) \
|
||||
$(REGISTRYUSER) $(REGISTRYPASSWORD) $(REGISTRYSERVER)
|
||||
@$(DOCKERRMIMAGE) $(REGISTRYSERVER)$(DOCKERIMAGENAME_PORTAL):$(VERSIONTAG)
|
||||
|
||||
@$(DOCKERTAG) $(DOCKERIMAGENAME_UI):$(VERSIONTAG) $(REGISTRYSERVER)$(DOCKERIMAGENAME_UI):$(VERSIONTAG)
|
||||
@$(PUSHSCRIPTPATH)/$(PUSHSCRIPTNAME) $(REGISTRYSERVER)$(DOCKERIMAGENAME_UI):$(VERSIONTAG) \
|
||||
$(REGISTRYUSER) $(REGISTRYPASSWORD) $(REGISTRYSERVER)
|
||||
|
@ -50,19 +50,19 @@ You can compile the code by one of the three approaches:
|
||||
* Build, install and bring up Harbor without Notary:
|
||||
|
||||
```sh
|
||||
$ make install GOBUILDIMAGE=golang:1.9.2 COMPILETAG=compile_golangimage CLARITYIMAGE=goharbor/harbor-clarity-ui-builder:1.6.0
|
||||
$ make install GOBUILDIMAGE=golang:1.9.2 COMPILETAG=compile_golangimage
|
||||
```
|
||||
|
||||
* Build, install and bring up Harbor with Notary:
|
||||
|
||||
```sh
|
||||
$ make install GOBUILDIMAGE=golang:1.9.2 COMPILETAG=compile_golangimage CLARITYIMAGE=goharbor/harbor-clarity-ui-builder:1.6.0 NOTARYFLAG=true
|
||||
$ make install GOBUILDIMAGE=golang:1.9.2 COMPILETAG=compile_golangimage NOTARYFLAG=true
|
||||
```
|
||||
|
||||
* Build, install and bring up Harbor with Clair:
|
||||
|
||||
```sh
|
||||
$ make install GOBUILDIMAGE=golang:1.9.2 COMPILETAG=compile_golangimage CLARITYIMAGE=goharbor/harbor-clarity-ui-builder:1.6.0 CLAIRFLAG=true
|
||||
$ make install GOBUILDIMAGE=golang:1.9.2 COMPILETAG=compile_golangimage CLAIRFLAG=true
|
||||
```
|
||||
|
||||
#### II. Compile code with your own Golang environment, then build Harbor
|
||||
@ -108,7 +108,6 @@ The `Makefile` contains these configurable parameters:
|
||||
Variable | Description
|
||||
-------------------|-------------
|
||||
BASEIMAGE | Container base image, default: photon
|
||||
CLARITYIMAGE | Clarity UI builder image, default: harbor-clarity-ui-builder
|
||||
DEVFLAG | Build model flag, default: dev
|
||||
COMPILETAG | Compile model flag, default: compile_normal (local golang build)
|
||||
NOTARYFLAG | Notary mode flag, default: false
|
||||
@ -128,9 +127,9 @@ Target | Description
|
||||
all | prepare env, compile binaries, build images and install images
|
||||
prepare | prepare env
|
||||
compile | compile ui and jobservice code
|
||||
compile_portal | compile portal code
|
||||
compile_ui | compile ui binary
|
||||
compile_jobservice | compile jobservice binary
|
||||
compile_clarity | compile Clarity binary
|
||||
build | build Harbor docker images (default: using build_photon)
|
||||
build_photon | build Harbor docker images from Photon OS base image
|
||||
install | compile binaries, build images, prepare specific version of compose file and startup Harbor instance
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Customize the look & feel of Harbor
|
||||
|
||||
The primary look & feel of Harbor supports to be customized with several simple steps. All the relevant customization in configurations are saved in the `setting.json` file under `$HARBOR_DIR/src/ui_ng/src` folder with `json` format and will be loaded when Harbor is launched.
|
||||
The primary look & feel of Harbor supports to be customized with several simple steps. All the relevant customization in configurations are saved in the `setting.json` file under `$HARBOR_DIR/src/portal/src` folder with `json` format and will be loaded when Harbor is launched.
|
||||
|
||||
## Configure
|
||||
Open the `setting.json` file, you'll see the default content as shown below:
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
### Steps to localize the UI in your language
|
||||
|
||||
1. In the folder `src/ui_ng/src/i18n/lang`, copy json file `en-us-lang.json` to a new file and rename it to `<language>-<locale>-lang.json` .
|
||||
1. In the folder `src/portal/src/i18n/lang`, copy json file `en-us-lang.json` to a new file and rename it to `<language>-<locale>-lang.json` .
|
||||
|
||||
The file contains a JSON object including all the key-value pairs of UI strings:
|
||||
```
|
||||
@ -21,7 +21,7 @@
|
||||
|
||||
2. After creating your language file, you should add it to the language supporting list.
|
||||
|
||||
Locate the file `src/ui_ng/src/app/shared/shared.const.ts`.
|
||||
Locate the file `src/portal/src/app/shared/shared.const.ts`.
|
||||
Append `<language>-<locale>` to the language supporting list:
|
||||
```
|
||||
export const supportedLangs = ['en-us', 'zh-cn', '<language>-<locale>'];
|
||||
@ -39,7 +39,7 @@
|
||||
|
||||
3. Enable the new language in the view.
|
||||
|
||||
Locate the file `src/ui_ng/src/app/base/navigator/navigator.component.html` and then find the following code piece:
|
||||
Locate the file `src/portal/src/app/base/navigator/navigator.component.html` and then find the following code piece:
|
||||
```
|
||||
<div class="dropdown-menu">
|
||||
<a href="javascript:void(0)" clrDropdownItem (click)='switchLanguage("en-us")' [class.lang-selected]='matchLang("en-us")'>English</a>
|
||||
|
@ -5,20 +5,18 @@ BASEIMAGE | Container base image, default: photon
|
||||
DEVFLAG | Build model flag, default: dev
|
||||
COMPILETAG | Compile model flag, default: compile_normal (local golang build)
|
||||
GOBUILDIMAGE | Golang image to compile harbor go source code.
|
||||
CLARITYIMAGE | Clarity image that based on Node to compile UI.
|
||||
NOTARYFLAG | Whether to enable notary in harbor, default:false
|
||||
HTTPPROXY | Clarity proxy to build UI.
|
||||
|
||||
|
||||
### Targets
|
||||
Target | Description
|
||||
--------------------|-------------
|
||||
all | prepare env, compile binaries, build images and install images
|
||||
prepare | prepare env
|
||||
compile | compile ui and jobservice code
|
||||
compile_portal | compile portal code
|
||||
compile_ui | compile ui binary
|
||||
compile_jobservice | compile jobservice binary
|
||||
compile_clarity | compile clarity ui binary
|
||||
compile_adminserver | compile admin server binary
|
||||
build | build Harbor docker images (default: using build_photon)
|
||||
build_photon | build Harbor docker images from Photon OS base image
|
||||
@ -39,10 +37,10 @@ version | set harbor version
|
||||
#### EXAMPLE:
|
||||
|
||||
#### Build and run harbor from source code.
|
||||
make install GOBUILDIMAGE=golang:1.7.3 COMPILETAG=compile_golangimage CLARITYIMAGE=goharbor/harbor-clarity-ui-builder:1.6.0 NOTARYFLAG=true HTTPPROXY=
|
||||
make install GOBUILDIMAGE=golang:1.7.3 COMPILETAG=compile_golangimage NOTARYFLAG=true
|
||||
|
||||
### Package offline installer
|
||||
make package_offline GOBUILDIMAGE=golang:1.7.3 COMPILETAG=compile_golangimage CLARITYIMAGE=goharbor/harbor-clarity-ui-builder:1.6.0 NOTARYFLAG=true HTTPPROXY=
|
||||
make package_offline GOBUILDIMAGE=golang:1.7.3 COMPILETAG=compile_golangimage NOTARYFLAG=true
|
||||
|
||||
### Start harbor with notary
|
||||
make -e NOTARYFLAG=true start
|
||||
|
@ -16,6 +16,10 @@ http {
|
||||
server ui:8080;
|
||||
}
|
||||
|
||||
upstream portal {
|
||||
server portal:80;
|
||||
}
|
||||
|
||||
log_format timed_combined '$$remote_addr - '
|
||||
'"$$request" $$status $$body_bytes_sent '
|
||||
'"$$http_referer" "$$http_user_agent" '
|
||||
@ -30,11 +34,37 @@ http {
|
||||
client_max_body_size 0;
|
||||
|
||||
location / {
|
||||
proxy_pass http://portal/;
|
||||
proxy_set_header Host $$host;
|
||||
proxy_set_header X-Real-IP $$remote_addr;
|
||||
proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for;
|
||||
|
||||
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
|
||||
proxy_set_header X-Forwarded-Proto $$scheme;
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://ui/api/;
|
||||
proxy_set_header Host $$host;
|
||||
proxy_set_header X-Real-IP $$remote_addr;
|
||||
proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for;
|
||||
|
||||
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
|
||||
proxy_set_header X-Forwarded-Proto $$scheme;
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
}
|
||||
|
||||
location ~ ^/(login|log_out|sendEmail|language|reset|userExists|reset_password|chartrepo) {
|
||||
proxy_pass http://ui/;
|
||||
proxy_set_header Host $$host;
|
||||
proxy_set_header X-Real-IP $$remote_addr;
|
||||
proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for;
|
||||
|
||||
|
||||
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
|
||||
proxy_set_header X-Forwarded-Proto $$scheme;
|
||||
|
||||
@ -51,7 +81,7 @@ http {
|
||||
proxy_set_header Host $$http_host;
|
||||
proxy_set_header X-Real-IP $$remote_addr;
|
||||
proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for;
|
||||
|
||||
|
||||
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
|
||||
proxy_set_header X-Forwarded-Proto $$scheme;
|
||||
proxy_buffering off;
|
||||
@ -63,15 +93,15 @@ http {
|
||||
proxy_set_header Host $$host;
|
||||
proxy_set_header X-Real-IP $$remote_addr;
|
||||
proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for;
|
||||
|
||||
|
||||
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
|
||||
proxy_set_header X-Forwarded-Proto $$scheme;
|
||||
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
}
|
||||
|
||||
location /service/notifications {
|
||||
|
||||
location /service/notifications {
|
||||
return 404;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,10 @@ http {
|
||||
upstream ui {
|
||||
server ui:8080;
|
||||
}
|
||||
|
||||
upstream portal {
|
||||
server portal:80;
|
||||
}
|
||||
|
||||
log_format timed_combined '$$remote_addr - '
|
||||
'"$$request" $$status $$body_bytes_sent '
|
||||
@ -47,7 +51,7 @@ http {
|
||||
chunked_transfer_encoding on;
|
||||
|
||||
location / {
|
||||
proxy_pass http://ui/;
|
||||
proxy_pass http://portal/;
|
||||
proxy_set_header Host $$http_host;
|
||||
proxy_set_header X-Real-IP $$remote_addr;
|
||||
proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for;
|
||||
@ -61,6 +65,32 @@ http {
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://ui/api/;
|
||||
proxy_set_header Host $$host;
|
||||
proxy_set_header X-Real-IP $$remote_addr;
|
||||
proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for;
|
||||
|
||||
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
|
||||
proxy_set_header X-Forwarded-Proto $$scheme;
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
}
|
||||
|
||||
location ~ ^/(login|log_out|sendEmail|language|reset|userExists|reset_password|chartrepo) {
|
||||
proxy_pass http://ui;
|
||||
proxy_set_header Host $$host;
|
||||
proxy_set_header X-Real-IP $$remote_addr;
|
||||
proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for;
|
||||
|
||||
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
|
||||
proxy_set_header X-Forwarded-Proto $$scheme;
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
}
|
||||
|
||||
location /v1/ {
|
||||
return 404;
|
||||
|
@ -1,32 +0,0 @@
|
||||
FROM node:10.7.0
|
||||
|
||||
RUN mkdir -p /harbor_resources
|
||||
RUN mkdir -p /harbor_src
|
||||
|
||||
COPY src/ui_ng/package.json /harbor_resources
|
||||
COPY make/dev/nodeclarity/entrypoint.sh /
|
||||
|
||||
# Install Chrome
|
||||
RUN apt-get update && apt-get install -y \
|
||||
apt-transport-https \
|
||||
ca-certificates \
|
||||
curl \
|
||||
gnupg \
|
||||
hicolor-icon-theme \
|
||||
libcanberra-gtk* \
|
||||
libgl1-mesa-dri \
|
||||
libgl1-mesa-glx \
|
||||
libpango1.0-0 \
|
||||
libpulse0 \
|
||||
libv4l-0 \
|
||||
--no-install-recommends
|
||||
RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
||||
RUN dpkg -i google-chrome-stable_current_amd64.deb; apt-get -fy install
|
||||
RUN rm google-chrome-stable_current_amd64.deb
|
||||
|
||||
# Install npm package
|
||||
WORKDIR /harbor_resources
|
||||
|
||||
RUN npm __proxy__ install && \
|
||||
chmod u+x /entrypoint.sh
|
||||
VOLUME ["/harbor_src"]
|
@ -1,69 +0,0 @@
|
||||
{
|
||||
"project": {
|
||||
"version": "1.6.0",
|
||||
"name": "Harbor"
|
||||
},
|
||||
"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",
|
||||
"../node_modules/prismjs/themes/prism-solarizedlight.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",
|
||||
"../node_modules/marked/lib/marked.js",
|
||||
"../node_modules/prismjs/prism.js",
|
||||
"../node_modules/prismjs/components/prism-yaml.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
|
||||
}
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
cd /harbor_src/ui_ng
|
||||
rm -rf dist/*
|
||||
|
||||
npm_proxy=
|
||||
|
||||
while getopts p: option
|
||||
do
|
||||
case "${option}"
|
||||
in
|
||||
p) npm_proxy=${OPTARG};;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ ! -z "$npm_proxy" -a "$npm_proxy" != " " ]; then
|
||||
npm config set proxy $npm_proxy
|
||||
fi
|
||||
|
||||
#Check if node_modules directory existing
|
||||
if [ ! -d "./node_modules" ]; then
|
||||
mv /harbor_resources/node_modules ./
|
||||
fi
|
||||
|
||||
cat ./package.json
|
||||
npm install
|
||||
|
||||
## Build harbor-ui and link it
|
||||
rm -rf /harbor_src/ui_ng/lib/dist
|
||||
npm run build:lib
|
||||
chmod -R +xr /harbor_src/ui_ng/lib/dist
|
||||
cd /harbor_src/ui_ng/lib/dist
|
||||
npm link
|
||||
cd /harbor_src/ui_ng
|
||||
npm link harbor-ui
|
||||
|
||||
## Rollup
|
||||
./node_modules/.bin/ngc -p tsconfig-aot.json
|
||||
sed -i 's/* as//g' src/app/shared/gauge/gauge.component.js
|
||||
./node_modules/.bin/rollup -c rollup-config.js
|
||||
|
||||
## Unlink
|
||||
npm unlink harbor-ui
|
||||
|
||||
#Copy built js to the static folder
|
||||
cp ./dist/build.min.js ../ui/static/
|
||||
|
||||
cp -r ./src/i18n/ ../ui/static/
|
||||
cp ./src/styles.css ../ui/static/
|
||||
cp -r ./src/images/ ../ui/static/
|
||||
cp ./src/setting.json ../ui/static/
|
||||
|
||||
cp ./node_modules/clarity-icons/clarity-icons.min.css ../ui/static/
|
||||
cp ./node_modules/mutationobserver-shim/dist/mutationobserver.min.js ../ui/static/
|
||||
cp ./node_modules/@webcomponents/custom-elements/custom-elements.min.js ../ui/static/
|
||||
cp ./node_modules/clarity-icons/clarity-icons.min.js ../ui/static/
|
||||
cp ./node_modules/clarity-ui/clarity-ui.min.css ../ui/static/
|
||||
cp -r ./node_modules/clarity-icons/shapes/ ../ui/static/
|
||||
|
||||
cp ./node_modules/prismjs/themes/prism-solarizedlight.css ../ui/static/
|
||||
cp ./node_modules/marked/lib/marked.js ../ui/static/
|
||||
cp ./node_modules/prismjs/prism.js ../ui/static/
|
||||
cp ./node_modules/prismjs/components/prism-yaml.min.js ../ui/static/
|
@ -1,13 +0,0 @@
|
||||
<!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>
|
@ -110,6 +110,18 @@ services:
|
||||
options:
|
||||
syslog-address: "tcp://127.0.0.1:1514"
|
||||
tag: "ui"
|
||||
portal:
|
||||
image: goharbor/harbor-portal:__version__
|
||||
container_name: harbor-portal
|
||||
restart: always
|
||||
networks:
|
||||
- harbor
|
||||
logging:
|
||||
driver: "syslog"
|
||||
options:
|
||||
syslog-address: "tcp://127.0.0.1:1514"
|
||||
tag: "portal"
|
||||
|
||||
jobservice:
|
||||
image: goharbor/harbor-jobservice:__version__
|
||||
container_name: harbor-jobservice
|
||||
@ -146,7 +158,7 @@ services:
|
||||
syslog-address: "tcp://127.0.0.1:1514"
|
||||
tag: "redis"
|
||||
proxy:
|
||||
image: goharbor/nginx-photon:__nginx_version__
|
||||
image: goharbor/nginx-photon:__version__
|
||||
container_name: nginx
|
||||
restart: always
|
||||
volumes:
|
||||
@ -161,6 +173,7 @@ services:
|
||||
- postgresql
|
||||
- registry
|
||||
- ui
|
||||
- portal
|
||||
- log
|
||||
logging:
|
||||
driver: "syslog"
|
||||
|
@ -39,6 +39,10 @@ DOCKERFILEPATH_ADMINSERVER=$(DOCKERFILEPATH)/adminserver
|
||||
DOCKERFILENAME_ADMINSERVER=Dockerfile
|
||||
DOCKERIMAGENAME_ADMINSERVER=goharbor/harbor-adminserver
|
||||
|
||||
DOCKERFILEPATH_PORTAL=$(DOCKERFILEPATH)/portal
|
||||
DOCKERFILENAME_PORTAL=Dockerfile
|
||||
DOCKERIMAGENAME_PORTAL=goharbor/harbor-portal
|
||||
|
||||
DOCKERFILEPATH_UI=$(DOCKERFILEPATH)/ui
|
||||
DOCKERFILENAME_UI=Dockerfile
|
||||
DOCKERIMAGENAME_UI=goharbor/harbor-ui
|
||||
@ -106,6 +110,11 @@ _build_adminserver:
|
||||
@$(DOCKERBUILD) -f $(DOCKERFILEPATH_ADMINSERVER)/$(DOCKERFILENAME_ADMINSERVER) -t $(DOCKERIMAGENAME_ADMINSERVER):$(VERSIONTAG) .
|
||||
@echo "Done."
|
||||
|
||||
_build_portal:
|
||||
@echo "building portal container for photon..."
|
||||
$(DOCKERBUILD) -f $(DOCKERFILEPATH_PORTAL)/$(DOCKERFILENAME_PORTAL) -t $(DOCKERIMAGENAME_PORTAL):$(VERSIONTAG) .
|
||||
@echo "Done."
|
||||
|
||||
_build_ui:
|
||||
@echo "building ui container for photon..."
|
||||
@$(DOCKERBUILD) -f $(DOCKERFILEPATH_UI)/$(DOCKERFILENAME_UI) -t $(DOCKERIMAGENAME_UI):$(VERSIONTAG) .
|
||||
@ -203,11 +212,12 @@ define _get_binary
|
||||
$(WGET) --timeout 30 --no-check-certificate $1 -O $2
|
||||
endef
|
||||
|
||||
build: _build_db _build_adminserver _build_ui _build_jobservice _build_log _build_nginx _build_registry _build_registryctl _build_notary _build_clair _build_redis _build_chart_server
|
||||
build: _build_db _build_adminserver _build_portal _build_ui _build_jobservice _build_log _build_nginx _build_registry _build_registryctl _build_notary _build_clair _build_redis _build_migrator _build_chart_server
|
||||
|
||||
cleanimage:
|
||||
@echo "cleaning image for photon..."
|
||||
- $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_ADMINSERVER):$(VERSIONTAG)
|
||||
- $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_PORTAL):$(VERSIONTAG)
|
||||
- $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_UI):$(VERSIONTAG)
|
||||
- $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_JOBSERVICE):$(VERSIONTAG)
|
||||
- $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_LOG):$(VERSIONTAG)
|
||||
|
35
make/photon/portal/Dockerfile
Normal file
35
make/photon/portal/Dockerfile
Normal file
@ -0,0 +1,35 @@
|
||||
FROM node:10.7.0
|
||||
|
||||
RUN mkdir -p /portal_src
|
||||
RUN mkdir -p /build_dir
|
||||
|
||||
COPY make/photon/portal/entrypoint.sh /
|
||||
COPY src/portal /portal_src
|
||||
|
||||
WORKDIR /portal_src
|
||||
|
||||
RUN npm install && \
|
||||
chmod u+x /entrypoint.sh
|
||||
RUN /entrypoint.sh
|
||||
VOLUME ["/portal_src"]
|
||||
|
||||
|
||||
FROM photon:1.0
|
||||
|
||||
RUN tdnf distro-sync -y \
|
||||
&& tdnf install -y nginx >> /dev/null \
|
||||
&& ln -sf /dev/stdout /var/log/nginx/access.log \
|
||||
&& ln -sf /dev/stderr /var/log/nginx/error.log \
|
||||
&& tdnf clean all
|
||||
|
||||
EXPOSE 80
|
||||
VOLUME /var/cache/nginx /var/log/nginx /run
|
||||
|
||||
COPY --from=0 /build_dir/dist /usr/share/nginx/html
|
||||
COPY make/photon/portal/nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
STOPSIGNAL SIGQUIT
|
||||
|
||||
HEALTHCHECK CMD curl --fail -s http://127.0.0.1 || exit 1
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
18
make/photon/portal/entrypoint.sh
Normal file
18
make/photon/portal/entrypoint.sh
Normal file
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
cd /build_dir
|
||||
cp -r /portal_src/* .
|
||||
ls -la
|
||||
|
||||
cat ./package.json
|
||||
npm install
|
||||
|
||||
## Build harbor-ui and link it
|
||||
rm -rf /build_dir/lib/dist
|
||||
npm run build_lib
|
||||
chmod -R +xr /build_dir/lib/dist
|
||||
npm run link_lib
|
||||
|
||||
## Build production
|
||||
npm run release
|
26
make/photon/portal/nginx.conf
Normal file
26
make/photon/portal/nginx.conf
Normal file
@ -0,0 +1,26 @@
|
||||
|
||||
worker_processes 1;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
include /etc/nginx/mime.types;
|
||||
|
||||
gzip on;
|
||||
gzip_min_length 1000;
|
||||
gzip_proxied expired no-cache no-store private auth;
|
||||
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
}
|
195
src/portal/angular.json
Normal file
195
src/portal/angular.json
Normal file
@ -0,0 +1,195 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"harbor-portal": {
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"projectType": "application",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"tsConfig": "src/tsconfig.app.json",
|
||||
"assets": [
|
||||
"src/images",
|
||||
"src/favicon.ico",
|
||||
"src/setting.json",
|
||||
"src/i18n"
|
||||
],
|
||||
"styles": [
|
||||
"node_modules/@clr/icons/clr-icons.min.css",
|
||||
"node_modules/@clr/ui/clr-ui.min.css",
|
||||
"node_modules/prismjs/themes/prism-solarizedlight.css",
|
||||
"src/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/@clr/icons/clr-icons.min.js",
|
||||
"node_modules/web-animations-js/web-animations.min.js",
|
||||
"node_modules/marked/lib/marked.js",
|
||||
"node_modules/prismjs/prism.js",
|
||||
"node_modules/prismjs/components/prism-yaml.min.js"
|
||||
]
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"aot": true,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "harbor-portal:build"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "harbor-portal:build:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "harbor-portal:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"tsConfig": "src/tsconfig.spec.json",
|
||||
"main": "src/test.ts",
|
||||
"karmaConfig": "./karma.conf.js",
|
||||
"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/@clr/icons/clr-icons.min.js",
|
||||
"node_modules/web-animations-js/web-animations.min.js",
|
||||
"node_modules/marked/lib/marked.js",
|
||||
"node_modules/prismjs/prism.js",
|
||||
"node_modules/prismjs/components/prism-yaml.min.js"
|
||||
],
|
||||
"styles": [
|
||||
"node_modules/@clr/icons/clr-icons.min.css",
|
||||
"node_modules/@clr/ui/clr-ui.min.css",
|
||||
"node_modules/prismjs/themes/prism-solarizedlight.css",
|
||||
"src/styles.css"
|
||||
],
|
||||
"assets": [
|
||||
"src/images",
|
||||
"src/favicon.ico",
|
||||
"src/setting.json",
|
||||
"src/i18n"
|
||||
]
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"src/tsconfig.app.json",
|
||||
"src/tsconfig.spec.json",
|
||||
"lib/tsconfig.lib.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
],
|
||||
"fix": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"harbor-portal-e2e": {
|
||||
"root": "e2e",
|
||||
"sourceRoot": "e2e",
|
||||
"projectType": "application",
|
||||
"architect": {
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "./protractor.config.js",
|
||||
"devServerTarget": "harbor-portal:serve"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [],
|
||||
"exclude": []
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"lib": {
|
||||
"root": "lib",
|
||||
"sourceRoot": "lib/src",
|
||||
"projectType": "library",
|
||||
"prefix": "enl",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "lib/tsconfig.lib.json",
|
||||
"project": "lib/ng-package.json"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"project": "lib/ng-package.prod.json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "lib/src/test.ts",
|
||||
"tsConfig": "lib/tsconfig.lib.json",
|
||||
"karmaConfig": "lib/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"lib/tsconfig.lib.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultProject": "harbor-portal",
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"prefix": "app",
|
||||
"styleext": "scss"
|
||||
},
|
||||
"@schematics/angular:directive": {
|
||||
"prefix": "app"
|
||||
}
|
||||
}
|
||||
}
|
11
src/portal/browserslist
Normal file
11
src/portal/browserslist
Normal file
@ -0,0 +1,11 @@
|
||||
# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
#
|
||||
# For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed
|
||||
|
||||
> 0.5%
|
||||
last 2 versions
|
||||
Firefox ESR
|
||||
not dead
|
||||
not IE 9-11
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
import {ClaritySeedAppHome} from './app.po';
|
||||
|
||||
fdescribe('clarity-seed app', function () {
|
||||
fdescribe('harbor-portal app', function () {
|
||||
|
||||
let expectedMsg: string = 'This is a Clarity seed application. This is the default page that loads for the application.';
|
||||
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.3 KiB |
@ -3,34 +3,31 @@
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular/cli'],
|
||||
basePath: '/',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-mocha-reporter'),
|
||||
require('karma-remap-istanbul'),
|
||||
require('@angular/cli/plugins/karma')
|
||||
require('@angular-devkit/build-angular/plugins/karma')
|
||||
],
|
||||
files: [
|
||||
{pattern: './src/test.ts', watched: false}
|
||||
],
|
||||
preprocessors: {
|
||||
'./src/test.ts': ['@angular/cli']
|
||||
|
||||
},
|
||||
mime: {
|
||||
'text/x-typescript': ['ts', 'tsx']
|
||||
},
|
||||
remapIstanbulReporter: {
|
||||
reports: {
|
||||
dir: require('path').join(__dirname, 'coverage'), 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'],
|
||||
@ -47,4 +44,4 @@ module.exports = function (config) {
|
||||
},
|
||||
singleRun: true
|
||||
});
|
||||
};
|
||||
};
|
@ -11,9 +11,9 @@ Wrap the following Harbor UI components into a sharable library and published as
|
||||
* Vulnerability scanning result bar chart and list view (Embedded in tag management view)
|
||||
* Registry(Harbor) related configuration options
|
||||
|
||||
The Harbor UI library is built on **[Angular ](https://angular.io/)** 4.x and **[Clarity ](https://vmware.github.io/clarity/)** 0.9.x .
|
||||
The Harbor UI library is built on **[Angular ](https://angular.io/)** 6.x and **[Clarity ](https://vmware.github.io/clarity/)** 0.12.x .
|
||||
|
||||
The library is published to the public npm repository with name **[harbor-ui](https://www.npmjs.com/package/harbor-ui)**.
|
||||
The library is published to the public npm repository with name **[@harbor/ui](https://www.npmjs.com/package/@harbor/ui)**.
|
||||
|
||||
## Build & Test
|
||||
Build library with command:
|
||||
@ -28,7 +28,7 @@ npm run test
|
||||
|
||||
Install the package
|
||||
```
|
||||
npm install harbor-ui[@version]
|
||||
npm install @harbor/ui[@version]
|
||||
```
|
||||
|
||||
## Usage
|
||||
@ -36,16 +36,16 @@ npm install harbor-ui[@version]
|
||||
|
||||
Execute install command to add dependency to package.json
|
||||
```
|
||||
npm install harbor-ui --save
|
||||
npm install @harbor/ui
|
||||
|
||||
//OR
|
||||
npm install harbor-ui@0.2.x --save
|
||||
npm install @harbor/ui@1.0.0
|
||||
```
|
||||
The latest version of the library will be installed.
|
||||
|
||||
**Import the library module into the root Angular module**
|
||||
```
|
||||
import { HarborLibraryModule } from 'harbor-ui';
|
||||
import { HarborLibraryModule } from '@harbor/ui';
|
||||
|
||||
@NgModule({
|
||||
declarations: [...],
|
||||
@ -252,7 +252,7 @@ This component provides some options for registry(Harbor) related configurations
|
||||
All the related configurations are defined in the **HarborModuleConfig** interface.
|
||||
|
||||
**1. config**
|
||||
The base configuration for the module. Mainly used to define the relevant endpoints of services which are in charge of retrieving data from backend APIs. It's a 'OpaqueToken' and defined by 'IServiceConfig' interface. If **config** is not set, the default value will be used.
|
||||
The base configuration for the module. Mainly used to define the relevant endpoints of services which are in charge of retrieving data from backend APIs. It's a 'InjectionToken' and defined by 'IServiceConfig' interface. If **config** is not set, the default value will be used.
|
||||
```
|
||||
export const DefaultServiceConfig: IServiceConfig = {
|
||||
systemInfoEndpoint: "/api/systeminfo",
|
13
src/portal/lib/ng-package.json
Normal file
13
src/portal/lib/ng-package.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"$schema": "../node_modules/ng-packagr/ng-package.schema.json",
|
||||
"dest": "./dist",
|
||||
"deleteDestPath": false,
|
||||
"lib": {
|
||||
"entryFile": "index.ts",
|
||||
"externals": {
|
||||
"@ngx-translate/core": "ngx-translate-core",
|
||||
"@ngx-translate/core/index": "ngx-translate-core",
|
||||
"ngx-markdown": "ngx-markdown"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"$schema": "./node_modules/ng-packagr/ng-package.schema.json",
|
||||
"$schema": "../node_modules/ng-packagr/ng-package.schema.json",
|
||||
"dest": "./dist",
|
||||
"lib": {
|
||||
"entryFile": "index.ts",
|
||||
"externals": {
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "harbor-ui",
|
||||
"version": "0.7.19-dev.9",
|
||||
"description": "Harbor shared UI components based on Clarity and Angular4",
|
||||
"author": "VMware",
|
||||
"name": "@harbor/ui",
|
||||
"version": "1.0.0-rc2",
|
||||
"description": "Harbor shared UI components based on Clarity and Angular6",
|
||||
"author": "CNCF",
|
||||
"module": "index.js",
|
||||
"main": "bundles/harborui.umd.min.js",
|
||||
"jsnext:main": "index.js",
|
||||
@ -10,7 +10,7 @@
|
||||
"keywords": [
|
||||
"Harbor",
|
||||
"Clarity",
|
||||
"Angular4"
|
||||
"Angular6"
|
||||
],
|
||||
"license": "Apache 2.0",
|
||||
"repository": {
|
||||
@ -19,29 +19,31 @@
|
||||
},
|
||||
"homepage": "https://github.com/vmware/harbor#readme",
|
||||
"peerDependencies": {
|
||||
"@angular/animations": "^4.3.0",
|
||||
"@angular/common": "^4.3.0",
|
||||
"@angular/compiler": "^4.3.0",
|
||||
"@angular/core": "^4.3.0",
|
||||
"@angular/forms": "^4.3.0",
|
||||
"@angular/http": "^4.3.0",
|
||||
"@angular/platform-browser": "^4.3.0",
|
||||
"@angular/platform-browser-dynamic": "^4.3.0",
|
||||
"@angular/router": "^4.3.0",
|
||||
"@angular/animations": "^6.0.0",
|
||||
"@angular/common": "^6.0.0",
|
||||
"@angular/compiler": "^6.0.0",
|
||||
"@angular/core": "^6.0.0",
|
||||
"@angular/forms": "^6.0.0",
|
||||
"@angular/http": "^6.0.0",
|
||||
"@angular/platform-browser": "^6.0.0",
|
||||
"@angular/platform-browser-dynamic": "^6.0.0",
|
||||
"@angular/router": "^6.0.0",
|
||||
"@ngx-translate/core": "^6.0.0",
|
||||
"@ngx-translate/http-loader": "0.0.3",
|
||||
"@webcomponents/custom-elements": "^1.0.0",
|
||||
"clarity-angular": "^0.10.17",
|
||||
"clarity-icons": "^0.10.17",
|
||||
"clarity-ui": "^0.10.17",
|
||||
"@clr/angular": "^0.12.0",
|
||||
"@clr/ui": "^0.12.0",
|
||||
"@clr/icons": "^0.12.0",
|
||||
"core-js": "^2.4.1",
|
||||
"intl": "^1.2.5",
|
||||
"mutationobserver-shim": "^0.3.2",
|
||||
"ngx-cookie": "^1.0.0",
|
||||
"ngx-markdown": "^1.5.1",
|
||||
"rxjs": "^5.0.1",
|
||||
"rxjs": "^6.2.2",
|
||||
"ts-helpers": "^1.1.1",
|
||||
"web-animations-js": "^2.2.1",
|
||||
"zone.js": "^0.8.4"
|
||||
"zone.js": "^0.8.4",
|
||||
"tslib": "^1.9.0"
|
||||
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@ 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 { ClarityModule } from '@clr/angular';
|
||||
import { HarborLibraryModule } from './harbor-library.module';
|
||||
|
||||
@NgModule({
|
@ -12,9 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
import { Observable } from "rxjs/Observable";
|
||||
import { Observable, Subject} from "rxjs";
|
||||
|
||||
@Injectable()
|
||||
export class ChannelService {
|
@ -56,9 +56,9 @@ export class ConfirmationDialogComponent {
|
||||
colorChange(list: BatchInfo) {
|
||||
if (!list.loading && !list.errorState) {
|
||||
return 'green';
|
||||
}else if (!list.loading && list.errorState) {
|
||||
} else if (!list.loading && list.errorState) {
|
||||
return 'red';
|
||||
}else {
|
||||
} else {
|
||||
return '#666';
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ import {
|
||||
OnDestroy
|
||||
} from "@angular/core";
|
||||
import { NgForm } from "@angular/forms";
|
||||
import { Subscription } from "rxjs/Subscription";
|
||||
import { Subscription } from "rxjs";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
|
||||
import { EndpointService } from "../service/endpoint.service";
|
@ -30,7 +30,8 @@ import { toPromise, clone, compareValue } from "../utils";
|
||||
import { LabelService } from "../service/label.service";
|
||||
import { ErrorHandler } from "../error-handler/error-handler";
|
||||
import { NgForm } from "@angular/forms";
|
||||
import { Subject } from "rxjs/Subject";
|
||||
import { Subject } from "rxjs";
|
||||
import { debounceTime } from "rxjs/operators";
|
||||
import { LabelColor } from "../shared/shared.const";
|
||||
|
||||
@Component({
|
||||
@ -64,7 +65,7 @@ export class CreateEditLabelComponent implements OnInit, OnDestroy {
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.nameChecker.debounceTime(500).subscribe((name: string) => {
|
||||
this.nameChecker.pipe(debounceTime(500)).subscribe((name: string) => {
|
||||
toPromise<Label[]>(
|
||||
this.labelService.getLabels(this.scope, this.projectId, name)
|
||||
)
|
@ -58,7 +58,7 @@
|
||||
<option *ngFor="let opt of filterListData[i]?.options;" value="{{opt}}">{{opt}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<label aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-bottom-left" [class.invalid]='(ruleForm.controls.filters.controls[i].controls.value.dirty || ruleForm.controls.filters.controls[i].controls.value.touched) && ruleForm.controls.filters.controls[i].controls.value.invalid'>
|
||||
<label aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-bottom-left" [class.invalid]='(filter.value.dirty || filter.value.touched) && filter.value.invalid'>
|
||||
<input type="text" #filterValue required size="14" formControlName="value" [attr.disabled]="(filterListData[i]?.name=='label') ?'' : null">
|
||||
<span class="tooltip-content">{{'TOOLTIP.EMPTY' | translate}}</span>
|
||||
</label>
|
||||
@ -68,7 +68,7 @@
|
||||
<clr-icon shape="warning-standard" class="is-solid is-warning" size="14" style="margin-left: -15px;" [hidden]="!deletedLabelCount || !(filterListData[i]?.name=='label')"></clr-icon>
|
||||
<clr-icon shape="times-circle" class="is-solid" (click)="deleteFilter(i)"></clr-icon>
|
||||
<div *ngIf="!withAdmiral">
|
||||
<hbr-filter-label [projectId]="ruleForm.controls.projects.controls[0]?.value.project_id" [selectedLabelInfo]="filterLabelInfo"
|
||||
<hbr-filter-label [projectId]="projectId" [selectedLabelInfo]="filterLabelInfo"
|
||||
[isOpen]="filterListData[i].isOpen" (selectedLabels)="selectedLabelList($event, i)" (closePanelEvent)="filterListData[i].isOpen = false"></hbr-filter-label>
|
||||
</div>
|
||||
</div>
|
@ -22,8 +22,8 @@ import {
|
||||
Output
|
||||
} from "@angular/core";
|
||||
import { Filter, ReplicationRule, Endpoint, Label } from "../service/interface";
|
||||
import { Subject } from "rxjs/Subject";
|
||||
import { Subscription } from "rxjs/Subscription";
|
||||
import { Subject , Subscription } from "rxjs";
|
||||
import {debounceTime, distinctUntilChanged} from "rxjs/operators";
|
||||
import { FormArray, FormBuilder, FormGroup, Validators } from "@angular/forms";
|
||||
import { clone, compareValue, isEmptyObject, toPromise } from "../utils";
|
||||
import { InlineAlertComponent } from "../inline-alert/inline-alert.component";
|
||||
@ -156,8 +156,8 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
this.nameChecker
|
||||
.debounceTime(300)
|
||||
.distinctUntilChanged()
|
||||
.pipe(debounceTime(300))
|
||||
.pipe(distinctUntilChanged())
|
||||
.subscribe((ruleName: string) => {
|
||||
let cont = this.ruleForm.controls["name"];
|
||||
if (cont) {
|
||||
@ -184,8 +184,8 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
|
||||
this.proNameChecker
|
||||
.debounceTime(500)
|
||||
.distinctUntilChanged()
|
||||
.pipe(debounceTime(500))
|
||||
.pipe(distinctUntilChanged())
|
||||
.subscribe((resp: string) => {
|
||||
let name = this.ruleForm.controls["projects"].value[0].name;
|
||||
this.noProjectInfo = "";
|
||||
@ -622,7 +622,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
||||
} else {
|
||||
controlArray.controls[index].get('value').setValue('');
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// store filter label info
|
||||
@ -705,7 +705,7 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
|
||||
let copyRuleForm: ReplicationRule = this.ruleForm.value;
|
||||
copyRuleForm.trigger = this.setTriggerVaule(copyRuleForm.trigger);
|
||||
// rewrite key name of label when filer contain labels.
|
||||
if (copyRuleForm.filters) { this.setFilterLabelVal(copyRuleForm.filters); };
|
||||
if (copyRuleForm.filters) { this.setFilterLabelVal(copyRuleForm.filters); }
|
||||
|
||||
if (this.policyId < 0) {
|
||||
this.repService
|
@ -3,7 +3,8 @@ import {LabelService} from "../service/label.service";
|
||||
import {toPromise} from "../utils";
|
||||
import {Label} from "../service/interface";
|
||||
import {ErrorHandler} from "../error-handler/error-handler";
|
||||
import {Subject} from "rxjs/Subject";
|
||||
import {Subject} from "rxjs";
|
||||
import {debounceTime, distinctUntilChanged} from "rxjs/operators";
|
||||
|
||||
export interface LabelState {
|
||||
iconsShow: boolean;
|
||||
@ -43,8 +44,8 @@ export class FilterLabelComponent implements OnInit, OnChanges {
|
||||
});
|
||||
|
||||
this.labelNameFilter
|
||||
.debounceTime(500)
|
||||
.distinctUntilChanged()
|
||||
.pipe(debounceTime(500))
|
||||
.pipe(distinctUntilChanged())
|
||||
.subscribe((name: string) => {
|
||||
if (this.filterLabelName.length) {
|
||||
|
||||
@ -95,7 +96,7 @@ export class FilterLabelComponent implements OnInit, OnChanges {
|
||||
handleInputFilter(): void {
|
||||
if (this.filterLabelName.length) {
|
||||
this.labelNameFilter.next(this.filterLabelName);
|
||||
}else {
|
||||
} else {
|
||||
this.labelLists.every(data => data.show = true);
|
||||
}
|
||||
}
|
@ -19,11 +19,10 @@ import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef
|
||||
} from "@angular/core";
|
||||
import { Subscription } from "rxjs/Subscription";
|
||||
import { Observable } from "rxjs/Observable";
|
||||
import "rxjs/add/observable/forkJoin";
|
||||
import { Subscription} from "rxjs";
|
||||
import {forkJoin} from "rxjs";
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
import { Comparator } from "clarity-angular";
|
||||
import { Comparator } from "@clr/angular";
|
||||
|
||||
import { Endpoint } from "../service/interface";
|
||||
import { EndpointService } from "../service/endpoint.service";
|
||||
@ -211,7 +210,7 @@ export class EndpointComponent implements OnInit, OnDestroy {
|
||||
}).catch(
|
||||
error => {
|
||||
if (error && error.status === 412) {
|
||||
Observable.forkJoin(this.translateService.get('BATCH.DELETED_FAILURE'),
|
||||
forkJoin(this.translateService.get('BATCH.DELETED_FAILURE'),
|
||||
this.translateService.get('DESTINATION.FAILED_TO_DELETE_TARGET_IN_USED')).subscribe(res => {
|
||||
operateChanges(operMessage, OperationState.failure, res[1]);
|
||||
});
|
@ -3,16 +3,16 @@ import { Injectable } from "@angular/core";
|
||||
/**
|
||||
* Declare interface for error handling
|
||||
*
|
||||
* @export
|
||||
**
|
||||
* @abstract
|
||||
* @class ErrorHandler
|
||||
* class ErrorHandler
|
||||
*/
|
||||
export abstract class ErrorHandler {
|
||||
/**
|
||||
* Send message with error level
|
||||
*
|
||||
* @abstract
|
||||
* @param {*} error
|
||||
* ** deprecated param {*} error
|
||||
*
|
||||
* @memberOf ErrorHandler
|
||||
*/
|
||||
@ -22,7 +22,7 @@ export abstract class ErrorHandler {
|
||||
* Send message with warning level
|
||||
*
|
||||
* @abstract
|
||||
* @param {*} warning
|
||||
* ** deprecated param {*} warning
|
||||
*
|
||||
* @memberOf ErrorHandler
|
||||
*/
|
||||
@ -32,7 +32,7 @@ export abstract class ErrorHandler {
|
||||
* Send message with info level
|
||||
*
|
||||
* @abstract
|
||||
* @param {*} info
|
||||
* ** deprecated param {*} info
|
||||
*
|
||||
* @memberOf ErrorHandler
|
||||
*/
|
||||
@ -42,7 +42,7 @@ export abstract class ErrorHandler {
|
||||
* Handle log message
|
||||
*
|
||||
* @abstract
|
||||
* @param {*} log
|
||||
* ** deprecated param {*} log
|
||||
*
|
||||
* @memberOf ErrorHandler
|
||||
*/
|
@ -12,10 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
import { Component, Input, Output, OnInit, EventEmitter } from "@angular/core";
|
||||
import { Subject } from "rxjs/Subject";
|
||||
|
||||
import "rxjs/add/operator/debounceTime";
|
||||
import "rxjs/add/operator/distinctUntilChanged";
|
||||
import { Subject } from "rxjs";
|
||||
import { debounceTime } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: "hbr-filter",
|
||||
@ -40,7 +38,7 @@ export class FilterComponent implements OnInit {
|
||||
|
||||
ngOnInit(): void {
|
||||
this.filterTerms
|
||||
.debounceTime(500)
|
||||
.pipe(debounceTime(500))
|
||||
.subscribe(terms => {
|
||||
this.filterEvt.emit(terms);
|
||||
});
|
@ -2,7 +2,7 @@
|
||||
<div class="items" [ngStyle]="itemsHolderStyle" #itemsHolder >
|
||||
<span *ngFor="let item of items;let i = index; trackBy:trackByFn" class='card-item' [ngStyle]="cardStyles[i]" #cardItem
|
||||
(mouseenter)='onCardEnter(i)' (mouseleave)='onCardLeave(i)'>
|
||||
<ng-template [ngTemplateOutlet]="gridItemTmpl" [ngOutletContext]="{item: item}">
|
||||
<ng-template [ngTemplateOutlet]="gridItemTmpl" [ngTemplateOutletContext]="{item: item}">
|
||||
</ng-template>
|
||||
</span>
|
||||
<span *ngIf="items.length === 0 && !loading" class="content-empty">
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user