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

feat(viewer): make zoom level configurable in viewer for OAPIF #221

Merged
merged 4 commits into from
Aug 8, 2024
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
11 changes: 5 additions & 6 deletions .github/workflows/e2e-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
steps:
- uses: actions/checkout@v3

# Build a local test image for re-use across end-to-end tests
# Build a local test image for (potential) re-use across end-to-end tests
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
Expand All @@ -19,13 +19,12 @@ jobs:
push: false
tags: gokoala:local

# E2E Test
# E2E Test (Docker Compose V2 can't unfortunately re-use image, so build it again).
- name: E2E Test => OGC API Features with Azure GeoPackage
run: |
docker-compose -f ./examples/docker-compose-features-azure.yaml pull \
&& \
docker-compose -f ./examples/docker-compose-features-azure.yaml up \
--no-build --exit-code-from smoketest
docker compose -f ./examples/docker-compose-features-azure.yaml build gokoala && \
docker compose -f ./examples/docker-compose-features-azure.yaml up \
--exit-code-from smoketest

- name: Start GoKoala test instance
run: |
Expand Down
60 changes: 36 additions & 24 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,9 +440,14 @@ type CollectionEntryFeatures struct {
// +optional
Filters FeatureFilters `yaml:"filters,omitempty" json:"filters,omitempty"`

// Downloads available for this collection
// Downloads available for this collection through map sheets. Note that 'map sheets' refer to a map
// divided in rectangle areas that can be downloaded individually.
// +optional
MapSheetDownloads *MapSheetDownloads `yaml:"mapSheetDownloads,omitempty" json:"mapSheetDownloads,omitempty"`

// Configuration specifically related to HTML/Web representation
// +optional
Web *WebConfig `yaml:"web,omitempty" json:"web,omitempty"`
}

