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

Add term UI.UserInteraction #61

Draft
wants to merge 100 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
e40b835
Update UI.xml
HeikoTheissen Oct 7, 2020
ff3fa69
Update UI.xml
HeikoTheissen Oct 7, 2020
adfb6b4
auto-refreshed
HeikoTheissen Oct 7, 2020
ea68f0c
Update UI.xml
HeikoTheissen Oct 8, 2020
e851f08
auto-refreshed
HeikoTheissen Oct 8, 2020
855876a
Update vocabularies/UI.xml
HeikoTheissen Dec 9, 2020
d52ab81
auto-refreshed
HeikoTheissen Dec 9, 2020
cda25ca
Update UI.xml
HeikoTheissen Dec 9, 2020
71af81b
auto-refreshed
HeikoTheissen Dec 9, 2020
6549b26
Create com.sap.vocabularies.UI.v1.UserInteraction-sample.xml
HeikoTheissen Dec 9, 2020
84c3df8
Update com.sap.vocabularies.UI.v1.UserInteraction-sample.xml
HeikoTheissen Dec 9, 2020
bd3a5eb
Merge branch 'master' into UI.UserInteraction
ralfhandl Dec 9, 2020
53695b4
Merge branch 'master' into UI.UserInteraction
ralfhandl Dec 9, 2020
3ab2a7f
Update UI.xml
HeikoTheissen Dec 9, 2020
bf02b7e
auto-refreshed
HeikoTheissen Dec 9, 2020
8b3ff09
Update com.sap.vocabularies.UI.v1.UserInteraction-sample.xml
HeikoTheissen Dec 9, 2020
398ce9c
Update UI.xml
HeikoTheissen Dec 9, 2020
1cad142
auto-refreshed
HeikoTheissen Dec 9, 2020
fa83b9a
Update com.sap.vocabularies.UI.v1.UserInteraction-sample.xml
HeikoTheissen Dec 9, 2020
f0262e2
Re-use Common.ValueListParameterOut type
HeikoTheissen Dec 9, 2020
e3e74b7
auto-refreshed
HeikoTheissen Dec 9, 2020
6dd2d61
Update UI.xml
HeikoTheissen Dec 9, 2020
a43816b
auto-refreshed
HeikoTheissen Dec 9, 2020
801d482
Update UI.xml
HeikoTheissen Dec 9, 2020
b584586
auto-refreshed
HeikoTheissen Dec 9, 2020
3e51d37
Update UI.xml
HeikoTheissen Dec 9, 2020
3558583
auto-refreshed
HeikoTheissen Dec 9, 2020
04f7ac7
Update com.sap.vocabularies.UI.v1.UserInteraction-sample.xml
HeikoTheissen Dec 9, 2020
e0adb8c
Update UI.xml
HeikoTheissen Feb 12, 2021
ca3b8a0
auto-refreshed
HeikoTheissen Feb 12, 2021
c25e19b
Update com.sap.vocabularies.UI.v1.UserInteraction-sample.xml
HeikoTheissen Feb 12, 2021
66a0f8d
Merge remote-tracking branch 'origin/master' into UI.UserInteraction
HeikoTheissen Feb 27, 2021
2fab035
Update nodejs.yml
ralfhandl Feb 8, 2021
07c3e09
moved example
HeikoTheissen Feb 27, 2021
f25f3ed
typo
HeikoTheissen May 26, 2021
a8258de
Merge remote-tracking branch 'origin/master' into UI.UserInteraction
HeikoTheissen May 26, 2021
c7ce8fc
minor rephrasing
HeikoTheissen May 26, 2021
33cee04
Derived types instead of enumerated values for interaction method
HeikoTheissen May 26, 2021
0a1e0ae
Redo lost changes
HeikoTheissen May 26, 2021
d0bef64
More detail for ChooseMultiple
HeikoTheissen May 27, 2021
54b0341
removed AppliesViaContainer
HeikoTheissen May 29, 2021
3536738
Allow user interaction via odata.navigationLink
HeikoTheissen Jun 1, 2021
30ae3e2
Merge remote-tracking branch 'origin/master' into UI.UserInteraction
HeikoTheissen Jun 1, 2021
1f58244
Avoid JSON-specific @ prefix
HeikoTheissen Jun 1, 2021
6912e47
Instance annotation suggested by @uhlmannm
HeikoTheissen Jun 2, 2021
31108f6
Rephrasing
HeikoTheissen Jun 2, 2021
a454bbd
revert userInteraction instance annotation
HeikoTheissen Jun 2, 2021
a6f99fa
markdown error
HeikoTheissen Jun 2, 2021
c8282bc
format of innererror
HeikoTheissen Jun 2, 2021
2e55feb
Readability
HeikoTheissen Jun 2, 2021
20a5303
rephrasing
HeikoTheissen Jun 2, 2021
bd6b0d9
new vocabulary for Edm.Untyped annotation
HeikoTheissen Jun 2, 2021
8f40118
rephrasing
HeikoTheissen Jun 2, 2021
0912f97
ConflictResponse -> ErrorResponse
HeikoTheissen Jun 2, 2021
71a3266
ErrorResponse -> Common_401
HeikoTheissen Jun 2, 2021
cd02062
README.md
HeikoTheissen Jun 7, 2021
41ff3c6
userInteraction -> callback
HeikoTheissen Jun 7, 2021
5a1120e
rephrasing
HeikoTheissen Jun 7, 2021
89d63a1
typos
HeikoTheissen Jun 9, 2021
8ed1c65
Merge remote-tracking branch 'origin/master' into UI.UserInteraction
HeikoTheissen Jun 21, 2021
87a8947
Merge remote-tracking branch 'origin/master' into UI.UserInteraction
HeikoTheissen Jul 6, 2021
857751f
Merge remote-tracking branch 'origin/master' into UI.UserInteraction
HeikoTheissen Jul 7, 2021
7f80597
touch README.md
HeikoTheissen Jul 7, 2021
cc82be0
touch README.md again
HeikoTheissen Jul 7, 2021
46caf20
Update README.md
ralfhandl Jul 7, 2021
a381de1
avoid "immediate"
HeikoTheissen Jul 7, 2021
c4f99b8
dummy
HeikoTheissen Jul 8, 2021
c4a6da9
Merge remote-tracking branch 'origin/main' into UI.UserInteraction
HeikoTheissen Jul 9, 2021
70bf3d6
Merge remote-tracking branch 'origin/main' into UI.UserInteraction
HeikoTheissen Jul 14, 2021
004b2a9
Merge remote-tracking branch 'origin/main' into UI.UserInteraction
HeikoTheissen Aug 6, 2021
809bd40
master -> main
HeikoTheissen Aug 12, 2021
13dde90
Merge remote-tracking branch 'origin/main' into UI.UserInteraction
HeikoTheissen Sep 28, 2021
bf333c0
Detailed example
HeikoTheissen Sep 28, 2021
e976d4e
Merge remote-tracking branch 'origin/main' into UI.UserInteraction
HeikoTheissen Dec 8, 2021
d3e915c
Detailed example
HeikoTheissen Jan 4, 2022
a2cefce
nullability
HeikoTheissen Jan 4, 2022
4f924de
Merge remote-tracking branch 'origin/main' into UI.UserInteraction
HeikoTheissen Jan 4, 2022
b765f5a
clicks -> triggers
HeikoTheissen Jan 4, 2022
3b3cc97
rephrasing
HeikoTheissen Jan 4, 2022
0039844
rephrasing
HeikoTheissen Jan 5, 2022
17df8da
rephrasing
HeikoTheissen Jan 5, 2022
0f87507
Avoid Collection(Edm.PrimitiveType)
HeikoTheissen Jan 20, 2022
d56e10d
DataField.Value does not allowed mixed-type collections
HeikoTheissen Jun 9, 2022
b88c1a2
+Edm.Double
HeikoTheissen Jun 9, 2022
c36cfa8
+Edm.Byte, +Edm.String
HeikoTheissen Jun 9, 2022
f5c6626
Merge remote-tracking branch 'origin/ODATA-1498' into UI.UserInteraction
HeikoTheissen Jun 10, 2022
334f46e
Merge remote-tracking branch 'origin/main' into UI.UserInteraction
HeikoTheissen Jul 26, 2022
acf4910
Merge remote-tracking branch 'origin/main' into UI.UserInteraction
HeikoTheissen Sep 6, 2022
138cc5d
Merge remote-tracking branch 'origin/main' into UI.UserInteraction
HeikoTheissen Apr 13, 2023
103b85c
Merge remote-tracking branch 'origin/main' into UI.UserInteraction
HeikoTheissen Apr 28, 2023
b2f5854
Merge remote-tracking branch 'origin/main' into UI.UserInteraction
HeikoTheissen Dec 12, 2023
c88dbcf
Remedial action via action
HeikoTheissen Dec 13, 2023
4d2a927
jsonc
HeikoTheissen Dec 13, 2023
3467120
Merge remote-tracking branch 'origin/main' into UI.UserInteraction
HeikoTheissen Dec 13, 2023
fda2d8b
Corrected example
HeikoTheissen Dec 13, 2023
eadfe5e
UI.UserInteractionResolveConflict
HeikoTheissen Dec 13, 2023
8c34ac5
Merge remote-tracking branch 'origin/main' into UI.UserInteraction
HeikoTheissen Jul 29, 2024
ad404e0
Mandatory vs. optional user interactions
HeikoTheissen Jan 14, 2025
d58d6cb
Merge remote-tracking branch 'origin/main' into UI.UserInteraction
HeikoTheissen Jan 14, 2025
2925e36
Optional user interaction
HeikoTheissen Jan 14, 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
67 changes: 67 additions & 0 deletions examples/UI.UserInteraction-sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"$Version": "4.0",
"$Reference": {
"https://sap.github.io/odata-vocabularies/vocabularies/UI.json": {
"$Include": [{ "$Namespace": "com.sap.vocabularies.UI.v1", "$Alias": "UI" }]
}
},
"userinteraction.sample": {
"$Alias": "self",
"AlternativeProduct": {
"$Kind": "EntityType",
"Product": {},
"UpsellNote": {},
"@UI.LineItem": [
{
"@odata.type": "https://sap.github.io/odata-vocabularies/vocabularies/UI.xml#UI.DataField",
"Label": "Alternative Product",
"Value": { "$Path": "Product" }
},
{
"@odata.type": "https://sap.github.io/odata-vocabularies/vocabularies/UI.xml#UI.DataField",
"Label": "Why it's better to buy this",
"Value": { "$Path": "UpsellNote" }
}
]
},
"SalesOrderItem": {
"$Kind": "EntityType",
"_AlternativeProducts": {
"$Kind": "NavigationProperty",
"$Collection": true,
"$Type": "self.AlternativeProduct",
"@[email protected]": "Please choose a product",
"@UI.UserInteraction": {
"@odata.type": "https://sap.github.io/odata-vocabularies/vocabularies/UI.xml#UI.UserInteractionChooseSingle",
"Parameters": [{ "ValueListProperty": "Product", "LocalDataProperty": "self.ExchangeProduct/NewProduct" }]
}
},
"_UpgradeProduct": {
"$Kind": "NavigationProperty",
"$Type": "self.AlternativeProduct",
"$Nullable": true,
"@[email protected]": "Do you want to upgrade the product?",
"@UI.UserInteraction": {
"@odata.type": "https://sap.github.io/odata-vocabularies/vocabularies/UI.xml#UI.UserInteractionConfirm",
"Parameters": [{ "ValueListProperty": "Product", "LocalDataProperty": "self.ExchangeProduct/NewProduct" }]
}
}
},
"ExchangeProduct": [
{
"$Kind": "Action",
"$IsBound": true,
"$Parameter": [
{ "$Name": "item", "$Type": "self.SalesOrderItem" },
{ "$Name": "NewProduct", "$Nullable": true }
],
"$ReturnType": { "$Type": "self.SalesOrderItem", "$Nullable": true }
}
],
"SalesOrderService": {
"$Kind": "EntityContainer",
"SalesOrderItems": { "$Collection": true, "$Type": "self.SalesOrder" }
}
},
"$EntityContainer": "userinteraction.sample.SalesOrderService"
}
87 changes: 87 additions & 0 deletions examples/UI.UserInteraction-sample.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Modelling a user interaction with annotations

