Skip to content

Commit

Permalink
Merge branch 'develop' into feature/text_annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexanderWatzinger committed Oct 11, 2024
2 parents 0924b7c + db2fc1c commit e1b888b
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 13 deletions.
2 changes: 2 additions & 0 deletions openatlas/api/endpoints/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ def set_search_param(self) -> None:
values['logicalOperator'] = (
values.get('logicalOperator') or 'or')
check_search_parameters(category, values)
if category in app.config['INT_VALUES']:
values['values'] = list(map(int, values['values']))
if check_if_date_search(category):
try:
values["values"] = [
Expand Down
4 changes: 2 additions & 2 deletions openatlas/api/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"info": {
"title": "OpenAtlas API",
"description": "An API that allows user to access data from an OpenAtlas instance.",
"version": "0.4.4f",
"version": "0.4.5a",
"contact": {
"name": "OpenAtlas",
"url": "https://openatlas.eu",
Expand Down Expand Up @@ -1541,7 +1541,7 @@
},
"search": {
"name": "search",
"description": "Search query for specific results.\n\n **Filterable categories**\n\n entityName, entityDescription, entityAliases, entityCidocClass, entitySystemClass, entityID, typeID, valueTypeID, typeIDWithSubs, typeName, beginFrom, beginTo, endFrom, endTo, relationToID\n\n **Values** \n\n Values has to be a list of items. The items can be either a string, an integer or a tuple (see Notes). Strings need to be marked with \u201c\u201d or \u2018\u2019, while integers does not allow this.\\n *Notes*: \n The category valueTypeID can search for values of a type ID. But it takes one or more two valued Tuple as list entry: (x,y). x is the type id and y is the searched value. This can be an int or a float, e.g: `{\"operator\":\"lesserThan\",\"values\":[(3142,543.3)],\"logicalOperator\":\"and\"}`\n The date categories (beginFrom, beginTo, endFrom, endTo) only allow *one* value in the **values** field and it has to be formated the following way: YYYY-MM-DD. Month and day values need to filled up with 0, e.g. 800-01-01 \n\n **Compare operators** \n\n equal, notEqual, like (1), greaterThan (2), greaterThanEqual (2), lesserThan (2)\n\nThe compare operators work like the mathematical operators. equal x=y, notEqual x!=y, greaterThan x>y , greaterThanEqual x>=y, lesserThan x<y, lesserThanEqual x<=y. The like operator searches for occurrence of the string, so a match can also occur in the middle of a word.\n\n(1)Only for string based categories\n\n(2)Only for beginFrom, beginTo, endFrom, endTo, valueTypeID\n\n**Logical operators**\n\nNot mandatory, OR is the default value. Logical operators handles, if the values are treated as OR or AND.",
"description": "Search query for specific results.\n\n **Filterable categories**\n\n entityName, entityDescription, entityAliases, entityCidocClass, entitySystemClass, entityID, typeID, valueTypeID, typeIDWithSubs, typeName, beginFrom, beginTo, endFrom, endTo, relationToID\n\n **Values** \n\n Values has to be a list of items. The items can be either a string, an integer or a tuple (see Notes). Strings need to be marked with \u201c\u201d or \u2018\u2019, while integers does not allow this. \n \n *Notes*: \n The category valueTypeID can search for values of a type ID. But it takes one or more two valued Tuple as list entry: (x,y). x is the type id and y is the searched value. This can be an int or a float, e.g: `{\"operator\":\"lesserThan\",\"values\":[(3142,543.3)],\"logicalOperator\":\"and\"}`\n The date categories (beginFrom, beginTo, endFrom, endTo) only allow *one* value in the **values** field and it has to be formated the following way: YYYY-MM-DD. Month and day values need to filled up with 0, e.g. 800-01-01 \n\n **Compare operators** \n\n equal, notEqual, like (1), greaterThan (2), greaterThanEqual (2), lesserThan (2)\n\nThe compare operators work like the mathematical operators. equal x=y, notEqual x!=y, greaterThan x>y , greaterThanEqual x>=y, lesserThan x<y, lesserThanEqual x<=y. The like operator searches for occurrence of the string, so a match can also occur in the middle of a word.\n\n(1)Only for string based categories\n\n(2)Only for beginFrom, beginTo, endFrom, endTo, valueTypeID\n\n**Logical operators**\n\nNot mandatory, OR is the default value. Logical operators handles, if the values are treated as OR or AND. \n \n The following table outlines the supported operations for each field:\n\n| | equal | notEqual | like | greaterThan | greaterThanEqual | lesserThan | lesserThanEqual |\n|------------------|-----------|-----------|-----------|-------------|------------------|------------|-----------------|\n| entityName | x | x | x | | | | |\n| entityDescription| x | x | x | | | | |\n| entityAliases | x | x | x | | | | |\n| entityCidocClass | x | x | x | | | | |\n| entitySystemClass| x | x | x | | | | |\n| typeName | x | x | x | | | | |\n| entityID | x | x | | | | | |\n| typeID | x | x | | | | | |\n| valueTypeID | x | x | | x | x | x | x |\n| typeIDWithSubs | x | x | | | | | |\n| relationToID | x | x | | | | | |\n| beginFrom | x | x | | x | x | x | x |\n| beginTo | x | x | | x | x | x | x |\n| endFrom | x | x | | x | x | x | x |\n| endTo | x | x | | x | x | x | x |\n\n",
"in": "query",
"content": {
"application/json": {
Expand Down
4 changes: 4 additions & 0 deletions openatlas/api/resources/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ class OperatorError(Exception):
pass


class OperatorNotSupported(Exception):
pass


class QueryEmptyError(Exception):
pass

Expand Down
8 changes: 6 additions & 2 deletions openatlas/api/resources/search_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
from openatlas import app
from openatlas.api.resources.error import (
InvalidSearchCategoryError, InvalidSearchValueError, LogicalOperatorError,
NoSearchStringError, OperatorError, ValueNotIntegerError)
NoSearchStringError, OperatorError, OperatorNotSupported,
ValueNotIntegerError)


def check_if_date_search(k: str) -> bool:
Expand All @@ -23,6 +24,9 @@ def check_search_parameters(category: str, values: dict[str, Any]) -> None:
if category not in app.config['VALID_VALUES']:
raise InvalidSearchCategoryError
if category in app.config['INT_VALUES']:
if values['operator'] not in ['equal', 'notEqual']:
raise OperatorNotSupported
for value in values['values']:
if not isinstance(value, int):
raise ValueNotIntegerError
if not value.isdigit():
raise ValueNotIntegerError
16 changes: 8 additions & 8 deletions openatlas/static/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,33 @@
"@fortawesome/fontawesome-free": "^5.15.4",
"@mapbox/leaflet-pip": "^1.1.0",
"@popperjs/core": "^2.11.5",
"bootstrap-autocomplete": "2.3.7",
"@tanstack/table-core": "^8.20.5",
"bootstrap": "^5.1.3",
"bootstrap-autocomplete": "2.3.7",
"chart.js": "4.3.0",
"chartjs-plugin-autocolors": "0.2.2",
"d3": "^5.16.0",
"datatables.net": "^1.11.5",
"datatables.net-bs4": "^1.11.5",
"datatables.net-buttons-dt": "^1.7.1",
"datatables.net-buttons": "^1.7.1",
"datatables.net-buttons-dt": "^1.7.1",
"datatables.net-dt": "^1.11.5",
"datatables.net": "^1.11.5",
"huebee": "^2.1.1",
"jquery": "^3.6.0",
"jquery-ui-dist": "^1.13.1",
"jquery-validation": "^1.19.3",
"jquery": "^3.6.0",
"jstree": "^3.3.12",
"leaflet-imageoverlay-rotated": "^v0.2.1",
"leaflet": "^1.7.1",
"leaflet-draw": "^1.0.4",
"leaflet-iiif": "^3.0.0",
"leaflet-groupedlayercontrol": "^0.6.1",
"leaflet-iiif": "^3.0.0",
"leaflet-imageoverlay-rotated": "^v0.2.1",
"leaflet.fullscreen": "2.2.0",
"leaflet.markercluster": "^1.5.3",
"leaflet": "^1.7.1",
"mirador": "^3.3.0",
"save-svg-as-png": "^1.4.17",
"tinymce": "^5.10.3",
"wellknown": "^0.5.0"
},
"devDependencies": {},
"name": "openatlas"
}
19 changes: 18 additions & 1 deletion openatlas/views/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
InvalidSearchSyntax, InvalidSearchValueError, InvalidSystemClassError,
InvalidViewClassError, LastEntityError, LogicalOperatorError,
NoLicenseError, NoSearchStringError, NotAPlaceError, NotATypeError,
NotPublicError, OperatorError, QueryEmptyError, UrlNotValid,
NotPublicError, OperatorError, OperatorNotSupported, QueryEmptyError,
UrlNotValid,
ValueNotIntegerError)


Expand Down Expand Up @@ -248,6 +249,22 @@ def invalid_operator(_e: Exception) -> tuple[Any, int]:
'status': 400}), 400


