Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SERV-1222] Add Web form #63

Merged
merged 9 commits into from
Mar 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,8 @@ go.work
# Build artifacts
*-service

# A profile configuration for the validation service
# The automatically duplicated version of the OpenAPI spec file
html/assets/openapi.yml

# A customizable config file that the service will use
profiles.json
9 changes: 8 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ ENV SERVICE_NAME=${SERVICE_NAME}
ARG LOG_LEVEL
ENV LOG_LEVEL=${LOG_LEVEL}

# Set a version number for the application
ARG VERSION
ENV VERSION=${VERSION}

# Set the location of the profiles config
ENV PROFILES_FILE="$DATA_DIR/profiles.json"

Expand All @@ -54,9 +58,12 @@ RUN addgroup -S "${SERVICE_NAME}" && adduser -S "${SERVICE_NAME}" -G "${SERVICE_
# Create a directory for our profiles file
RUN mkdir -p "$DATA_DIR"

# Copy the templates directory into our container
COPY "html/" "$DATA_DIR/html/"

# Copy the file without --chown or --chmod (BuildKit not required)
COPY --from=build "/${SERVICE_NAME}" "/sbin/${SERVICE_NAME}"
COPY "testdata/test_profiles.json" "$PROFILES_FILE"
COPY "profiles.json" "$PROFILES_FILE"

# Now, modify ownership and permissions in a separate RUN step
RUN chown "${SERVICE_NAME}":"${SERVICE_NAME}" "/sbin/${SERVICE_NAME}" && chmod 0700 "/sbin/${SERVICE_NAME}"
Expand Down
41 changes: 31 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
# Build and runtime variables
# Build and runtime variables that can be overridden
SERVICE_NAME := validation-service
LOG_LEVEL := info
PORT := 8888
VERSION := dev-SNAPSHOT

# Force the API target to run even if the openapi.yml has not been touched/changed
ifneq ($(filter FORCE,$(MAKECMDGOALS)),)
.PHONY: api/api.go
endif

# Define FORCE as a target so accidentally using on other targets won't cause errors
.PHONY: FORCE
FORCE:
@echo "Makefile target(s) run with FORCE to require an API code rebuild"

# Do a full build of the project
all: api lint build test docker-test
all: config api lint build test docker-test

# Lint the code
# Lint the code for correctness
lint:
golangci-lint run

# Generate Go code from the OpenAPI specification only when it has changed
# We generate Go API code from the OpenAPI specification only when it has changed
# We assume Windows developers are using WSL, so we don't define $(CP) for this
api/api.go: openapi.yml
oapi-codegen -package api -generate types,server,spec -o api/api.go openapi.yml
cp openapi.yml html/assets/openapi.yml

# This is an alias for the longer API generation Makefile target api/api.go
api: api/api.go

# Build the Go project
build:
build: api
go build -o $(SERVICE_NAME)

# Run Go tests, excluding tests in the 'integration' directory
Expand All @@ -27,11 +40,12 @@ test:

# Build the Docker container (an optional debugging step)
docker-build:
docker build . --tag $(SERVICE_NAME) --build-arg SERVICE_NAME=$(SERVICE_NAME)
docker build . --tag $(SERVICE_NAME) --build-arg SERVICE_NAME=$(SERVICE_NAME) --build-arg VERSION=$(VERSION)

# A convenience target to assist with running the Docker container outside of the build (optional)
docker-run:
docker run -p $(PORT):8888 --name $(SERVICE_NAME) -d $(shell docker image ls -q --filter=reference=$(SERVICE_NAME))
CONTAINER_ID=$(shell docker image ls -q --filter=reference=$(SERVICE_NAME)); \
docker run -p $(PORT):8888 --name $(SERVICE_NAME) -e LOG_LEVEL="$(LOG_LEVEL)" -d $$CONTAINER_ID

docker-logs:
docker logs -f $(shell docker ps --filter "name=$(SERVICE_NAME)" --format "{{.ID}}")
Expand All @@ -48,6 +62,13 @@ docker-test:
clean:
rm -rf $(SERVICE_NAME) api/api.go

# Run the validation service locally
run: api build
PROFILES_FILE="testdata/test_profiles.json" ./$(SERVICE_NAME)
# Creates a new local profile configuration file if it doesn't already exist
profile.json: profiles.example.json
@if [ ! -f profile.json ]; then cp profiles.example.json profiles.json; fi

# An alias for the profile.json target
config: profile.json

