Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
d460291
adjust layout
KatKatKateryna Aug 5, 2025
17bbedd
formatting
KatKatKateryna Aug 5, 2025
5bfbf0b
create bbox preview
KatKatKateryna Aug 5, 2025
b00e656
better syntax
KatKatKateryna Aug 5, 2025
851489b
load bbox on resource selection
KatKatKateryna Aug 5, 2025
7282155
update resources props
KatKatKateryna Aug 5, 2025
5e87822
add provider subclasses
KatKatKateryna Aug 5, 2025
b1dc2e5
specify provider types
KatKatKateryna Aug 5, 2025
5bbd2e9
set defaults
KatKatKateryna Aug 6, 2025
8dc0683
don't report missing optional fields; type check for list content
KatKatKateryna Aug 6, 2025
d238989
deserialize supported providers on load
KatKatKateryna Aug 6, 2025
c7cfeb7
rearrange functions and bbox
KatKatKateryna Aug 7, 2025
fcb42a3
placeholder functions
KatKatKateryna Aug 7, 2025
81c7501
more UI details
KatKatKateryna Aug 7, 2025
c15c677
default values
KatKatKateryna Aug 7, 2025
2a7fcec
save data in correct formats; write yaml as strings
KatKatKateryna Aug 7, 2025
07f5da8
optimize functions
KatKatKateryna Aug 7, 2025
bbf55c1
list add-delete functionality
KatKatKateryna Aug 7, 2025
642c9f0
UI navigation on Save or Cancel
KatKatKateryna Aug 7, 2025
d19e302
resource data saving and updating
KatKatKateryna Aug 8, 2025
141250f
delete collections
KatKatKateryna Aug 8, 2025
5eb6330
hide resource selection on edit
KatKatKateryna Aug 8, 2025
5968bc4
more UI
KatKatKateryna Aug 8, 2025
fa691df
fix map canvas behavior
KatKatKateryna Aug 8, 2025
e98800d
bbox validator
KatKatKateryna Aug 8, 2025
4ab9db8
more placeholders
KatKatKateryna Aug 8, 2025
b470576
fix lists parsing
KatKatKateryna Aug 8, 2025
09be440
UI rearranged
KatKatKateryna Aug 8, 2025
bc9d22d
fix bbox layout
KatKatKateryna Aug 8, 2025
b1873cc
set UI from data(resources extents)
KatKatKateryna Aug 8, 2025
1e298fb
set all data except links and providers
KatKatKateryna Aug 8, 2025
d843315
fix inline lists
KatKatKateryna Aug 8, 2025
8a5ee40
fix temporal extent field
KatKatKateryna Aug 8, 2025
3d12f1f
ignore None values on Save
KatKatKateryna Aug 8, 2025
58afd05
make visibility optional
KatKatKateryna Aug 8, 2025
54c4249
logging as optional
KatKatKateryna Aug 8, 2025
67c884b
server.templates as optional
KatKatKateryna Aug 8, 2025
169a677
load and save links
KatKatKateryna Aug 8, 2025
1549f38
resource ui validation before save
KatKatKateryna Aug 8, 2025
fe852de
load and save Postgresql resource
KatKatKateryna Aug 8, 2025
0c71f65
update ui
KatKatKateryna Aug 8, 2025
a27b61f
rename clearly
KatKatKateryna Aug 8, 2025
338584f
fix provider saving logic
KatKatKateryna Aug 8, 2025
6b3fd8c
rename btn
KatKatKateryna Aug 8, 2025
d4805aa
validate providers before save
KatKatKateryna Aug 8, 2025
c0b393d
deserialize all supported providers
KatKatKateryna Aug 8, 2025
a8d321f
rearrange files
KatKatKateryna Aug 8, 2025
13b3fc5
ui setter class
KatKatKateryna Aug 8, 2025
5050b1f
add DataSetter from UI; add Resource validator on Save
KatKatKateryna Aug 8, 2025
2cfa4c8
better UI
KatKatKateryna Aug 8, 2025
ef6ef82
delegate methods from Dialog
KatKatKateryna Aug 9, 2025
d5d416e
more methods moved
KatKatKateryna Aug 9, 2025
0eaa13a
fix InlineList
KatKatKateryna Aug 9, 2025
35b9624
bigger indent in YAML
KatKatKateryna Aug 9, 2025
7fec620
arrange imports
KatKatKateryna Aug 9, 2025
391a3a7
remove unused
KatKatKateryna Aug 9, 2025
a5b3436
handle Enum deserialization when its a Union type
KatKatKateryna Aug 9, 2025
d3b0291
make UiSetter non-static
KatKatKateryna Aug 11, 2025
549de07
make DataFromUiSetter non-static
KatKatKateryna Aug 11, 2025
09a5e69
moving provider-specific logic out of configData (via abstract method…
KatKatKateryna Aug 20, 2025
efa9035
make hreflang a Dropdown
KatKatKateryna Aug 20, 2025
af54120
_setup all UI dropdowns in one place
KatKatKateryna Aug 20, 2025
f8d904f
split bbox into 4 inputs
KatKatKateryna Aug 20, 2025
60e8beb
trs as a dropdown
KatKatKateryna Aug 20, 2025
95a5739
_clean up fields on resource load
KatKatKateryna Aug 20, 2025
57d2ee0
validate CRS
KatKatKateryna Aug 21, 2025
440c768
add storage_crs
KatKatKateryna Aug 21, 2025
0552a30
pack and unpack provider data in their own classes; add storage_crs
KatKatKateryna Aug 21, 2025
6d50e0f
provider window always on top
KatKatKateryna Aug 21, 2025
47712f1
provider_crs as array + corresponding widget
KatKatKateryna Aug 21, 2025
2ace6d4
_warning stays on top
KatKatKateryna Aug 21, 2025
4bfc9fe
scrollable warning message on open/save
KatKatKateryna Aug 21, 2025
bbf2ef8
support 2 other providers
KatKatKateryna Aug 21, 2025
a497e50
editing providers
KatKatKateryna Aug 21, 2025
1298b81
_align names; fix crs validation; fix zoom validation
KatKatKateryna Aug 21, 2025
ebc3848
handle no-internet requests
KatKatKateryna Aug 26, 2025
4914bcf
fix '0' value packing
KatKatKateryna Aug 26, 2025
a2bd9a5
set provider names as dropdowns
KatKatKateryna Aug 26, 2025
6b2f0a4
save read-only providers to a separate widget
KatKatKateryna Aug 26, 2025
7496b84
keep provider CRS optional
KatKatKateryna Aug 26, 2025
1457e7d
properly delete providers on Delete Selected
KatKatKateryna Aug 26, 2025
fd64e7a
reorder read-only providers to the end of list; enable scroll for rea…
KatKatKateryna Aug 26, 2025
f98c714
add ui folder to zip build
KatKatKateryna Aug 26, 2025
87a8857
add CRS verification for Provider.CRS list
KatKatKateryna Aug 26, 2025
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: 5 additions & 0 deletions models/top_level/ResourceConfigTemplate.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
InlineList,
bbox_from_list,
get_enum_value_from_string,
is_url_responsive,
is_valid_string,
)
from .providers.records import CrsAuthorities
Expand Down Expand Up @@ -166,6 +167,10 @@ def validate_reassign_bbox(self) -> bool:
self.extents.spatial.bbox = InlineList([-180, -90, 180, 90])
return False

