This is an automated email from the ASF dual-hosted git repository.

imbajin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hugegraph-computer.git


The following commit(s) were added to refs/heads/master by this push:
     new 60bb1b65 fix(vermeer): add Web UI build pipeline (#348)
60bb1b65 is described below

commit 60bb1b659cdd23089fd37ca542a18e68d9cf8225
Author: lokidundun <[email protected]>
AuthorDate: Tue Jun 2 15:06:49 2026 +0800

    fix(vermeer): add Web UI build pipeline (#348)
    
    * add license
    * Add release metadata to Docker image and add Vermeer CI workflow
---
 .github/workflows/vermeer-ci.yml                   | 109 +++++++++
 README.md                                          |   2 +-
 vermeer/.dockerignore                              |  22 +-
 vermeer/.gitignore                                 |   8 +
 vermeer/Dockerfile                                 |   3 +
 vermeer/Makefile                                   |  25 ++-
 vermeer/README.md                                  |  49 ++++-
 vermeer/asset/asset.go                             |   2 +-
 vermeer/asset/asset_dev_ui.go                      |   2 +-
 vermeer/build.sh                                   |  14 +-
 vermeer/config/worker.ini                          |   5 +-
 vermeer/release-docs/LICENSE                       | 244 +++++++++++++++++++++
 vermeer/release-docs/NOTICE                        |  44 ++++
 .../release-docs/licenses/LICENSE-bootstrap.txt    |  22 ++
 .../licenses/LICENSE-bootstrap4-glyphicons.txt     | 201 +++++++++++++++++
 .../release-docs/licenses/LICENSE-fontawesome.txt  | 110 ++++++++++
 .../release-docs/licenses/LICENSE-glyphicons.txt   |  26 +++
 vermeer/release-docs/licenses/LICENSE-jquery.txt   |  22 ++
 vermeer/scripts/download_ui_assets.sh              | 177 +++++++++++++++
 vermeer/ui/package.json                            |  10 +
 vermeer/ui/ui/lib/functions.js                     | 187 ++++++++++++++++
 vermeer/ui/ui/lib/vermeer.css                      |  53 +++++
 22 files changed, 1315 insertions(+), 22 deletions(-)

diff --git a/.github/workflows/vermeer-ci.yml b/.github/workflows/vermeer-ci.yml
new file mode 100644
index 00000000..777ecfce
--- /dev/null
+++ b/.github/workflows/vermeer-ci.yml
@@ -0,0 +1,109 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+name: "Vermeer CI"
+
+on:
+  push:
+    branches:
+      - master
+      - /^release-.*$/
+    paths:
+      - vermeer/**
+      - .github/workflows/vermeer-ci.yml
+  pull_request:
+    paths:
+      - vermeer/**
+      - .github/workflows/vermeer-ci.yml
+
+defaults:
+  run:
+    working-directory: vermeer
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: true
+
+jobs:
+  vermeer-build:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+
+      - name: Set up Go
+        uses: actions/setup-go@v5
+        with:
+          go-version: '1.23'
+
+      - name: Set up Node.js
+        uses: actions/setup-node@v4
+        with:
+          node-version: '20'
+
+      - name: Cache Go modules
+        uses: actions/cache@v4
+        with:
+          path: |
+            ~/go/pkg/mod
+            ~/.cache/go-build
+          key: ${{ runner.os }}-go-${{ hashFiles('vermeer/go.sum') }}
+          restore-keys: ${{ runner.os }}-go-
+
+      - name: Download Go modules
+        run: go mod download
+
+      - name: Download UI assets
+        run: ./scripts/download_ui_assets.sh
+
+      - name: Generate embedded assets
+        run: cd asset && go generate
+
+      - name: Build
+        run: CGO_ENABLED=0 go build -o vermeer
+
+      - name: Verify binary exists
+        run: test -x vermeer
+
+      - name: Verify release metadata exists
+        run: |
+          test -f release-docs/LICENSE
+          test -f release-docs/NOTICE
+          test -d release-docs/licenses
+
+  vermeer-docker:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+
+      - name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v3
+
+      - name: Build Docker image (dry-run)
+        uses: docker/build-push-action@v6
+        with:
+          context: vermeer
+          push: false
+          tags: vermeer:ci-check
+          cache-from: type=gha
+          cache-to: type=gha,mode=max
+
+      - name: Verify release metadata in image
+        run: |
+          docker run --rm --entrypoint test vermeer:ci-check -f 
/go/bin/release-docs/LICENSE
+          docker run --rm --entrypoint test vermeer:ci-check -f 
/go/bin/release-docs/NOTICE
+          docker run --rm --entrypoint test vermeer:ci-check -d 
/go/bin/release-docs/licenses
diff --git a/README.md b/README.md
index c9fda699..2f742e16 100644
--- a/README.md
+++ b/README.md
@@ -146,7 +146,7 @@ For quick start and single-machine deployments, we 
recommend **Vermeer**:
 # Pull the image
 docker pull hugegraph/vermeer:latest
 
-# Change config path in docker-compose.yml
+# Change config path in docker-compose.yaml
 volumes:
       - ~/:/go/bin/config # Change here to your actual config path, e.g., 
vermeer/config
 
diff --git a/vermeer/.dockerignore b/vermeer/.dockerignore
index 6e8f887b..697abfb0 100644
--- a/vermeer/.dockerignore
+++ b/vermeer/.dockerignore
@@ -14,6 +14,22 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-*data*
-*test*
-*.git*
\ No newline at end of file
+.git/
+.gitignore
+.gitattributes
+test/
+vermeer_test.go
+vermeer_test.sh
+vermeer_data/
+asset/assets_vfsdata.go
+ui/node_modules/
+ui/package-lock.json
+ui/ui/lib/bootstrap-4.3.1-dist/
+ui/ui/lib/bootstrap4-glyphicons/
+ui/ui/lib/jquery-3.5.1.min.js
+ui/ui/lib/jquery-license
+_tmp_extractor/
+tools/supervisord/*/supervisord
+tools/protoc/*/protoc
+tools/protoc/*/bin/
+tools/protoc/*/include/
\ No newline at end of file
diff --git a/vermeer/.gitignore b/vermeer/.gitignore
index 8fb775a2..9907f62d 100644
--- a/vermeer/.gitignore
+++ b/vermeer/.gitignore
@@ -99,6 +99,14 @@ tools/protoc/*/include/
 ######################
 asset/assets_vfsdata.go
 
+# UI dependencies (downloaded via scripts/download_ui_assets.sh) #
+######################
+ui/node_modules/
+ui/package-lock.json
+ui/ui/lib/*
+!ui/ui/lib/functions.js
+!ui/ui/lib/vermeer.css
+
 # AI assistant specific files (we only maintain AGENTS.md) #
 ######################
 CLAUDE.md
diff --git a/vermeer/Dockerfile b/vermeer/Dockerfile
index 75a65bf6..44da2502 100644
--- a/vermeer/Dockerfile
+++ b/vermeer/Dockerfile
@@ -15,9 +15,11 @@
 # limitations under the License.
 #
 FROM golang:1.23-alpine AS builder
+RUN apk add --no-cache npm bash curl
 COPY ./ /src/
 WORKDIR /src/
 ENV CGO_ENABLED="0"
+RUN ./scripts/download_ui_assets.sh
 RUN cd asset && go generate
 RUN go build -o /go/bin/app
 
@@ -25,6 +27,7 @@ FROM alpine
 EXPOSE 8080
 COPY --from=builder /go/bin/app /go/bin/app
 COPY --from=builder /src/config/ /go/bin/config/
+COPY --from=builder /src/release-docs/ /go/bin/release-docs/
 COPY --from=builder /usr/local/go/lib/time/zoneinfo.zip /
 ENV TZ=Asia/Shanghai
 ENV ZONEINFO=/zoneinfo.zip
diff --git a/vermeer/Makefile b/vermeer/Makefile
index ba9cb73f..1bc765c3 100644
--- a/vermeer/Makefile
+++ b/vermeer/Makefile
@@ -15,13 +15,13 @@
 # limitations under the License.
 #
 
-.PHONY: all init download-binaries generate-assets build clean help
+.PHONY: all init download-binaries download-ui-assets generate-assets build 
clean help
 
 # Default target
 all: generate-assets build
 
 # Initialize project (first time setup)
-init: download-binaries
+init: download-binaries download-ui-assets
        @echo "Installing Go dependencies..."
        go mod download
        @echo "Project initialized successfully!"
@@ -31,8 +31,17 @@ download-binaries:
        @echo "Downloading binary dependencies..."
        @./scripts/download_binaries.sh || (echo "Failed to download binaries" 
&& exit 1)
 
+# Download UI assets (jQuery, Bootstrap, Glyphicons)
+download-ui-assets:
+       @if [ ! -f "ui/ui/lib/.downloaded" ]; then \
+               echo "Downloading UI assets..."; \
+               ./scripts/download_ui_assets.sh || (echo "Failed to download UI 
assets" && exit 1); \
+       else \
+               echo "UI assets already exist, skipping download."; \
+       fi
+
 # Generate assets (vfsdata.go for web UI)
-generate-assets:
+generate-assets: download-ui-assets
        @echo "Generating assets..."
        @cd asset && go generate || (echo "Failed to generate assets" && exit 1)
        @echo "Assets generated successfully!"
@@ -66,6 +75,11 @@ clean-all: clean
        @rm -rf tools/protoc/*/protoc
        @rm -rf tools/protoc/*/bin
        @rm -rf tools/protoc/*/include
+       @echo "Cleaning downloaded UI assets..."
+       @rm -rf ui/node_modules ui/package-lock.json
+       @rm -f ui/ui/lib/.downloaded ui/ui/lib/jquery-license
+       @rm -rf ui/ui/lib/bootstrap-*-dist ui/ui/lib/bootstrap4-glyphicons
+       @rm -f ui/ui/lib/jquery-*.min.js
        @echo "All clean completed!"
 
 # Help
@@ -73,13 +87,14 @@ help:
        @echo "Vermeer Build System"
        @echo ""
        @echo "Usage:"
-       @echo "  make init              - First time setup (download binaries + 
go mod download)"
+       @echo "  make init              - First time setup (download binaries + 
UI assets + go mod download)"
        @echo "  make download-binaries - Download supervisord and protoc 