@app.errorhandler(OperatorNotSupported)
def operator_not_supported(_e: Exception) -> tuple[Any, int]:
return jsonify({
'title': 'Operator not supported',
'message':
'Operator not supported for this search category.'
'"like" is only supported by entityName, entityDescription, '
'entityAliases, entityCidocClass, entitySystemClass, typeName.'
'"greaterThan", "greaterThanEqual", "lesserThan" and '
'"lesserThanEqual" are only supported by beginFrom, beginTo, '
'endFrom, endTo, valueTypeID',
'url': request.url,
'timestamp': datetime.now(),
'status': 400}), 400


@app.errorhandler(QueryEmptyError)
def empty_query(_e: Exception) -> tuple[Any, int]:
return jsonify({
Expand Down
8 changes: 8 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,14 @@ def test_api(self) -> None:
'"logicalOperator":"and"}]}'))
assert 'Invalid search value' in rv.get_json()['title']

rv = self.app.get(url_for(
'api_04.view_class',
view_class='place',
search='{"typeID":[{"operator":"like",'
'"values":["Boundary Mark", "Height", "Dimension"],'
'"logicalOperator":"and"}]}'))
assert 'Operator not supported' in rv.get_json()['title']

rv = self.app.get(url_for(
'api_04.view_class',
view_class='place',
Expand Down

0 comments on commit e1b888b

Please sign in to comment.