def validate_extents_crs(self):
# not currently used, as we don't enforce data validation that requires internet access
return is_url_responsive(self.extents.spatial.crs, True)

def get_invalid_properties(self):
"""Checks the values of mandatory fields: identification (title, description, keywords)."""
all_invalid_fields = []
Expand Down
1 change: 0 additions & 1 deletion models/top_level/ServerConfig.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from dataclasses import dataclass, field
from enum import Enum
from urllib.parse import urlparse

from .utils import is_valid_string

Expand Down
30 changes: 30 additions & 0 deletions models/top_level/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
from enum import Enum
import gzip
import requests
from urllib.parse import urlparse
from urllib3.response import HTTPResponse

STRING_SEPARATOR = " | "

Expand Down Expand Up @@ -44,3 +48,29 @@ def bbox_from_list(raw_bbox_list: list):
)

return InlineList(list_bbox_val)


def is_url_responsive(url: str, detect_exceptions_in_successful_response=False) -> bool:

parsed_url = urlparse(url)
if not all([parsed_url.scheme, parsed_url.netloc]):
return False

try:
if detect_exceptions_in_successful_response:
# Detect OGC ExceptionReport (invalid request)
response = requests.get(url, allow_redirects=True, timeout=5)
if response.status_code != 200:
return False
else:
text = response.text
if "ExceptionReport" in text or "ExceptionText" in text:
return False
return True