binaries for your platform"
+       @echo "  make download-ui-assets - Download jQuery, Bootstrap, 
Glyphicons to ui/ui/lib/"
        @echo "  make generate-assets   - Generate assets_vfsdata.go from web 
UI (required before build)"
        @echo "  make build             - Build vermeer for current platform 
(default: local architecture)"
        @echo "  make build-linux-amd64 - Build for Linux AMD64 (for 
deployment)"
        @echo "  make build-linux-arm64 - Build for Linux ARM64 (for ARM 
servers)"
        @echo "  make clean             - Remove generated files and binaries 
(keep downloaded tools)"
-       @echo "  make clean-all         - Remove everything including 
downloaded tools"
+       @echo "  make clean-all         - Remove everything including 
downloaded tools and UI assets"
        @echo "  make all               - Generate assets and build (default 
target)"
        @echo "  make help              - Show this help message"
diff --git a/vermeer/README.md b/vermeer/README.md
index 38425637..97cf58d7 100644
--- a/vermeer/README.md
+++ b/vermeer/README.md
@@ -89,7 +89,12 @@ vermeer/
 │   ├── master.ini
 │   └── worker.ini
 ├── tools/               # Binary dependencies (supervisord, protoc)
-└── ui/                  # Web dashboard
+└── ui/                  # Web dashboard source and dependencies
+    ├── package.json     # Frontend dependencies (jQuery, Bootstrap)
+    └── ui/
+        ├── master.html  # Master dashboard page
+        ├── worker.html  # Worker dashboard page
+        └── lib/         # Downloaded at build time (git-ignored)
 ```
 
 ## Quick Start
@@ -107,8 +112,8 @@ Create a dedicated config directory (e.g., 
`~/vermeer-config/`) with `master.ini
 Run with Docker:
 
 ```bash
-# Master node
-docker run -v ~/vermeer-config:/go/bin/config hugegraph/vermeer --env=master
+# Master node (with Web UI enabled)
+docker run -v ~/vermeer-config:/go/bin/config hugegraph/vermeer --env=master 
-auth token -auth_token_factor 1234
 
 # Worker node
 docker run -v ~/vermeer-config:/go/bin/config hugegraph/vermeer --env=worker
@@ -158,6 +163,7 @@ Configure parameters in `vermeer.sh`, then:
 #### Prerequisites
 
 - Go 1.23 or later
+- Node.js/npm (for downloading UI assets)
 - `curl` and `unzip` utilities (for downloading dependencies)
 - Internet connection (for first-time setup)
 
@@ -226,10 +232,41 @@ task_strategy = 1
 
 # Number of parallel tasks
 task_parallel_num = 1
+
+# Authentication mode (none or token)
+# Set to "token" to enable Web UI and API authentication
+auth = none
+
+# Token authentication factor (required when auth=token)
+auth_token_factor = 1234
 ```
 
 **Note**: HugeGraph connection details (`pd_peers`, `server`, `graph`) are 
