diff --git a/.eslintrc.js b/.eslintrc.js index 3f197cb..c0f040d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -35,8 +35,23 @@ module.exports = { 'max-classes-per-file': 'off', 'no-use-before-define': 'off', 'vue/multi-word-component-names': 'off', + '@typescript-eslint/no-unused-vars': ['warn', { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + }], + 'vue/no-v-for-template-key': 'off', + 'vue/html-button-has-type': 'off', + 'vue/no-template-target-blank': 'off', }, parserOptions: { parser: '@typescript-eslint/parser', }, + settings: { + 'import/resolver': { + typescript: { + project: './tsconfig.json', + }, + }, + }, } diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..5990d9c --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index c2d9fbd..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: test and build - -on: - push: - branches: - - develop - pull_request: - workflow_dispatch: - -concurrency: - # prevent duplicate runs - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - build: - runs-on: ubuntu-latest - - strategy: - matrix: - # todo: upgrade to latest supported LTS node version - # https://nodejs.org/en/about/previous-releases#release-schedule - node: [16] - - steps: - - # https://github.com/actions/checkout - name: Checkout repo - uses: actions/checkout@v4 - - - # https://github.com/actions/setup-node - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node }} - cache: 'npm' - - - name: Install dependencies from package-lock.json - run: npm clean-install - - - name: Lint - run: npm run lint - - - name: Build - run: npm run build - - # todo: without tests this does not do much diff --git a/.github/workflows/generate_changelog.yml b/.github/workflows/generate_changelog.yml new file mode 100644 index 0000000..61c4940 --- /dev/null +++ b/.github/workflows/generate_changelog.yml @@ -0,0 +1,138 @@ +name: Generate Changelog + +permissions: + contents: write + pull-requests: write + +on: + workflow_call: + inputs: + tag: + required: true + type: string + +jobs: + generate-changelog: + name: Update CHANGELOG and Open PR + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v6 + with: + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 + + - name: Generate changelog entry + shell: bash + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BASE_BRANCH: ${{ github.event.repository.default_branch }} + run: | + set -euo pipefail + + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + + CHANGELOG_FILE="CHANGELOG.md" + LATEST_TAG="${{ inputs.tag }}" + PREVIOUS_TAG="$(git tag --sort=-creatordate | sed -n '2p')" + CHANGELOG_BRANCH="chore/changelog-${LATEST_TAG#v}" + + if [[ -n "$PREVIOUS_TAG" ]]; then + RANGE="$PREVIOUS_TAG..$LATEST_TAG" + echo "Generating changelog for $LATEST_TAG since $PREVIOUS_TAG" + else + RANGE="$LATEST_TAG" + echo "Generating changelog for $LATEST_TAG from repository start" + fi + + git checkout -B "$CHANGELOG_BRANCH" + + COMMITS="$(git log "$RANGE" --no-merges --pretty=format:"%s by @%an in %h" || true)" + + ADDED=""; CHANGED=""; FIXED=""; REMOVED=""; SECURITY="" + while IFS= read -r line; do + [[ -z "$line" ]] && continue + case "$line" in + *feat*|*implement*) ADDED+="- $line\n" ;; + *fix*|*bug*|*resolve*|*patch*) FIXED+="- $line\n" ;; + *update*|*modify*|*change*|*refactor*|*chore*) CHANGED+="- $line\n" ;; + *decommission*|*delete*|*remove*) REMOVED+="- $line\n" ;; + *security*|*vuln*|*"patch security"*) SECURITY+="- $line\n" ;; + *) CHANGED+="- $line\n" ;; + esac + done <<< "$COMMITS" + + if [[ -z "$ADDED$CHANGED$FIXED$REMOVED$SECURITY" ]]; then + CHANGED="- No user-facing changes captured in commit messages.\n" + fi + + { + echo "## [$LATEST_TAG] - $(date +'%Y-%m-%d')" + echo + [[ -n "$ADDED" ]] && echo -e "### Added\n$ADDED" + [[ -n "$CHANGED" ]] && echo -e "### Changed\n$CHANGED" + [[ -n "$FIXED" ]] && echo -e "### Fixed\n$FIXED" + [[ -n "$REMOVED" ]] && echo -e "### Removed\n$REMOVED" + [[ -n "$SECURITY" ]] && echo -e "### Security\n$SECURITY" + } > temp_changelog.md + + if [[ ! -f "$CHANGELOG_FILE" ]]; then + { + echo "# Changelog" + echo + echo "All notable changes to this project will be documented in this file." + echo + echo "## [Unreleased]" + echo + } > "$CHANGELOG_FILE" + fi + + if grep -q "^## \[Unreleased\]" "$CHANGELOG_FILE"; then + awk ' + BEGIN { inserted=0 } + { + print + if (!inserted && $0 ~ /^## \[Unreleased\]/) { + print "" + while ((getline line < "temp_changelog.md") > 0) print line + close("temp_changelog.md") + print "" + inserted=1 + } + } + ' "$CHANGELOG_FILE" > "${CHANGELOG_FILE}.tmp" + mv "${CHANGELOG_FILE}.tmp" "$CHANGELOG_FILE" + else + { + cat temp_changelog.md + echo + cat "$CHANGELOG_FILE" + } > "${CHANGELOG_FILE}.tmp" + mv "${CHANGELOG_FILE}.tmp" "$CHANGELOG_FILE" + fi + rm -f temp_changelog.md + + git add "$CHANGELOG_FILE" + if git diff --cached --quiet; then + echo "No changelog updates to commit; skipping PR creation." + exit 0 + fi + + git commit -m "docs: update CHANGELOG.md for $LATEST_TAG" + git push --set-upstream origin "$CHANGELOG_BRANCH" + + if [[ -z "${BASE_BRANCH}" ]]; then + BASE_BRANCH="develop" + fi + + EXISTING_PR_COUNT="$(gh pr list --head "$CHANGELOG_BRANCH" --base "$BASE_BRANCH" --json number --jq 'length')" + if [[ "$EXISTING_PR_COUNT" -eq 0 ]]; then + gh pr create \ + --title "chore: update changelog for $LATEST_TAG" \ + --body "This PR updates the changelog for release $LATEST_TAG." \ + --base "$BASE_BRANCH" \ + --head "$CHANGELOG_BRANCH" + else + echo "A changelog PR for $CHANGELOG_BRANCH already exists." + fi diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 1f9cc50..0000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Publish to Docker Hub - -on: - push: - branches: - - develop - pull_request: - release: - types: - - created - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - publish: - uses: FAIRDataTeam/github-workflows/.github/workflows/docker-publish.yml@v2 - secrets: inherit - with: - file: './Dockerfile' - push: ${{ github.event_name == 'push' || github.event_name == 'release' }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..ab324b6 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,149 @@ +# SPDX-FileCopyrightText: 2024 Stichting Health-RI +# SPDX-FileContributor: 2024 PNED G.I.E. +# +# SPDX-License-Identifier: Apache-2.0 + +name: Create Release + +permissions: + contents: write + pull-requests: write + +on: + workflow_dispatch: + inputs: + version: + description: Version increment + type: choice + options: + - major + - minor + - patch + required: true + default: patch + +env: + DOCKER_IMAGE: healthri/fdp-client + +jobs: + versioning: + name: Create Version Tag + runs-on: ubuntu-latest + outputs: + new_tag: ${{ steps.tagging.outputs.new_tag }} + steps: + - name: Checkout Repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Set Git User Identity + run: | + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + + - name: Fetch Latest Tag and Increment Version + id: tagging + shell: bash + run: | + LATEST_TAG=$(git tag --sort=-creatordate | head -n 1) + if [[ -z "$LATEST_TAG" ]]; then + LATEST_TAG="v0.0.0" + fi + echo "Latest tag: $LATEST_TAG" + + # Extract Major, Minor, Patch + IFS='.' read -r MAJOR MINOR PATCH <<<"${LATEST_TAG#v}" + INCREMENT=${{ github.event.inputs.version }} + echo "Updating $INCREMENT version" + + case "$INCREMENT" in + major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;; + minor) MINOR=$((MINOR + 1)); PATCH=0 ;; + patch|*) PATCH=$((PATCH + 1)) ;; + esac + + NEW_TAG="v$MAJOR.$MINOR.$PATCH" + echo "Pushing this tag: $NEW_TAG" + + git tag -a "$NEW_TAG" -m "Release $NEW_TAG" + git push origin "$NEW_TAG" + + echo "New tag pushed: $NEW_TAG" + echo "new_tag=$NEW_TAG" >> "$GITHUB_OUTPUT" + + publish-release: + name: Publish GitHub Release + runs-on: ubuntu-latest + needs: versioning + steps: + - name: Checkout Repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Generate and Publish GitHub Release + shell: bash + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + LATEST_TAG="${{ needs.versioning.outputs.new_tag }}" + PREVIOUS_TAG=$(git tag --sort=-creatordate | sed -n '2p') + + echo "Creating GitHub release for $LATEST_TAG from previous release $PREVIOUS_TAG" + + if [[ -n "$PREVIOUS_TAG" ]]; then + gh release create "$LATEST_TAG" \ + --title "Release $LATEST_TAG" \ + --generate-notes \ + --notes-start-tag "$PREVIOUS_TAG" + else + gh release create "$LATEST_TAG" \ + --title "Release $LATEST_TAG" \ + --generate-notes + fi + + call-generate-changelog: + name: Generate Changelog PR + needs: [versioning, publish-release] + uses: ./.github/workflows/generate_changelog.yml + secrets: inherit + with: + tag: ${{ needs.versioning.outputs.new_tag }} + + docker-release: + name: Build and Push Docker Image + runs-on: ubuntu-latest + needs: [versioning, publish-release, call-generate-changelog] + steps: + - name: Checkout Repository + uses: actions/checkout@v6 + + - name: Prepare Docker tags + id: docker_meta + run: | + VERSION="${{ needs.versioning.outputs.new_tag }}" + VERSION="${VERSION#v}" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + push: true + platforms: linux/amd64,linux/arm64 + tags: | + ${{ env.DOCKER_IMAGE }}:${{ steps.docker_meta.outputs.version }} + ${{ env.DOCKER_IMAGE }}:latest diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..c33f4b3 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,21 @@ +name: Run Tests + +on: push + +jobs: + test-frontend: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-node@v6 + with: + node-version: 24 + - name: Install + run: | + npm install + - name: Lint + run: | + npm run lint diff --git a/CHANGELOG.md b/CHANGELOG.md index fd0f12c..8f4fcb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add support for integer and decimal datetypes +## [v1.0.0] - 2026-02-13 + +### Fixed +- I did a patch of the index.html by @Hans-christian in e894c10 + + - Add boolean editor - Add option to show the validation report when request fails - Add datatypes in serialized RDF diff --git a/Dockerfile b/Dockerfile index eb3ca2a..fa6aed2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ ###### BUILD STAGE ###### # https://v2.vuejs.org/v2/cookbook/dockerize-vuejs-app.html -FROM node:16-alpine AS build-stage +FROM node:20-alpine AS build-stage WORKDIR /app # install-layer @@ -26,10 +26,8 @@ COPY --from=build-stage /app/src/scss src/scss COPY --from=build-stage /app/src/components src/components COPY --from=build-stage /app/src/views src/views COPY --from=build-stage /app/node_modules/bootstrap/scss src/~bootstrap/scss -COPY --from=build-stage /app/node_modules/bootstrap-vue/src src/~bootstrap-vue/src +COPY --from=build-stage /app/node_modules/bootstrap-vue-next/src src/~bootstrap-vue-next/src COPY --from=build-stage /app/node_modules/prismjs/themes src/~prismjs/themes -COPY --from=build-stage /app/node_modules/vue-select/src/scss src/~vue-select/src/scss -COPY --from=build-stage /app/node_modules/vue2-datepicker/scss src/~vue2-datepicker/scss # nginx COPY nginx/default.conf /etc/nginx/conf.d/default.conf diff --git a/README.md b/README.md index 075a53b..7dde9b7 100644 --- a/README.md +++ b/README.md @@ -17,15 +17,26 @@ Install dependencies using: $ npm install ``` -Create `public/config.js` file. For local development, you need to set the apiURL to where the FDP server is running, usually: +### Local development (no Docker) + +1) Start the FDP server (default `http://localhost:8080`). +2) Create `public/config.js` and set `apiURL` to the FDP server: ```js // public/config.js window.config = { - apiURL: 'http://localhost:8080' + apiURL: 'http://localhost:8080', } ``` +3) Run the dev server: + +``` +$ npm run serve +``` + +The client will be available at `http://localhost:8081`. + > **Tip:** If you run both, the server and the client locally, start the server first, because it needs to run on port 8080. The client will then be automatically started on port 8081. Compile and hot-reload for development: @@ -40,6 +51,37 @@ Compile and minify for production: $ npm run build ``` +## Docker + +The nginx container can be configured at runtime using environment variables: + +- `API_URL` (optional): browser-facing API base URL. For Docker, use `/` to call same-origin and avoid CORS/internal DNS issues. +- `FDP_HOST` (required for Docker proxy): backend `host:port` used by nginx inside the container network. Do not include `http://` or `https://`. +- `FDP_SCHEME` (optional): `http` or `https` for the proxy (`http` default). +- `PUBLIC_PATH` (optional): base path if serving under a subpath (e.g. `/app`). +- `REBUILD_STYLES` (optional): set to any value to force rebuilding SCSS at container start. + +Example: backend is another container on the same network (`fdp` service): + +``` +docker run --rm -p 8081:80 \ + --network fdppv1_default \ + -e FDP_HOST=fdp:8080 \ + -e API_URL=/ \ + fdp-client +``` + +Example: backend is on host machine: + +``` +docker run --rm -p 8081:80 \ + -e FDP_HOST=host.docker.internal:8080 \ + -e API_URL=/ \ + fdp-client +``` + +If the backend is HTTPS-only, set `FDP_SCHEME=https` and ensure the API URL is `https://...`. + Run tests or linter: ``` diff --git a/public/index.html b/index.html similarity index 77% rename from public/index.html rename to index.html index 9d6c912..8bb98d3 100644 --- a/public/index.html +++ b/index.html @@ -5,8 +5,8 @@ - - + +