From 50cfe29d12e03bf776ffe02fce2a027b24126a2e Mon Sep 17 00:00:00 2001 From: Steffen Weinstock <79531202+stewsk@users.noreply.github.com> Date: Thu, 8 Feb 2024 16:41:00 +0100 Subject: [PATCH 1/5] Localized & draft & ID_texts Document current behavior, reasoning, potential way forward ... --- advanced/fiori.md | 91 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/advanced/fiori.md b/advanced/fiori.md index 086d4c01b2..9faa077dfd 100644 --- a/advanced/fiori.md +++ b/advanced/fiori.md @@ -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 +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?) +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 redeploment the same values +for `ID_texts` are produced. + +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. + +Is there a way to avoid this popup, but on the other hand keep the structure of the `.texts` entity +and table unchanged? + +The basic idea is to have in the CDS runtime and for the database a `.texts` entity and table with +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. + + + + + + ### 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. From ba25cbba9e5a9050fe92464f1ee957946f2e3be6 Mon Sep 17 00:00:00 2001 From: Steffen Weinstock <79531202+stewsk@users.noreply.github.com> Date: Thu, 8 Feb 2024 16:47:39 +0100 Subject: [PATCH 2/5] Update advanced/fiori.md Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- advanced/fiori.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced/fiori.md b/advanced/fiori.md index 9faa077dfd..7fba8d49a2 100644 --- a/advanced/fiori.md +++ b/advanced/fiori.md @@ -494,7 +494,7 @@ 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 redeploment the same values +`ID_texts`. It is important the the generated value is stable, so that upon redeployment the same values for `ID_texts` are produced. Today Fiori can also deal with composite keys with non-UUID types. For an entity with such a key, From ebb1653a62632fc9b5fa4898e3a2c853301ab884 Mon Sep 17 00:00:00 2001 From: Steffen Weinstock <79531202+stewsk@users.noreply.github.com> Date: Mon, 18 Mar 2024 21:31:44 +0100 Subject: [PATCH 3/5] Update advanced/fiori.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Adrian Görler --- advanced/fiori.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced/fiori.md b/advanced/fiori.md index 7fba8d49a2..3c20e58214 100644 --- a/advanced/fiori.md +++ b/advanced/fiori.md @@ -436,7 +436,7 @@ 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 +If such a `.texts` entity should take part in the draft workflow, this must be explicitly switched 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. From b7a8a223a15415a3d6664f1b932f00e0b11a3b5c Mon Sep 17 00:00:00 2001 From: Steffen Weinstock <79531202+stewsk@users.noreply.github.com> Date: Mon, 18 Mar 2024 21:32:44 +0100 Subject: [PATCH 4/5] Update advanced/fiori.md --- advanced/fiori.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced/fiori.md b/advanced/fiori.md index 3c20e58214..3c0a2afce7 100644 --- a/advanced/fiori.md +++ b/advanced/fiori.md @@ -440,7 +440,7 @@ If such a `.texts` entity should take part in the draft workflow, this must be e 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?) +At the time draft support was implemented in CAP, Fiori required 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 From 3bbf3aca9c07c73f18c6ab9817890c098f441096 Mon Sep 17 00:00:00 2001 From: "Dr. David A. Kunz" Date: Tue, 21 May 2024 16:54:04 +0200 Subject: [PATCH 5/5] Update advanced/fiori.md --- advanced/fiori.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced/fiori.md b/advanced/fiori.md index 3c0a2afce7..220cac027f 100644 --- a/advanced/fiori.md +++ b/advanced/fiori.md @@ -499,7 +499,7 @@ for `ID_texts` are produced. 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. +the user to provide the immutable key values. Is there a way to avoid this popup, but on the other hand keep the structure of the `.texts` entity and table unchanged?