provided in the graph load API request, not in the configuration file. See 
[HugeGraph Integration](#hugegraph-integration) section for details.
 
+### Generating Auth Token
+
+When `auth=token` is enabled, you need to generate a token for login. Use the 
built-in token generator:
+
+```bash
+# Run with Go
+go run tools/token/token_generator.go -user admin -space default -factor 1234 
-i
+
+# Or run in Docker (no local Go required)
+docker run --rm -v $(pwd):/src -v $(pwd)/config:/src/config golang:1.23-alpine 
sh -c "cd /src && go run tools/token/token_generator.go -user admin -space 
default -factor 1234 -i"
+```
+
+Parameters:
+- `-user` — Username (default: `foo`)
+- `-space` — Graph space name (default: `bar`)
+- `-factor` — Must match `auth_token_factor` in `master.ini`
+- `-client` — Client identifier (default: `hg`)
+- `-i` — Generate immortal token (never expires)
+
+The generated token can be used in two ways:
+
+1. **HTTP Header**: `Authorization: Bearer <token>`
+2. **Login API**: `POST /api/v1/login` with body `{"token": "<token>"}` (sets 
cookie)
+
 ### Worker Configuration (`worker.ini`)
 
 ```ini
@@ -278,6 +315,8 @@ worker_group = default
 
 Vermeer exposes a REST API on port `6688` (configurable in `master.ini`).
 
+> **Note**: The Web UI (`/ui/*`) is only available when `auth=token` is 
configured. Set `auth_token_factor` in `master.ini` or pass `-auth token 
-auth_token_factor <value>` via command line.
+
 ### Key Endpoints
 
 | Endpoint | Method | Description |
@@ -502,7 +541,9 @@ vermeer/tools/protoc/linux64/protoc 
vermeer/apps/protos/*.proto --go-grpc_out=ve
 
 ## Monitoring
 
-Access the Web UI dashboard at `http://master-ip:6688/ui/` for:
+Access the Web UI dashboard at `http://master-ip:6688/ui/master.html` for:
+
+> **Note**: The Web UI requires `auth=token` in `master.ini` (or `-auth token` 
via command line). Without token authentication, the UI routes are not 
registered.
 
 - Worker status and resource usage
 - Active and completed tasks
diff --git a/vermeer/asset/asset.go b/vermeer/asset/asset.go
index a2f15891..040a4361 100644
--- a/vermeer/asset/asset.go
+++ b/vermeer/asset/asset.go
@@ -25,4 +25,4 @@ import (
 )
 
 // Assets contains the project's assets.
-var Assets http.FileSystem = http.Dir("../ui")
+var Assets http.FileSystem = http.Dir("../ui/ui")
diff --git a/vermeer/asset/asset_dev_ui.go b/vermeer/asset/asset_dev_ui.go
index 1b82cab5..60a0b3a6 100644
--- a/vermeer/asset/asset_dev_ui.go
+++ b/vermeer/asset/asset_dev_ui.go
@@ -27,5 +27,5 @@ import (
 
 func init() {
        // for ui development
-       Assets = http.Dir(common.AppRootPath() + "/ui/")
+       Assets = http.Dir(common.AppRootPath() + "/ui/ui/")
 }
diff --git a/vermeer/build.sh b/vermeer/build.sh
index 47cd42e3..7d28846a 100644
--- a/vermeer/build.sh
+++ b/vermeer/build.sh
@@ -33,17 +33,21 @@ go mod download
 echo "Checking binary dependencies..."
 ./scripts/download_binaries.sh
 
-# Generate assets if not exist
-if [ ! -f "asset/assets_vfsdata.go" ]; then
-    echo "Generating assets..."
-    cd asset && go generate && cd ..
+# Download UI assets if stamp file is missing
+echo "Checking UI assets..."
+if [ ! -f "ui/ui/lib/.downloaded" ]; then
+    ./scripts/download_ui_assets.sh
 fi
+
+# Always regenerate embedded assets so UI source changes are picked up
+echo "Generating assets..."
+cd asset && go generate && cd ..
 ARCH=$1
 CGO_ENABLED=0 GOOS=linux GOARCH="$ARCH" go build
 
 VERSION=$(cat ./apps/version/version.go | grep 'Version' | awk -F '"' '{print 
$2}')
 cp tools/supervisord/linux_"$ARCH"/supervisord supervisord
-tar --exclude=config/afs_client.conf -zcvf vermeer-"$VERSION"-"$ARCH".tar.gz 
vermeer config/ supervisord vermeer.sh mem_supervisor.sh
+tar --exclude=config/afs_client.conf -zcvf vermeer-"$VERSION"-"$ARCH".tar.gz 
vermeer config/ supervisord vermeer.sh mem_supervisor.sh release-docs/LICENSE 
release-docs/NOTICE release-docs/licenses/
 
 mkdir "$BUILD_REPO_WS"/output
 mv vermeer-"$VERSION"-"$ARCH".tar.gz "$BUILD_REPO_WS"/output/
diff --git a/vermeer/config/worker.ini b/vermeer/config/worker.ini
index c11cbc4a..5bfd38b4 100644
--- a/vermeer/config/worker.ini
+++ b/vermeer/config/worker.ini
@@ -12,7 +12,6 @@
 ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ; See the License for the specific language governing permissions and
 ; limitations under the License.
-  
 [default]
 log_level=info
 debug_mode=release
@@ -20,4 +19,6 @@ http_peer=0.0.0.0:6788
 grpc_peer=0.0.0.0:6789
 master_peer=127.0.0.1:6689
 run_mode=worker
-worker_group=default
\ No newline at end of file
+worker_group=default
+auth=none
+auth_token_factor=1234
diff --git a/vermeer/release-docs/LICENSE b/vermeer/release-docs/LICENSE
new file mode 100644
index 00000000..bb3cfbe1
--- /dev/null
+++ b/vermeer/release-docs/LICENSE
@@ -0,0 +1,244 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+
+============================================================================
+   APACHE HUGEGRAPH SUBCOMPONENTS:
+
+   The Apache HugeGraph project contains subcomponents with separate copyright
+   notices and license terms. Your use of the source code for the these
+   subcomponents is subject to the terms and conditions of the following
+   licenses.
+
+========================================================================
+Third party MIT licenses
+========================================================================
+
+The following components are provided under the MIT License.
+See licenses/ for text of these licenses.
+
+    (The MIT License) * jQuery(jQuery:3.5.1-https://jquery.com/ )
+    (The MIT License) * Bootstrap(bootstrap:4.3.1-https://getbootstrap.com/ )
+    (The MIT License) * Bootstrap 3 Glyphicons 
CSS(bootstrap-glyphicons:3.3.7-https://getbootstrap.com/ )
+    (The MIT License) * Font Awesome 5 Free 
CSS(fontawesome-free:5.x-https://fontawesome.com/ )
+    (The MIT License) * Glyphicons Halflings 
Font(glyphicons-halflings-regular-https://glyphicons.com/ )
+
+========================================================================
+Third party Apache 2.0 licenses
+========================================================================
+
+The following components are provided under the Apache 2.0 License.
+See licenses/ for text of these licenses.
+
+    (Apache License, Version 2.0) * 
bootstrap4-glyphicons(bootstrap4-glyphicons-https://github.com/Darkseal/bootstrap4-glyphicons
 )
+
+========================================================================
+Third party SIL Open Font licenses
+========================================================================
+
+The following components are provided under the SIL Open Font License 1.1.
+See licenses/ for text of these licenses.
+
+    (SIL OFL 1.1) * Font Awesome 5 Free 
Fonts(fontawesome-free-fonts:5.x-https://fontawesome.com/ )
+        Font Awesome font files (fa-brands-400, fa-regular-400, fa-solid-900)
+        in eot, svg, ttf, woff, woff2 formats.
diff --git a/vermeer/release-docs/NOTICE b/vermeer/release-docs/NOTICE
new file mode 100644
index 00000000..6e8895d9
--- /dev/null
+++ b/vermeer/release-docs/NOTICE
@@ -0,0 +1,44 @@
+Apache HugeGraph - Vermeer
+Copyright 2022-2026 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+The initial codebase was donated to the ASF by HugeGraph Authors, copyright 
2017-2021.
+
+========================================================================
+This product bundles the following third-party frontend assets:
+========================================================================
+
+jQuery 3.5.1
+  Copyright JS Foundation and other contributors
+  https://jquery.com/
+  Licensed under the MIT License
+
+Bootstrap 4.3.1
+  Copyright 2011-2019 Twitter, Inc.
+  Copyright 2011-2019 The Bootstrap Authors
+  https://getbootstrap.com/
+  Licensed under the MIT License
+
+bootstrap4-glyphicons
+  Copyright 2018 Darkseal / Ryadel
+  https://github.com/Darkseal/bootstrap4-glyphicons
+  Licensed under the Apache License, Version 2.0
+
+Bootstrap 3 Glyphicons CSS (bundled within bootstrap4-glyphicons)
+  Copyright 2011-2018 Twitter, Inc.
+  https://getbootstrap.com/
+  Licensed under the MIT License
+
+Font Awesome 5 Free (fonts and CSS bundled within bootstrap4-glyphicons)
+  Copyright 2018 Fonticons, Inc.
+  https://fontawesome.com/
+  Font files licensed under the SIL Open Font License 1.1
+  CSS and Less files licensed under the MIT License
+  Icons licensed under CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)
+
+Glyphicons Halflings font files (bundled within bootstrap4-glyphicons)
+  Copyright 2011-2018 Twitter, Inc.
+  https://glyphicons.com/
+  Licensed under the MIT License
diff --git a/vermeer/release-docs/licenses/LICENSE-bootstrap.txt 
b/vermeer/release-docs/licenses/LICENSE-bootstrap.txt
new file mode 100644
index 00000000..dee7c9d4
--- /dev/null
+++ b/vermeer/release-docs/licenses/LICENSE-bootstrap.txt
@@ -0,0 +1,22 @@
+MIT License
+
+Copyright (c) 2011-2019 Twitter, Inc.
+Copyright (c) 2011-2019 The Bootstrap Authors
+
+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.
diff --git a/vermeer/release-docs/licenses/LICENSE-bootstrap4-glyphicons.txt 
b/vermeer/release-docs/licenses/LICENSE-bootstrap4-glyphicons.txt
new file mode 100644
index 00000000..94e912e6
--- /dev/null
+++ b/vermeer/release-docs/licenses/LICENSE-bootstrap4-glyphicons.txt
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 2018 Darkseal / Ryadel
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/vermeer/release-docs/licenses/LICENSE-fontawesome.txt 
b/vermeer/release-docs/licenses/LICENSE-fontawesome.txt
new file mode 100644
index 00000000..adbe7017
--- /dev/null
+++ b/vermeer/release-docs/licenses/LICENSE-fontawesome.txt
@@ -0,0 +1,110 @@
+Font Awesome Free License
+-------------------------
+
+Font Awesome Free is free, open source, and GPL friendly. You can use it for
+commercial projects, open source projects, or really almost whatever you want.
+
+Icons -- CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/)
+In the Font Awesome Free download, the CC BY 4.0 license applies to all icons
+packaged as SVG and JS file types.
+
+Fonts -- SIL OFL 1.1 License (https://scripts.sil.org/OFL)
+In the Font Awesome Free download, the SIL OFL 1.1 license applies to all icons
+packaged as web and desktop font files.
+
+Code -- MIT License (https://opensource.org/licenses/MIT)
+In the Font Awesome Free download, the MIT license applies to all non-font and
+non-icon files.
+
+Attribution is required by MIT, SIL OFL 1.1, and CC BY 4.0 licenses. Based on
+the Font Awesome Free package, we have included attribution in the NOTICE file.
+
+Copyright 2018 Fonticons, Inc. (https://fontawesome.com)
+
+
+------------------------------------------------------------------------------
+SIL Open Font License 1.1
+------------------------------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components
+as distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/vermeer/release-docs/licenses/LICENSE-glyphicons.txt 
b/vermeer/release-docs/licenses/LICENSE-glyphicons.txt
new file mode 100644
index 00000000..74775809
--- /dev/null
+++ b/vermeer/release-docs/licenses/LICENSE-glyphicons.txt
@@ -0,0 +1,26 @@
+MIT License (Glyphicons Halflings)
+
+Copyright 2011-2018 Twitter, Inc.
+
+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.
+
+Note: Glyphicons Halflings font files were originally part of Bootstrap 3
+and are distributed under the MIT License by Twitter, Inc. The Glyphicons
+project (https://glyphicons.com/) provides the Halflings set for use with
+Bootstrap.
diff --git a/vermeer/release-docs/licenses/LICENSE-jquery.txt 
b/vermeer/release-docs/licenses/LICENSE-jquery.txt
new file mode 100644
index 00000000..1730e965
--- /dev/null
+++ b/vermeer/release-docs/licenses/LICENSE-jquery.txt
@@ -0,0 +1,22 @@
+MIT License
+
+Copyright JS Foundation and other contributors, https://js.foundation/
+
+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.
diff --git a/vermeer/scripts/download_ui_assets.sh 
b/vermeer/scripts/download_ui_assets.sh
new file mode 100755
index 00000000..ab78877f
--- /dev/null
+++ b/vermeer/scripts/download_ui_assets.sh
@@ -0,0 +1,177 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+set -e
+set -o pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
+UI_DIR="$PROJECT_ROOT/ui"
+LIB_DIR="$PROJECT_ROOT/ui/ui/lib"
+
+# Glyphicons source (GitHub raw) - pinned to specific commit for reproducible 
builds
+GLYPHICONS_COMMIT="f7b1a17bbe64308d1d8b2b4bb2ba8a0ea621b377"
+GLYPHICONS_BASE="https://raw.githubusercontent.com/Darkseal/bootstrap4-glyphicons/${GLYPHICONS_COMMIT}/bootstrap4-glyphicons";
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+NC='\033[0m'
+
+log_info() {
+    echo -e "${GREEN}[INFO]${NC} $1"
+}
+
+log_warn() {
+    echo -e "${YELLOW}[WARN]${NC} $1"
+}
+
+log_error() {
+    echo -e "${RED}[ERROR]${NC} $1"
+}
+
+# Download a single file from URL to target path
+download_file() {
+    local url=$1
+    local target=$2
+
+    mkdir -p "$(dirname "$target")"
+    if ! curl -sL -f "$url" -o "$target"; then
+        log_error "Failed to download: $url"
+        return 1
+    fi
+}
+
+# Main function
+main() {
+    log_info "Downloading UI assets..."
+
+    # Check npm and node
+    if ! command -v npm &> /dev/null; then
+        log_error "npm is required but not installed. Please install 
Node.js/npm first."
+        exit 1
+    fi
+    if ! command -v node &> /dev/null; then
+        log_error "node is required but not installed. Please install Node.js 
first."
+        exit 1
+    fi
+
+    # Step 1: npm install (jQuery + Bootstrap)
+    log_info "Installing npm dependencies (jQuery, Bootstrap)..."
+    cd "$UI_DIR"
+    npm install --no-audit --no-fund
+    cd "$PROJECT_ROOT"
+
+    # Read actual versions from package.json (source of truth)
+    JQUERY_VERSION=$(node -p 
"require('$UI_DIR/package.json').dependencies.jquery")
+    BOOTSTRAP_VERSION=$(node -p 
"require('$UI_DIR/package.json').dependencies.bootstrap")
+
+    # Step 2: Create lib directory structure
+    log_info "Copying files to ui/ui/lib/..."
+    mkdir -p "$LIB_DIR"
+
+    # Copy jQuery (npm names it jquery.min.js, rename to match version)
+    cp "$UI_DIR/node_modules/jquery/dist/jquery.min.js" 
"$LIB_DIR/jquery-${JQUERY_VERSION}.min.js"
+
+    # Copy Bootstrap CSS
+    mkdir -p "$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/css"
+    cp "$UI_DIR/node_modules/bootstrap/dist/css/bootstrap.min.css" 
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/css/"
+    cp "$UI_DIR/node_modules/bootstrap/dist/css/bootstrap.min.css.map" 
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/css/"
+    cp "$UI_DIR/node_modules/bootstrap/dist/css/bootstrap-grid.min.css" 
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/css/"
+    cp "$UI_DIR/node_modules/bootstrap/dist/css/bootstrap-grid.min.css.map" 
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/css/"
+    cp "$UI_DIR/node_modules/bootstrap/dist/css/bootstrap-reboot.min.css" 
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/css/"
+    cp "$UI_DIR/node_modules/bootstrap/dist/css/bootstrap-reboot.min.css.map" 
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/css/"
+
+    # Copy Bootstrap JS
+    mkdir -p "$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/js"
+    cp "$UI_DIR/node_modules/bootstrap/dist/js/bootstrap.min.js" 
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/js/"
+    cp "$UI_DIR/node_modules/bootstrap/dist/js/bootstrap.min.js.map" 
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/js/"
+    cp "$UI_DIR/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js" 
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/js/"
+    cp "$UI_DIR/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js.map" 
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/js/"
+
+    # Copy Bootstrap LICENSE
+    cp "$UI_DIR/node_modules/bootstrap/LICENSE" 
"$LIB_DIR/bootstrap-${BOOTSTRAP_VERSION}-dist/"
+
+    # Create jquery-license (MIT)
+    cat > "$LIB_DIR/jquery-license" << 'JQLICENSE'
+Copyright JS Foundation and other contributors, https://js.foundation/
+
+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.
+JQLICENSE
+
+    # Step 3: Download Bootstrap4 Glyphicons from GitHub
+    log_info "Downloading Bootstrap4 Glyphicons from GitHub..."
+    download_file "$GLYPHICONS_BASE/css/bootstrap-glyphicons.min.css" \
+        "$LIB_DIR/bootstrap4-glyphicons/css/bootstrap-glyphicons.min.css"
+
+    # Download fontawesome fonts
+    for font in fa-brands-400 fa-regular-400 fa-solid-900; do
+        for ext in eot svg ttf woff woff2; do
+            download_file "$GLYPHICONS_BASE/fonts/fontawesome/${font}.${ext}" \
+                
"$LIB_DIR/bootstrap4-glyphicons/fonts/fontawesome/${font}.${ext}"
+        done
+    done
+
+    # Download glyphicons fonts
+    for ext in eot svg ttf woff woff2; do
+        download_file 
"$GLYPHICONS_BASE/fonts/glyphicons/glyphicons-halflings-regular.${ext}" \
+            
"$LIB_DIR/bootstrap4-glyphicons/fonts/glyphicons/glyphicons-halflings-regular.${ext}"
+    done
+
+    # Download maps
+    download_file "$GLYPHICONS_BASE/maps/glyphicons-fontawesome.less" \
+        "$LIB_DIR/bootstrap4-glyphicons/maps/glyphicons-fontawesome.less"
+    download_file "$GLYPHICONS_BASE/maps/glyphicons-fontawesome.min.css" \
+        "$LIB_DIR/bootstrap4-glyphicons/maps/glyphicons-fontawesome.min.css"
+
+    # Download bootstrap4-glyphicons LICENSE for release metadata
+    
GLYPHICONS_LICENSE_URL="https://raw.githubusercontent.com/Darkseal/bootstrap4-glyphicons/${GLYPHICONS_COMMIT}/LICENSE";
+    if ! curl -sL -f "$GLYPHICONS_LICENSE_URL" -o 
"$LIB_DIR/bootstrap4-glyphicons/LICENSE" 2>/dev/null; then
+        log_warn "Could not download bootstrap4-glyphicons LICENSE file (repo 
may not have one)"
+    fi
+
+    # Stamp file for incremental builds
+    touch "$LIB_DIR/.downloaded"
+
+    log_info "All UI assets downloaded successfully!"
+    log_info ""
+    log_info "Downloaded to: $LIB_DIR"
+    log_info "  - jQuery ${JQUERY_VERSION}"
+    log_info "  - Bootstrap ${BOOTSTRAP_VERSION} (CSS + JS + source maps)"
+    log_info "  - Bootstrap4 Glyphicons (CSS + fonts + maps)"
+}
+
+main "$@"
diff --git a/vermeer/ui/package.json b/vermeer/ui/package.json
new file mode 100644
index 00000000..978c95d8
--- /dev/null
+++ b/vermeer/ui/package.json
@@ -0,0 +1,10 @@
+{
+  "name": "vermeer-ui",
+  "version": "1.0.0",
+  "private": true,
+  "description": "Frontend dependencies for Vermeer UI (downloaded at build 
time for ASF compliance)",
+  "dependencies": {
+    "jquery": "3.5.1",
+    "bootstrap": "4.3.1"
+  }
+}
diff --git a/vermeer/ui/ui/lib/functions.js b/vermeer/ui/ui/lib/functions.js
new file mode 100644
index 00000000..faf73618
--- /dev/null
+++ b/vermeer/ui/ui/lib/functions.js
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+; (function () {
+    const API_PREFIX = '/api/v1';
+    window.vermeer = {
+        login: function () {
+            const token = $('#admin_token').val();
+            if (!token) {
+                showDelModal('empty token');
+                return;
+            }
+
+            const req = { token: token };
+            postJson('/login', req,
+                function (data) {
+                    console.log(data.message);
+                    location.reload(true);
+                }
+            );
+        },
+        queryGraphs: function () {
+            const $t = $('#graphs_table');
+            $t.empty();
+            const fields = ['space_name', 'name', 'status', 'state', 
'create_time',
+                'update_time', 'use_out_edges', 'use_out_degree'];
+            $t.append('<thead><tr/></thead>');
+            const $tr = $t.find('thead tr');
+            $.each(fields, function (index, field) {
+                $tr.append($('<th/>').text(field));
+            });
+
+            const ok = function (data) {
+                const $tb = $('<tbody/>');
+                $t.append($tb);
+                const rows = data.graphs;
+                $.each(rows, function (index, row) {
+                    $tb.append(toTableRow(fields, row));
+                });
+            };
+
+            get('/graphs', ok);
+        },
+        queryTasks: function () {
+            const $t = $('#tasks_table');
+            $t.empty();
+            const fields = ['id', 'space_name', 'graph_name', 'create_user', 
'task_type',
+                'status', 'state', 'create_time', 'start_time', 'update_time'];
+            $t.append('<thead><tr/></thead>');
+            const $tr = $t.find('thead tr');
+            $.each(fields, function (index, field) {
+                $tr.append($('<th/>').text(field));
+            });
+
+            const ok = function (data) {
+                const $tb = $('<tbody/>');
+                $t.append($tb);
+                const rows = data.tasks;
+                $.each(rows, function (index, row) {
+                    $tb.append(toTableRow(fields, row));
+                });
+            };
+            get('/tasks', ok);
+        }
+
+    };
+
+    function toTableRow(fields, row) {
+        const $row = $('<tr>');
+        $.each(fields, function (index, field) {
+            let value = '';
+
+            if (field.endsWith('_time')) {
+                value = formatDate(row[field]);
+            } else {
+                value = row[field];
+            }
+
+            const $span = $('<span/>').text(value);
+
+            switch (value) {
+                case 'error':
+                    $span.addClass('badge badge-lg badge-danger');
+                    break;
+                case 'incomplete':
+                    $span.addClass('badge badge-lg badge-warning');
+                    break;
+                case 'complete':
+                case 'loaded':
+                case 'disk':
+                    $span.addClass('badge badge-lg badge-success');
+            }
+
+            const $td = $('<td>').append($span);
+            $row.append($td);
+        });
+        return $row;
+    }
+
+    function showDelModal(text) {
+        $('#msg-modal-msg').text(text);
+        $('#msg-modal').modal('show');
+    }
+
+    function get(url, ok, error, caller) {
+        ajax('GET', url, '', ok, error, caller);
+    }
+
+    function postJson(url, data, ok, error, caller) {
+        ajax('POST', url, JSON.stringify(data), ok, error, caller);
+    }
+
+    function ajax(method, url, data, ok, error, caller) {
+        $.ajax({
+            url: API_PREFIX + url,
+            type: method,
+            data: data,
+            contentType: 'application/json',
+            success: function (response) {
+                if (!ok) {
+                    console.log('ajax request successful:', response);
+                    return;
+                }
+                if (caller) {
+                    ok.apply(caller, [response]);
+                } else {
+                    ok(response);
+                }
+            },
+            error: function (err) {
+                if (err.status === 401) {
+                    showDelModal('Login First!');
+                    return;
+                } else {
+                    console.log('ajax request failed:', err);
+                }
+                if (!error) {
+                    let data = JSON.parse(err.responseText);
+                    showDelModal(data.message);
+                    return;
+                }
+                if (caller) {
+                    error.apply(caller, [err]);
+                } else {
+                    error(err);
+                }
+            }
+        });
+    }
+
+    function formatDate(inputDate) {
+        if (!inputDate) {
+            return '-';
+        }
+        const date = new Date(inputDate);
+        if (isNaN(date.getTime()) || date.getFullYear() === 1) {
+            return '-';
+        }
+        const year = date.getFullYear();
+        const month = (date.getMonth() + 1).toString().padStart(2, '0');
+        const day = date.getDate().toString().padStart(2, '0');
+        const hours = date.getHours().toString().padStart(2, '0');
+        const minutes = date.getMinutes().toString().padStart(2, '0');
+        const seconds = date.getSeconds().toString().padStart(2, '0');
+
+        return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+    }
+
+})();
+
+$(function () {
+    vermeer.queryGraphs();
+    vermeer.queryTasks();
+});
diff --git a/vermeer/ui/ui/lib/vermeer.css b/vermeer/ui/ui/lib/vermeer.css
new file mode 100644
index 00000000..a35ba7ef
--- /dev/null
+++ b/vermeer/ui/ui/lib/vermeer.css
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+/* Move down content because we have a fixed navbar that is 50px tall with 
20px padding */
+body {
+    padding-top: 70px;
+    padding-bottom: 20px;
+}
+
+.state_indicator {
+    padding: 0 4px 0 4px;
+}
+
+.literal_output td {
+    font-family: monospace;
+}
+
+.cursor-pointer {
+    cursor: pointer;
+}
+
+.tooltip-inner {
+    max-width: none;
+    text-align: left;
+}
+
+.label {
+    white-space: normal;
+}
+
+/* The navbar adds horizontal padding already */
+.navbar .container-fluid {
+    padding: 0;
+}
+
+/* This class provides style for containers that hold card like (without 
background) objects within container-fluid and out of accordion */
+.blank-card {
+    padding-bottom: 50px;
+    padding-right: 25px;
+}
\ No newline at end of file

Reply via email to