-
Notifications
You must be signed in to change notification settings - Fork 105
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
Localized & draft & ID_texts #677
base: main
Are you sure you want to change the base?
Changes from 3 commits
50cfe29
8699c9e
ba25cbb
ebb1653
b7a8a22
3bbf3ac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -425,6 +425,97 @@ Adding the annotation `@fiori.draft.enabled` won't work if the corresponding `_t | |
|
||
If you're editing data in multiple languages, the _General_ tab in the example above is reserved for the default language (often "en"). Any change to other languages has to be done in the _Translations_ tab, where a corresponding language can be chosen from a drop-down menu as illustrated above. This also applies if you use the URL parameter `sap-language` on the draft page. | ||
|
||
#### Background | ||
|
||
> TODO: find a good place for this section, maybe make it internal | ||
|
||
When we initially built draft support, the assumption was that most apps would not maintain | ||
translations for texts in the data (like product names and descriptions) via the UI, | ||
but do the translation externally and then bring in the translated texts via mass data upload. | ||
Thus the default is that if an entity is draft enabled via `@odata.draft.enabled`, | ||
the corresponding `.texts` entity is _not_ part of the draft tree, although it is a composition child of | ||
the main entity. | ||
|
||
If such a `.texts` entity should take part in the draft game, this must be explicitly switched | ||
stewsk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
on by also adding the annotation `@fiori.draft.enabled` to the main entity. | ||
This annotation does however not only include the `.texts` entity into the draft tree, but it also | ||
changes the key of the `.texts`entity. | ||
At the time draft support was implemented in CAP, Fiori required (TODO is this true?) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, this is true
stewsk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
that a draft enabled entity must have a single key element of type UUID. | ||
As a `.texts` entity by construction has at least two key elements (the `locale` plus the key elements | ||
of the main entity), we remove the `key` property from all these elements and add a technical key element | ||
`ID_texts` of type UUID. | ||
|
||
Example: | ||
```cds | ||
service S { | ||
@odata.draft.enabled | ||
@fiori.draft.enabled | ||
entity Books { | ||
key ID : Integer; | ||
title : localized String; | ||
} | ||
} | ||
``` | ||
Generated tables: | ||
```sql | ||
CREATE TABLE S_Books ( | ||
ID INTEGER NOT NULL, | ||
title NVARCHAR(255), | ||
PRIMARY KEY(ID) | ||
); | ||
CREATE TABLE S_Books_drafts ( | ||
ID INTEGER NOT NULL, | ||
title NVARCHAR(255) NULL, | ||
-- ... special draft fields | ||
PRIMARY KEY(ID) | ||
); | ||
CREATE TABLE S_Books_texts ( | ||
ID_texts NVARCHAR(36) NOT NULL, -- <-- new key field | ||
locale NVARCHAR(14), | ||
ID INTEGER, | ||
title NVARCHAR(255), | ||
PRIMARY KEY(ID_texts), | ||
CONSTRAINT S_Books_texts_locale UNIQUE (locale, ID) | ||
); | ||
CREATE TABLE S_Books_texts_drafts ( | ||
ID_texts NVARCHAR(36) NOT NULL, | ||
locale NVARCHAR(14) NULL, | ||
ID INTEGER NULL, | ||
title NVARCHAR(255) NULL, | ||
-- ... special draft fields | ||
PRIMARY KEY(ID_texts) | ||
); | ||
``` | ||
|
||
This is the current state, but it has another problem. The `.texts` entity now has a key column | ||
that the developer didn't define and doesn't need. So when providing initial data in a `csv` file, | ||
this column usually isn't part of it. | ||
|
||
Deployment (for PostgreSQL) has recently been improved to handle this. For each entry, the values of | ||
the original key elements are used to generate a hash value which is then used as value for | ||
`ID_texts`. It is important the the generated value is stable, so that upon redeployment the same values | ||
for `ID_texts` are produced. | ||
Comment on lines
+495
to
+498
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was not aware of this. I assume that the generated hash value adheres to the UUID format. Maybe we could invent an |
||
|
||
Today Fiori can also deal with composite keys with non-UUID types. For an entity with such a key, | ||
Fiori cannot generate an initial value. So when creating a new entry, a pop-up is launched asking | ||
the user to provide the key values. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would rather say that the backend doesn't allow key changes, hence Fiori Elements shows a popup to set the value once and doesn't allow to modify the value afterwards. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please add that to the text / change the text accordingly
David-Kunz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Is there a way to avoid this popup, but on the other hand keep the structure of the `.texts` entity | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it is possible via annotation to suppress the popup (don't ask me what it is). node backend generates values for all uuid key properties, regardless how many. so it might be possible to just prompt the user for the locale info... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure if it's possible to suppress the pop up for non-UUID keys. It's something, the user cannot change, even in draft mode, hence the moment the user 'hops out' of the field, it would need to become immutable - Fiori elements can't do that. |
||
and table unchanged? | ||
|
||
The basic idea is to have in the CDS runtime and for the database a `.texts` entity and table with | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so it would be the following?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the basic idea for what? |
||
the original structure, but a `.texts.drafts` entity and table with `ID_texts` as key. | ||
The entity in the OData API would also have the `ID_texts` key. | ||
|
||
This only works, however, if we can guarantee that Fiori never sends a query based on `ID_texts`. | ||
So, an ObjectPage for a text entry would not work. | ||
|
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue: when creating the new instance, we need to generate the id in the backend. at that point, however, we don't yet know the intended locale -> anything that tries to concatenate a fake id field on read (e.g., There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Not during runtime, only when doing the CSV import, so it should be fine. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In CAP Java CSVs are also uploaded by the runtime (in case of in-memory DBs). We chould have a well-defined hashing algorithm, which is used accross the runtimes. |
||
|
||
|
||
|
||
|
||
### Validating Drafts | ||
|
||
You can add [custom handlers](../guides/providing-services#custom-logic) to add specific validations, as usual. In addition, for a draft, you can register handlers to the `PATCH` events to validate input per field, during the edit session, as follows. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could also add a link from here: https://pages.github.tools.sap/cap/docs/guides/localized-data#behind-the-scenes