Certain user interactions cannot be handled by one request, because they follow the pattern "user triggers, server offers, user chooses". For example, the action "exchange product in a sales order item" is triggered by the user on a sales order item, the server returns the item with an inlined collection of alternative products, from which the user must then choose, and the request is repeated with the chosen product.

In the "upgrade case", the server returns only one alternative product and lets the user confirm rather than choose. Both cases (exchange and upgrade) are supported by a service with [these metadata](UI.UserInteraction-sample.xml), let's look at an example of the exchange case where the user chooses.

## User triggers

The "exchange product" action is triggered by the user on a sales order item without specifying a parameter.

```
POST SalesOrderItems(...)/userinteraction.sample.ExchangeProduct HTTP/1.1
Content-Type: application/json

{}
```

## Server offers

The server returns the item with an inlined collection of alternative products, from which the user must then choose.

```
HTTP/1.1 409 Conflict
Content-Type: application/json

{
"Order": "A",
"Item": "010",
"Product": "Wheat flour",
"_AlternativeProducts": [
{"Product": "Rice", "UpsellNote": "Healthier"},
{"Product": "Noodles", "UpsellNote": "Tastes better"}
]
}
```

Servers that cannot send a structured payload in a 4xx response may instead return an error message with a [`Common.callback`](../vocabularies/Common.md#callback) instance annotation.

```
HTTP/1.1 400 Bad Request
Content-Type: application/json

{
"error": {
"code": "UF0",
"message": {
"lang": "en",
"value": "Missing parameter 'NewProduct'"
},
"@Common.callback": {
"Order": "A",
"Item": "010",
"Product": "Wheat flour",
"_AlternativeProducts": [
{"Product": "Rice", "UpsellNote": "Healthier"},
{"Product": "Noodles", "UpsellNote": "Tastes better"}
]
}
}
}
```

Upon receiving either of these payloads, the client constructs a user dialog based on (a) the `UI.UserInteraction` annotation of the `_AlternativeProducts` navigation property and (b) the UI annotations of the `AlternativeProduct` entity type. The [type](../vocabularies/UI.md#UserInteractionChooseSingle) of the `UI.UserInteraction` annotation implies that this is a choice popup, not a confirmation prompt. The superscripted headings in the popup also come from the annotations.

> ### Please choose a product<sup>a</sup>
>
> |Alternative Product<sup>b</sup>|Why it's better to buy this<sup>b</sup>|
> |-------------------------------|---------------------------------------|
> |Rice |Healthier |
> |Noodles |Tastes better |
>
> <kbd>OK</kbd> <kbd>Cancel</kbd>

## User chooses

After the user has chosen, the client repeats the request with the chosen product inserted according to the `UI.UserInteraction/Parameters`.

```
POST SalesOrderItems(...)/userinteraction.sample.ExchangeProduct HTTP/1.1
Content-Type: application/json

{"NewProduct": "Rice"}
```

The status 409 in the first response implies that the first request made no changes on the server. As a consequence
* if the first request had been a POST on a collection, the second request would again be a POST (not a PATCH)
* no second request is made if the user has canceled the popup (no clean-up needed).
66 changes: 66 additions & 0 deletions examples/UI.UserInteraction-sample.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8" ?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
<edmx:Reference Uri="https://sap.github.io/odata-vocabularies/vocabularies/UI.xml">
<edmx:Include Namespace="com.sap.vocabularies.UI.v1" Alias="UI" />
</edmx:Reference>
<edmx:DataServices>
<Schema Namespace="userinteraction.sample" Alias="self" xmlns="http://docs.oasis-open.org/odata/ns/edm">
<EntityType Name="AlternativeProduct">
<Property Name="Product" Type="Edm.String" Nullable="false"/>
<Property Name="UpsellNote" Type="Edm.String" Nullable="false"/>
<Annotation Term="UI.LineItem">
<Collection>
<Record Type="UI.DataField">
<PropertyValue Property="Label" String="Alternative Product"/>
<PropertyValue Property="Value" Path="Product"/>
</Record>
<Record Type="UI.DataField">
<PropertyValue Property="Label" String="Why it's better to buy this"/>
<PropertyValue Property="Value" Path="UpsellNote"/>
</Record>
</Collection>
</Annotation>
</EntityType>
<EntityType Name="SalesOrderItem">
<NavigationProperty Name="_AlternativeProducts" Type="Collection(self.AlternativeProduct)">
<Annotation Term="UI.UserInteraction">
<Annotation Term="Core.Description" String="Please choose a product"/>
<Record Type="UI.UserInteractionChooseSingle">
<PropertyValue Property="Parameters">
<Collection>
<Record>
<PropertyValue Property="ValueListProperty" String="Product"/>
<PropertyValue Property="LocalDataProperty" PropertyPath="self.ExchangeProduct/NewProduct"/>
</Record>
</Collection>
</PropertyValue>
</Record>
</Annotation>
</NavigationProperty>
<NavigationProperty Name="_UpgradeProduct" Type="self.AlternativeProduct">
<Annotation Term="UI.UserInteraction">
<Annotation Term="Core.Description" String="Do you want to upgrade the product?"/>
<Record Type="UI.UserInteractionConfirm">
<PropertyValue Property="Parameters">
<Collection>
<Record>
<PropertyValue Property="ValueListProperty" String="Product"/>
<PropertyValue Property="LocalDataProperty" PropertyPath="self.ExchangeProduct/NewProduct"/>
</Record>
</Collection>
</PropertyValue>
</Record>
</Annotation>
</NavigationProperty>
</EntityType>
<Action Name="ExchangeProduct" IsBound="true">
<Parameter Name="item" Type="self.SalesOrderItem" Nullable="false"/>
<Parameter Name="NewProduct" Type="Edm.String"/>
<ReturnType Type="self.SalesOrderItem"/>
</Action>
<EntityContainer Name="SalesOrderService">
<EntitySet Name="SalesOrderItems" EntityType="self.SalesOrder"/>
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
12 changes: 12 additions & 0 deletions vocabularies/Common.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
"https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Aggregation.V1.json": {
"$Include": [{ "$Namespace": "Org.OData.Aggregation.V1", "$Alias": "Aggregation" }]
},
"https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.JSON.V1.json": {
"$Include": [{ "$Namespace": "Org.OData.JSON.V1", "$Alias": "JSON" }]
},
"https://sap.github.io/odata-vocabularies/vocabularies/UI.json": {
"$Include": [{ "$Namespace": "com.sap.vocabularies.UI.v1", "$Alias": "UI" }]
},
Expand Down Expand Up @@ -1351,6 +1354,15 @@
"@Common.Experimental": true,
"@Core.Description": "Channel for WebSocket connections",
"@Core.LongDescription": "Messages sent over the channel follow the [ABAP Push Channel Protocol](https://community.sap.com/t5/application-development-blog-posts/specification-of-the-push-channel-protocol-pcp/ba-p/13137541).\nTo consume a channel, the client opens a web socket connection at the [`WebSocketBaseURL`](#WebSocketBaseURL)\nfollowed by URL parameters\n- parameter name = annotation qualifier, parameter value = channel ID (see below)\n- parameter name = `relatedService`, parameter value = base URL (relative to server root) of the OData service of the app\n\n<dl>Supported qualifiers and channel IDs:\n<dt>`sideEffects` <dd>Notifications about side effects to be triggered by the client (channel ID = non-null annotation value)\n</dl>"
},
"callback": {
"$Kind": "Term",
"$Type": "JSON.JSON",
"$AppliesTo": ["Record"],
"@Common.Experimental": true,
"@Common.IsInstanceAnnotation": true,
"@Core.Description": "Data that the server has embedded within an error response to make a callback to the client",
"@Core.LongDescription": "This instance annotation has the format of a [message body](https://docs.oasis-open.org/odata/odata-json-format/v4.01/odata-json-format-v4.01.html#sec_MessageBody)\n that could be a valid response to the given request.\n The callback allows the client to adjust the request so that it can be successfully repeated.\n An example for such a callback is a user interaction to resolve a conflict that was detected by the server,\n see [`UI.UserInteraction`](UI.md#UserInteraction)."
}
}
}
Loading
Loading