// +kubebuilder:object:generate=true
Expand Down Expand Up @@ -485,25 +490,50 @@ type DownloadLink struct {

// +kubebuilder:object:generate=true
type MapSheetDownloads struct {
// Properties that provide the download details per map sheet
// Properties that provide the download details per map sheet. Note that 'map sheets' refer to a map
// divided in rectangle areas that can be downloaded individually.
Properties MapSheetDownloadProperties `yaml:"properties" json:"properties" validate:"required"`
}

// +kubebuilder:object:generate=true
type MapSheetDownloadProperties struct {
// Property containing file download URL
// Property/column containing file download URL
rkettelerij marked this conversation as resolved.
Show resolved Hide resolved
AssetURL string `yaml:"assetUrl" json:"assetUrl" validate:"required"`

// Property containing file size
// Property/column containing file size
Size string `yaml:"size" json:"size" validate:"required"`

// Property containing file media type
// The actual media type (not a property/column) of the download, like application/zip.
MediaType MediaType `yaml:"mediaType" json:"mediaType" validate:"required"`

// Property containing the map sheet identifier
// Property/column containing the map sheet identifier
MapSheetID string `yaml:"mapSheetId" json:"mapSheetId" validate:"required"`
}

// +kubebuilder:object:generate=true
type WebConfig struct {
// Viewer config for displaying multiple features on a map
// +optional
FeaturesViewer *FeaturesViewer `yaml:"featuresViewer,omitempty" json:"featuresViewer,omitempty"`

// Viewer config for displaying a single feature on a map
// +optional
FeatureViewer *FeaturesViewer `yaml:"featureViewer,omitempty" json:"featureViewer,omitempty"`
}

// +kubebuilder:object:generate=true
type FeaturesViewer struct {
// Maximum initial zoom level of the viewer when rendering features, specified by scale denominator.
// Defaults to 1000 (= scale 1:1000).
// +optional
MinScale int `yaml:"minScale,omitempty" json:"minScale,omitempty" validate:"gt=0" default:"1000"`

// Minimal initial zoom level of the viewer when rendering features, specified by scale denominator
// (not set by default).
// +optional
MaxScale *int `yaml:"maxScale,omitempty" json:"maxScale,omitempty" validate:"omitempty,gt=0,gtefield=MinScale"`
}

// +kubebuilder:object:generate=true
type OgcAPI3dGeoVolumes struct {
// Reference to the server (or object storage) hosting the 3D Tiles
Expand Down Expand Up @@ -612,24 +642,6 @@ func (oaf *OgcAPIFeatures) ProjectionsForCollection(collectionID string) []strin
return result
}

func (oaf *OgcAPIFeatures) PropertyFiltersForCollection(collectionID string) []PropertyFilter {
for _, coll := range oaf.Collections {
if coll.ID == collectionID && coll.Features != nil && coll.Features.Filters.Properties != nil {
return coll.Features.Filters.Properties
}
}
return []PropertyFilter{}
}

func (oaf *OgcAPIFeatures) MapSheetPropertiesForCollection(collectionID string) *MapSheetDownloadProperties {
for _, coll := range oaf.Collections {
if coll.ID == collectionID && coll.Features != nil && coll.Features.MapSheetDownloads != nil {
return &coll.Features.MapSheetDownloads.Properties
}
}
return nil
}

// +kubebuilder:object:generate=true
type OgcAPIProcesses struct {
// Enable to advertise dismiss operations on the conformance page
Expand Down
50 changes: 50 additions & 0 deletions config/zz_generated.deepcopy.go

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

3 changes: 0 additions & 3 deletions examples/docker-compose-features-azure.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
---
version: "3"

services:
azurite:
image: mcr.microsoft.com/azure-storage/azurite:3.29.0
Expand Down Expand Up @@ -42,7 +40,6 @@ services:
retries: 30

gokoala:
image: gokoala:local # run local image if available (used in CI)
build:
context: ../
dockerfile: Dockerfile
Expand Down
45 changes: 33 additions & 12 deletions internal/ogc/features/html.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type featureCollectionPage struct {
Limit int
ReferenceDate *time.Time
MapSheetProperties *config.MapSheetDownloadProperties
WebConfig *config.WebConfig

// Property filters as supplied by the user in the URL: filter name + value(s)
PropertyFilters map[string]string
Expand All @@ -66,19 +67,20 @@ type featurePage struct {
FeatureID string
Metadata *config.GeoSpatialCollectionMetadata
MapSheetProperties *config.MapSheetDownloadProperties
WebConfig *config.WebConfig
}

func (hf *htmlFeatures) features(w http.ResponseWriter, r *http.Request, collectionID string, cursor domain.Cursors,
featuresURL featureCollectionURL, limit int, referenceDate *time.Time,
propertyFilters map[string]string, configuredPropertyFilters datasources.PropertyFiltersWithAllowedValues,
mapSheetProperties *config.MapSheetDownloadProperties, fc *domain.FeatureCollection) {
featuresURL featureCollectionURL, limit int, referenceDate *time.Time, propertyFilters map[string]string,
configuredPropertyFilters datasources.PropertyFiltersWithAllowedValues, configuredFC *config.CollectionEntryFeatures,
fc *domain.FeatureCollection) {

collectionMetadata := collections[collectionID]
collection := configuredCollections[collectionID]

breadcrumbs := collectionsBreadcrumb
breadcrumbs = append(breadcrumbs, []engine.Breadcrumb{
{
Name: getCollectionTitle(collectionID, collectionMetadata),
Name: getCollectionTitle(collectionID, collection.Metadata),
Path: collectionsCrumb + collectionID,
},
{
Expand All @@ -90,17 +92,26 @@ func (hf *htmlFeatures) features(w http.ResponseWriter, r *http.Request, collect
if referenceDate.IsZero() {
referenceDate = nil
}
var mapSheetProps *config.MapSheetDownloadProperties
var wc *config.WebConfig
if configuredFC != nil {
if configuredFC.MapSheetDownloads != nil {
mapSheetProps = &configuredFC.MapSheetDownloads.Properties
}
wc = configuredFC.Web
}

pageContent := &featureCollectionPage{
*fc,
collectionID,
collectionMetadata,
collection.Metadata,
cursor,
featuresURL.toPrevNextURL(collectionID, cursor.Prev, engine.FormatHTML),
featuresURL.toPrevNextURL(collectionID, cursor.Next, engine.FormatHTML),
limit,
referenceDate,
mapSheetProperties,
mapSheetProps,
wc,
propertyFilters,
configuredPropertyFilters,
}
Expand All @@ -110,13 +121,13 @@ func (hf *htmlFeatures) features(w http.ResponseWriter, r *http.Request, collect
}

func (hf *htmlFeatures) feature(w http.ResponseWriter, r *http.Request, collectionID string,
mapSheetProperties *config.MapSheetDownloadProperties, feat *domain.Feature) {
collectionMetadata := collections[collectionID]
configuredFC *config.CollectionEntryFeatures, feat *domain.Feature) {
collection := configuredCollections[collectionID]

breadcrumbs := collectionsBreadcrumb
breadcrumbs = append(breadcrumbs, []engine.Breadcrumb{
{
Name: getCollectionTitle(collectionID, collectionMetadata),
Name: getCollectionTitle(collectionID, collection.Metadata),
Path: collectionsCrumb + collectionID,
},
{
Expand All @@ -129,12 +140,22 @@ func (hf *htmlFeatures) feature(w http.ResponseWriter, r *http.Request, collecti
},
}...)

var mapSheetProps *config.MapSheetDownloadProperties
var wc *config.WebConfig
if configuredFC != nil {
if configuredFC.MapSheetDownloads != nil {
mapSheetProps = &configuredFC.MapSheetDownloads.Properties
}
wc = configuredFC.Web
}

pageContent := &featurePage{
*feat,
collectionID,
feat.ID,
collectionMetadata,
mapSheetProperties,
collection.Metadata,
mapSheetProps,
wc,
}

lang := hf.engine.CN.NegotiateLanguage(w, r)
Expand Down
Loading
Loading