# Run the validation service locally, independent of the Docker container
run: config api build
PROFILES_FILE="profiles.json" LOG_LEVEL=$(LOG_LEVEL) VERSION=$(VERSION) ./$(SERVICE_NAME)
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ your system's documentation or package system for more details.
* The [golangci-lint](https://github.com/golangci/golangci-lint) linter for checking code style conformance

Optionally, if you want to test (or build using) the project's GitHub Actions:

* [ACT](https://github.com/nektos/act): A local GitHub Action runner that will also build and test the project

## Building and Running with Make
Expand Down Expand Up @@ -60,10 +61,21 @@ Note: If you want to change the values defined in the Makefile (echo.g., the `LO

make test LOG_LEVEL=debug

To run the validation service, locally, for testing purposes:
To run the validation service, without a Docker container, for live testing purposes (i.e., the fastest way to test):

make run

or

make run LOG_LEVEL=debug

The `run` or `all` targets can also be run with `FORCE` to force the API code to be regenerated, even if the OpenAPI
spec hasn't changed since the last run:

make run LOG_LEVEL=debug FORCE

The usual behavior of `run` or `all` is not to run the `api` target if the OpenAPI spec has not been touched/changed.

### Working with Docker

One can also run Docker locally, for more hands-on testing, from the Makefile. Unlike the tests, which will not leave
Expand Down
64 changes: 19 additions & 45 deletions api/api.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions html/assets/validation.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* CSS overrides for the validation service's SPA and its embedded reDoc OpenAPI viewer. */

.navbar { background-color: #0074D9; }
.navbar-item.validator-title {
color: #FFC107 !important; font-weight: bold; font-size: 2em; text-shadow: 1px 1px 0px #0056A6;
}
.navbar-item.nav-link { color: #FFF; }
.navbar-item.nav-link:hover { color: #0056A6; background-color: #EEE !important; }
body { background-color: #EEE; min-height: 100vh; }
.box { background-color: #FFF; }
.button.is-primary { background-color: #0074D9; border-color: #0074D9; }
.button.is-primary:hover { background-color: #0056A6; }
a.has-text-link { color: #0074D9 !important; }
a.has-text-link:hover { color: #0056A6 !important; }

/* Right sidebar styles */
div[id^="operation/"] div:nth-child(2) div button, div[id^="panel"] { background-color: #333 !important; }
div.react-tabs__tab-panel div div:nth-child(1) { background-color: #555; } /* Content type box */
div.react-tabs__tab-panel div:nth-child(2) div { background-color: #333; } /* Copy button bg */
.tab-success.react-tabs__tab--selected {
background-color: green !important; color: white !important; margin-bottom: 5px;
}
div[id^="operation/"] > div:nth-child(2), div[id^="operation/"] + div, div.redoc-wrap > div:last-child {
background-color: #EEE; /* Right sidebar bg */
}

/* Code block changes below */
div.redoc-json, code { background-color: white !important; font-size: 16px; padding: 0px; }
.token.property.string { color: #0074D9 !important; }
.token.string { color: green !important; }
.token.punctuation, div.hoverable { color: #0056A6 !important; background-color: white !important; }

/* Response samples text */
h3 {
margin-top: 30px; margin-bottom: 5px; font-weight: bold; font-size: larger; background-color: #EEE;
color: #0056A6 !important;
}

/* Where we keep the version number */
footer { font-size: smaller; text-align: right; }
52 changes: 52 additions & 0 deletions html/assets/validation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@

/**
* Determines which part of the SPA to show depending on the contentID that's passed.
*
* @param {string} contentID - The ID of the content-section that's being passed to the function
*/
function showContent(contentID) {
let content;

document.querySelectorAll('.content-section').forEach(section => {
section.style.display = 'none';
});

content = document.getElementById(contentID);
if (content) {
content.style.display = 'block';

// If showing API docs, reinitialize Redoc
if (contentID === "api-docs") {
Redoc.init("openapi.yml", document.getElementById("api-docs"));
}
}
}

/**
* Adds a listener to toggle the main view to the 'csv-update' page content by default.
*
* @param {string} DOMContentLoaded - The type of event listener being added to the page
*/
document.addEventListener("DOMContentLoaded", function () {
showContent('csv-upload'); // Show CSV Upload by default
});

/**
* Adds an event listener to override the onClick behavior of the redoc source code copy button.
*
* @param {string} click - The type of event listener being added to the page
*/
document.addEventListener("click", /** @param {MouseEvent} event */ function (event) {
let button = event.target;

// Find the problematic response samples copy button (really a div) and fix it
if (button.tagName === "DIV" && button.innerText.trim().startsWith("Copy")) {
button.querySelectorAll("div").forEach(div => {
if (!div.innerText.trim() && div.children.length === 0) {
div.remove(); // Remove the divs that display incorrectly when clicking copy
} else {
div.style.backgroundColor = "#fff"; // Give the working ones white backgrounds
}
});
}
});
Loading
Loading