You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2020/05/22 21:58:24 UTC
[airavata-django-portal] branch
AIRAVATA-3324-custom-input-editor-autocomplete-input-editor updated:
AIRAVATA-3324 Adding documentation
This is an automated email from the ASF dual-hosted git repository.
machristie pushed a commit to branch AIRAVATA-3324-custom-input-editor-autocomplete-input-editor
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git
The following commit(s) were added to refs/heads/AIRAVATA-3324-custom-input-editor-autocomplete-input-editor by this push:
new a9b69c3 AIRAVATA-3324 Adding documentation
a9b69c3 is described below
commit a9b69c38cc69b003a9e3fa35266ed7c7c7c823da
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Fri May 22 17:17:35 2020 -0400
AIRAVATA-3324 Adding documentation
---
docs/admin/app_inputs.md | 268 +++++++++++++++++++++++++++++++++++++
docs/images/app-input-metadata.png | Bin 0 -> 244374 bytes
mkdocs.yml | 1 +
3 files changed, 269 insertions(+)
diff --git a/docs/admin/app_inputs.md b/docs/admin/app_inputs.md
new file mode 100644
index 0000000..4d1b4b1
--- /dev/null
+++ b/docs/admin/app_inputs.md
@@ -0,0 +1,268 @@
+# Advanced Applicaton Input Configuration
+
+The Airavata Django Portal supports customization of the user interface used to
+configure an application input. For example, instead of the default text input
+box for a string input, with customization the UI can be configured to be a drop
+down list of options.
+
+To configure application inputs one needs to provide JSON configuration in the
+**Advanced Input Field Modification Metadata** field of the application input.
+To get there:
+
+1. Select **Settings** from the drop down menu in the header.
+2. You should see the **Application Catalog**. If not, click the gears icon on
+ the left hand side.
+3. Select the application you want to configure by clicking on it.
+4. Select the _Interface_ tab.
+5. Scroll down to the _Input Field_ that you want to customize then scroll down
+ to the **Advanced Input Field Modification Metadata** text box. This is the
+ field where you will input your JSON configuration. This field will outline
+ in green when the JSON is valid and in red when invalid. See the following
+ screenshot.
+
+![Screenshot of Application Interface editor, highlighting the input JSON metadata field](../images/app-input-metadata.png)
+
+## Validation
+
+### Example
+
+```json
+{
+ "editor": {
+ "ui-component-id": "textarea-input-editor",
+ "config": {
+ "rows": 6
+ },
+ "validations": [
+ {
+ "type": "min-length",
+ "value": 10
+ },
+ {
+ "type": "max-length",
+ "value": 200
+ },
+ {
+ "type": "regex",
+ "value": "^[XYL\\s]+$",
+ "message": "Target sequence may only contain letters X, Y and L."
+ }
+ ]
+ }
+}
+```
+
+## Dependencies
+
+You can hide/show inputs based on the values of other inputs. For example, if
+the option selected in input A is 'list-of-urls' then you can have input B show
+a field to upload a file.
+
+### Example
+
+```json
+{
+ "editor": {
+ "dependencies": {
+ "show": {
+ "Select reading options": {
+ "comparison": "equals",
+ "value": "list-urls"
+ }
+ }
+ }
+ }
+}
+```
+
+## Alternate UI Components
+
+### Checkboxes
+
+#### Example
+
+```json
+{
+ "editor": {
+ "ui-component-id": "checkbox-input-editor",
+ "config": {
+ "options": [
+ {
+ "value": "a",
+ "text": "A label"
+ },
+ {
+ "value": "b",
+ "text": "B label"
+ },
+ {
+ "value": "c",
+ "text": "C label"
+ }
+ ]
+ }
+ }
+}
+```
+
+### Radio Buttons
+
+#### Example
+
+```json
+{
+ "editor": {
+ "ui-component-id": "radio-button-input-editor",
+ "config": {
+ "options": [
+ {
+ "value": "breakfast",
+ "text": "Breakfast"
+ },
+ {
+ "value": "lunch",
+ "text": "Lunch"
+ },
+ {
+ "value": "dinner",
+ "text": "Dinner"
+ }
+ ]
+ }
+ }
+}
+```
+
+### Selects
+
+#### Example
+
+```json
+{
+ "editor": {
+ "ui-component-id": "select-input-editor",
+ "config": {
+ "options": [
+ {
+ "value": "breakfast",
+ "text": "Breakfast"
+ },
+ {
+ "value": "lunch",
+ "text": "Lunch"
+ },
+ {
+ "value": "dinner",
+ "text": "Dinner"
+ }
+ ]
+ }
+ }
+}
+```
+
+### Autocomplete
+
+The Autocomplete UI component looks up matching entries for the given substring
+typed by the user. This one requires that a custom Django app be developed to
+implement the REST API for returning autocomplete suggestions.
+
+#### REST API contract
+
+- URL is called with query parameter search with value of whatever the user
+ has currently typed
+- URL should return a JSON response with a search key and the value of that
+ key used for the search and an results key with a list matching results,
+ limited to the top 10. Each result should have a text key with the text
+ displayed to the user and a value key which is the value applied to the
+ experiment input if selected. For example:
+
+```json
+{
+ "search": "mammal",
+ "results": [
+ {
+ "text": "Horse",
+ "value": "horse"
+ },
+ {
+ "text": "Mouse",
+ "value": "mouse"
+ }
+ ]
+}
+```
+
+- URL can also be called with query parameter exact with a value that was
+ previously returned. This call is made by the UI to retrieve the "text"
+ value to display to the user for this value. The JSON response should be
+ similar to the above except that it should only have one result:
+
+```json
+{
+ "search": "horse",
+ "results": [
+ {
+ "text": "Horse",
+ "value": "horse"
+ }
+ ]
+}
+```
+
+- If the exact query parameter is specified and there is no match for that
+ value, the JSON response should have HTTP status 404. The error reason can
+ be added to the "detail" key of the response body, for example:
+
+```json
+{
+ "detail": "No matching value was found."
+}
+```
+
+#### Example REST API implementation
+
+To create the REST API backend needed by the Autocomplete component, first you need a create a custom Django app. See [Custom Django Apps](../dev/custom_django_app) for more information.
+
+Here's a simple implementation of a view function that looks up words in the system dictionary file:
+
+```python
+def test_autocomplete_search(request):
+ """Find matching words for given search string."""
+ import re
+ if 'search' in request.GET:
+ query = request.GET['search']
+ pattern = re.compile(re.escape(query), re.IGNORECASE)
+ elif 'exact' in request.GET:
+ query = request.GET['exact']
+ pattern = re.compile(r"^" + re.escape(query) + r"$")
+ else:
+ return generic_json_exception_response(
+ "Missing required query parameter: one of 'search' or 'exact'", status=400)
+
+ matches = []
+ with open("/usr/share/dict/words", 'r') as f:
+ matches = [line.strip() for line in f if pattern.search(line)]
+ # TODO: if 'exact', make sure len(matches) == 1. if 0, then return 404
+ if 'exact' in request.GET and len(matches) == 0:
+ return generic_json_exception_response(f"No match for exact = {request.GET['exact']}", status=404)
+ return JsonResponse({
+ "search": query,
+ "results": [{"text": m, "value": m} for m in matches[:20]]
+ })
+```
+
+See also a real world example [miga-autocomplete](https://github.com/bio-miga/miga-autocomplete).
+
+#### Example Input Metadata Configuration
+
+```json
+{
+ "editor": {
+ "ui-component-id": "autocomplete-input-editor",
+ "config": {
+ "url": "/custom/search/"
+ }
+ }
+}
+```
diff --git a/docs/images/app-input-metadata.png b/docs/images/app-input-metadata.png
new file mode 100644
index 0000000..b9a8f87
Binary files /dev/null and b/docs/images/app-input-metadata.png differ
diff --git a/mkdocs.yml b/mkdocs.yml
index 7740248..74cecb1 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -13,6 +13,7 @@ nav:
- Developing the Backend: dev/developing_backend.md
- Developing a Wagtail Export (theme): dev/wagtail_export.md
- Administrator Guide:
+ - Application Input Customization: admin/app_inputs.md
- Tusd Installation: admin/tusd.md
- Tutorials:
- Gateways 2019: tutorial/gateways2019_tutorial.md