else: # lighter request (if content is not needed)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you don't use this option in the code. I am curious about the use case (:

Copy link
Collaborator Author

@KatKatKateryna KatKatKateryna Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be used if we introduce URL validation for other fields, e.g. 'data' in WMSFacade (which shouldn't always return 200 like the CRS), but I will remove for now

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is fine to keep it; I just wanted to understand why (👍🏽

response = requests.head(url, allow_redirects=True, timeout=5)
return response.status_code == 200

except requests.RequestException:
return False
22 changes: 21 additions & 1 deletion pygeoapi_config_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@

from .ui_widgets import DataSetterFromUi, UiSetter
from .models.ConfigData import ConfigData
from .models.top_level.utils import InlineList, get_enum_value_from_string
from .models.top_level.utils import (
InlineList,
get_enum_value_from_string,
is_url_responsive,
)

from PyQt5.QtWidgets import (
QMainWindow,
Expand Down Expand Up @@ -343,6 +347,22 @@ def _validate_and_add_res_provider(self, values, provider_type):
f"Invalid Provider values: {invalid_fields}",
)

def validate_res_extents_crs(self):
"""Called from .ui file."""
url = self.data_from_ui_setter.get_extents_crs_from_ui(self)
if is_url_responsive(url, True):
QMessageBox.information(
self,
"Information",
f"Valid CRS URL: {url}",
)
else:
QMessageBox.warning(
self,
"Warning",
f"Invalid CRS URL: {url}",
)

def delete_metadata_id_title(self):
"""Delete keyword from metadata, called from .ui file."""
self.ui_setter.delete_list_widget_selected_item(self.listWidgetMetadataIdTitle)
Expand Down
38 changes: 33 additions & 5 deletions pygeoapi_config_dialog_base.ui
Original file line number Diff line number Diff line change
Expand Up @@ -1732,11 +1732,22 @@
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditResExtentsSpatialCrs">
<property name="placeholderText">
<string>CRS84</string>
</property>
</widget>
<layout class = "QHBoxLayout">
<item>
<widget class="QLineEdit" name="lineEditResExtentsSpatialCrs">
<property name="placeholderText">
<string>CRS84</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="validateResExtentsCrsButton">
<property name="text">
<string>Validate</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
Expand Down Expand Up @@ -2533,6 +2544,23 @@
</hint>
</hints>
</connection>

<connection>
<sender>validateResExtentsCrsButton</sender>
<signal>clicked()</signal>
<receiver>PygeoapiConfigDialogBase</receiver>
<slot>validate_res_extents_crs()</slot>
<hints>
<hint type="sourcelabel">
<x>434</x>
<y>160</y>
</hint>
<hint type="destinationlabel">
<x>434</x>
<y>244</y>
</hint>
</hints>
</connection>

</connections>
<slots>
Expand Down
13 changes: 9 additions & 4 deletions ui_widgets/DataSetterFromUi.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,7 @@ def set_resource_data_from_ui(self):

# spatial crs
config_data.resources[res_name].extents.spatial.crs = (
"http://www.opengis.net/def/crs/"
+ dialog.comboBoxResExtentsSpatialCrsType.currentText()
+ "/"
+ dialog.lineEditResExtentsSpatialCrs.text()
self.get_extents_crs_from_ui(dialog)
)

# temporal: only initialize if any of the values are present, otherwise leave as default None
Expand Down Expand Up @@ -358,6 +355,14 @@ def set_resource_data_from_ui(self):
if res_name in config_data.resources:
config_data.resources[new_alias] = config_data.resources.pop(res_name)

def get_extents_crs_from_ui(self, dialog):
return (
"http://www.opengis.net/def/crs/"
+ get_widget_text_value(dialog.comboBoxResExtentsSpatialCrsType)
+ "/"
+ get_widget_text_value(dialog.lineEditResExtentsSpatialCrs)
)

def get_invalid_resource_ui_fields(self) -> list[str]:
"""Get list of invalid UI values in Resource UI."""

Expand Down