diff --git a/resources/server/api/ogc/static/style.css b/resources/server/api/ogc/static/style.css
index 4f551095b3d..41d47d5f103 100644
--- a/resources/server/api/ogc/static/style.css
+++ b/resources/server/api/ogc/static/style.css
@@ -5,7 +5,32 @@ a { color: green; }
height: 400px;
}
-
.card-header span.small {
font-size: 70%;
}
+
+.path-button {
+ text-transform: uppercase;
+}
+
+.path-path {
+ font-weight: bold;
+}
+
+.model-toggle {
+ font-weight: bold;
+}
+
+.model-toggle::after {
+ display: inline-block;
+ vertical-align: bottom;
+ width: 20px;
+ height: 20px;
+ content: "";
+ background: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z'/%3E%3C/svg%3E") 50% no-repeat;
+ background-size: 100%;
+}
+
+.top-buffer {
+ margin-top:20px;
+}
diff --git a/resources/server/api/ogc/templates/wfs3/getApiDescription.html b/resources/server/api/ogc/templates/wfs3/getApiDescription.html
index 7a2f0fcbef5..fa9eed90a8b 100644
--- a/resources/server/api/ogc/templates/wfs3/getApiDescription.html
+++ b/resources/server/api/ogc/templates/wfs3/getApiDescription.html
@@ -1,170 +1,180 @@
{% include "header.html" %}
-
API description
+
+
+
API description
+
Info
+
+ - Description
+ - {{ info.description }}
+ - Title
+ - {{ info.title }}
+ - Contact email
+ - {{ info.contact.email }}
+ - Contact name
+ - {{ info.contact.name }}
+
+
+
- Info
-
- - Description
- - {{ info.description }}
- - Title
- - {{ info.title }}
- - Contact email
- - {{ info.contact.email }}
- - Contact name
- - {{ info.contact.name }}
-
-
- Paths
-
-
- {% for path, path_info in paths %}
- {% for method, method_data in path_info %}
-
-
-
-
- - OperationId
- - {{ method_data.operationId }}
-
- Tags
- - {{ method_data.tags }}
-
- Description
- - {{ method_data.description }}
- {% if existsIn(method_data, "parameters") %}
- - Parameters
- -
-
-
-
- Name |
- Description |
- Type |
-
-
-
- {% for param in method_data.parameters %}
- {% if existsIn(param, "name") %}
-
- {{ param.name }} |
- {{ param.description }} |
- {{ param.schema.type }} |
-
- {% else %}
-
-
- {{ param }}
- |
+
+
+
Paths
+
+
+ {% for path, path_info in paths %}
+ {% for method, method_data in path_info %}
+
+
+
+
+ - OperationId
+ - {{ method_data.operationId }}
+
- Tags
+ - {{ method_data.tags }}
+
- Description
+ - {{ method_data.description }}
+ {% if existsIn(method_data, "parameters") %}
+ - Parameters
+ -
+
+
+
+ Name |
+ Description |
+ Type |
+
+
+
+ {% for param in method_data.parameters %}
+ {% if existsIn(param, "name") %}
+
+ {{ param.name }} |
+ {{ param.description }} |
+ {{ param.schema.type }} |
+
+ {% else %}
+
+
+ {{ param }}
+ |
+ {% endif %}
+ {% endfor %}
+
+
+
{% endif %}
- {% endfor %}
-
-
-
- {% endif %}
- - Responses
- - {{ method_data.responses}}
-
-
-
-
- {% endfor %}
- {% endfor %}
-
-
-
- Models
-
-
- {% for schema_name, schema_model in components.schemas %}
-
-
-
-
- - Type
- - {{ schema_model.type }}
-
- Properties
- -
-
-
-
- Name |
- Description |
- Type |
- Example |
-
-
-
- {% for property_name, property_data in schema_model.properties %}
- {% if existsIn(property_data, "example") and existsIn(property_data, "description") %}
-
- {{ property_name }} |
- {{ property_data.description }} |
- {{ property_data.type }} |
-
- {% if isArray(property_data.example) %}
-
- {% for example in property_data.example %}
- - {{ example }}
- {% endfor %}
-
- {% else %}
- {{ property_data.example }}
- {% endif %}
- |
-
- {% else %}
-
- {{ property_name }} |
-
- {{ property_data }}
- |
- {% endif %}
- {% endfor %}
-
-
-
- - Required
- -
-
- {% for req in schema_model.required %}
- - {{ req }}
- {% endfor %}
-
-
-
-
-
-
- {% endfor %}
-
-
+ Responses
+ {{ method_data.responses}}
+
+
+
+ {% endfor %}
+ {% endfor %}
+
+
+
+
+
+
+
Models
+
+
+ {% for schema_name, schema_model in components.schemas %}
+
+
+
+
+ - Type
+ - {{ schema_model.type }}
+
- Properties
+ -
+
+
+
+ Name |
+ Description |
+ Type |
+ Example |
+
+
+
+ {% for property_name, property_data in schema_model.properties %}
+ {% if existsIn(property_data, "example") and existsIn(property_data, "description") %}
+
+ {{ property_name }} |
+ {{ property_data.description }} |
+ {{ property_data.type }} |
+
+ {% if isArray(property_data.example) %}
+
+ {% for example in property_data.example %}
+ - {{ example }}
+ {% endfor %}
+
+ {% else %}
+ {{ property_data.example }}
+ {% endif %}
+ |
+
+ {% else %}
+
+ {{ property_name }} |
+
+ {{ property_data }}
+ |
+ {% endif %}
+ {% endfor %}
+
+
+
+ - Required
+ -
+
+ {% for req in schema_model.required %}
+ - {{ req }}
+ {% endfor %}
+
+
+
+
+
+ {% endfor %}
+
+
+
+
{% include "footer.html" %}
diff --git a/src/server/services/wfs3/qgswfs3handlers.cpp b/src/server/services/wfs3/qgswfs3handlers.cpp
index 3e60c6df360..8ea1106df6f 100644
--- a/src/server/services/wfs3/qgswfs3handlers.cpp
+++ b/src/server/services/wfs3/qgswfs3handlers.cpp
@@ -98,6 +98,12 @@ void QgsWfs3APIHandler::handleRequest( const QgsServerApiContext &context ) cons
}
};
+ // Add links only if not OPENAPI3 to avoid validation errors
+ if ( QgsServerOgcApiHandler::contentTypeFromRequest( context.request() ) != QgsServerOgcApi::ContentType::OPENAPI3 )
+ {
+ data["links"] = links( context );
+ }
+
// Gather path information from handlers
json paths = json::array();
for ( const auto &h : mApi->handlers() )