diff --git a/docs/notes/1.2.0.md b/docs/notes/1.2.0.md new file mode 100644 index 0000000000..125bc2733b --- /dev/null +++ b/docs/notes/1.2.0.md @@ -0,0 +1,60 @@ +--- +id: 1.2.0 +title: 1.2.0 +--- + + +#### 05/01/2025 + +import ComingSoon from '@site/src/components/ComingSoon' + + + +## Qodly Studio + +
+
+
+
.
+
+
+
+Setting a Primary Locale ensures consistent fallback behavior across user sessions and browsers.
+
+
+### Previewing Locales in the Studio
+
+By default, no locale is selected when opening a page in the Studio.
+
+
+
+Developers can manually switch between configured locales during development to preview how translations appear across languages.
+
+
+
in the [Header panel](./pageLoaders/pageLoaderOverview.md#header-panel) of the page.
+
+ - Selecting any of the available locales to simulate the translated application view.
+
+
+
+
+
.
+
+
+
+
+
+ :::tip
+ The key will appear under all locales.
+ :::
+
+- Different values can be assigned for the same key depending on the active locale.
+
+### Translation Key Scenarios
+
+Here’s how key assignment works when localizing content:
+
+1. **Assigning a Key in the Base State (No Locale Selected)**: When no specific locale is selected (you’re in the base state), clicking the purple i18n button adds the key to all locales.
+
+2. **Assigning a Key While a Locale is Selected**: If a locale is selected when you click the i18n button, the key is still added to all locales, including the base state.
+
+3. **Manually Editing Labels per Locale (No Key Used)**: Instead of using keys, you can manually update the Label field for each locale.
+ - Select a locale and directly type the desired label.
+ - This is quick and flexible but may become harder to manage at scale.
+ - Use the approach that best matches the complexity and reuse patterns of your UI labels.
+
+
+### Removing a Key from a Literal
+
+If needed, you can remove a translation key association from a text component:
+
+
next to the assigned key.
+
+
+
+
+By switching between locales inside the Studio and previewing the pages, developers can immediately see how each configured translation appears for different languages.
+
+
+
+
next to the locale name.
+- A language selector dropdown will appear.
+- Choose a new language to replace the current one.
+
+### Removing a Locale
+
+To completely remove a locale:
+
+- Navigate to the **Localization** page from the Explorer.
+- Find the locale you wish to remove.
+- Click on the **Delete** button
next to the locale name.
+
+Removing a locale will:
+
+- Delete all translation keys associated with that locale.
+- Automatically update the `UserLanguage.supported` array, removing the deleted language from the runtime switching options.
+
+
+## Managing Keys
+
+### Editing a Translation Key
+
+To edit the value of a translation key for a specific locale:
+
+1. Go to the Localization page in Qodly Studio.
+2. Select the desired locale.
+3. Locate the key you wish to update from the list.
+4. Click the edit icon or directly click into the value field.
+5. Modify the value and click the ✔ button to confirm your changes or ✖ to cancel.
+
+
+
+### Deleting a Translation Key
+
+To delete a translation key entirely from the Localization page:
+
+1. Open the Localization page.
+2. Navigate to the locale where the key is visible.
+3. Locate the key in the list and click the delete icon.
+
+
+
+Deleting a key will:
+
+- Remove the key itself.
+- Remove all translations associated with it across all locales.
+- Unlink any components or literals that were referencing the deleted key.
+
+Use this option only when the key is no longer needed in the application.
+
+
+## Runtime Language Switching
+
+To enable dynamic, user-driven language switching at runtime, the application must be configured to bind to the [UserLanguage shared Qodly source](./pageLoaders/qodlySources.md#qodlysource-userlanguage).
+
+Runtime switching involves the following configuration steps:
+
+
+
+
+
+
by default.
+
+To enable the Export button:
+
+1. You must select at least one locale from the Localization panel.
+
+2. You can either:
+
+ - Manually check the box for one or more locales.
+
+ - Or check the **Select All** checkbox
to select all available locales at once.
+
+
+ Once at least one locale is selected, the **Export** button becomes active
.
+
+3. Click **Export** to open the export configuration modal.
+
+
+
located next to the Export options.
+
+
{`
-self.fd-selectbox {
+self .fd-selectbox {
border-radius: 10px;
background-color: #E0E0E0;
box-shadow: -4px 4px 10px rgba(220, 220, 220, 0.4), -2px 2px 10px rgba(192, 192, 192, 0.3);
@@ -262,7 +265,7 @@ In this example each choice within the select box is customized with rounded cor
{`
-self.fd-selectbox {
+self .fd-selectbox {
border-radius: 10px;
background-color: #E0E0E0;
box-shadow: -4px 4px 10px rgba(220, 220, 220, 0.4), -2px 2px 10px rgba(192, 192, 192, 0.3);
@@ -290,7 +293,7 @@ In this example, the virtual list of the Select Box is customized by applying a
{`
-self.fd-selectbox {
+self .fd-selectbox {
border-radius: 10px;
background-color: #E0E0E0;
box-shadow: -4px 4px 10px rgba(220, 220, 220, 0.4), -2px 2px 10px rgba(192, 192, 192, 0.3);
@@ -316,7 +319,7 @@ This example customizes the Select Box menu by applying a light gray background,
{`
-self.fd-selectbox__menu {
+self .fd-selectbox__menu {
color:rgb(152, 92, 8);
background-color: #E0E0E0;
font-family: cursive;
@@ -334,6 +337,24 @@ self.fd-selectbox__menu {
For smooth application of CSS Classes, both `.fd-selectbox` and `.fd-selectbox__menu` should be attached to `self` **without an extra space** unlike other classNames.
:::
+#### Example 6: Custom Search Bar Styling
+This example shows how to apply a dark theme to the search bar using the available CSS classes:
+
+```css
+self {
+ .fd-selectbox__search {
+ background-color: black;
+ color: white;
+ }
+ .fd-selectbox__search__input {
+ background-color: transparent;
+ }
+ .fd-selectbox__search__icon {
+ color: white;
+ }
+}
+```
+
## Showcase
Here's a glimpse of how the **Select Box** component will look and behave in action:
diff --git a/docs/studio/pageLoaders/components/textinput.md b/docs/studio/pageLoaders/components/textinput.md
index dc8148c053..6c5a70b074 100644
--- a/docs/studio/pageLoaders/components/textinput.md
+++ b/docs/studio/pageLoaders/components/textinput.md
@@ -146,7 +146,7 @@ Within the **Text Input** component, an embedded **Input** allows for further cu
:::
- date: Limits input to date values with a date picker.
+ date: Limits input to date values with a date picker. Users can navigate to the next or previous month, as well as jump to the next or previous year directly within the date picker.
@@ -199,6 +199,7 @@ Within the **Text Input** component, an embedded **Input** allows for further cu
| `include` | `Boolean` | Defines whether the interval should include (`true`) or exclude (`false`) dates. |
| `type` | `String` | Specifies the interval type. Possible values: **startingFrom, until, range, days**. |
| `params` | `Object` | Contains details about the interval, such as specific dates or recurring patterns. |
+ | `active` | `Boolean` | Whether the interval is active. Defaults to true. If false, the interval is ignored. This behaves exactly like the Card Toggle in the UI, which enables or disables the interval block without removing your settings. |
#### **`params` Object Properties**
| **Interval Type** | **Parameters** | **Example JSON Format** |
diff --git a/docs/studio/pageLoaders/img/QodlysourceUserLanguage.png b/docs/studio/pageLoaders/img/QodlysourceUserLanguage.png
new file mode 100644
index 0000000000..267ed26321
Binary files /dev/null and b/docs/studio/pageLoaders/img/QodlysourceUserLanguage.png differ
diff --git a/docs/studio/pageLoaders/img/headerPanel.png b/docs/studio/pageLoaders/img/headerPanel.png
index 2f5787ae24..76f6aca5e1 100644
Binary files a/docs/studio/pageLoaders/img/headerPanel.png and b/docs/studio/pageLoaders/img/headerPanel.png differ
diff --git a/docs/studio/pageLoaders/img/maximizeQodlySourceEditor.png b/docs/studio/pageLoaders/img/maximizeQodlySourceEditor.png
new file mode 100644
index 0000000000..b00edb6cc4
Binary files /dev/null and b/docs/studio/pageLoaders/img/maximizeQodlySourceEditor.png differ
diff --git a/docs/studio/pageLoaders/img/pageLocalizationButton.png b/docs/studio/pageLoaders/img/pageLocalizationButton.png
new file mode 100644
index 0000000000..fdced0b2c4
Binary files /dev/null and b/docs/studio/pageLoaders/img/pageLocalizationButton.png differ
diff --git a/docs/studio/pageLoaders/img/popupEditor.png b/docs/studio/pageLoaders/img/popupEditor.png
new file mode 100644
index 0000000000..a962a97182
Binary files /dev/null and b/docs/studio/pageLoaders/img/popupEditor.png differ
diff --git a/docs/studio/pageLoaders/img/popupEditor2.png b/docs/studio/pageLoaders/img/popupEditor2.png
new file mode 100644
index 0000000000..4b4f278508
Binary files /dev/null and b/docs/studio/pageLoaders/img/popupEditor2.png differ
diff --git a/docs/studio/pageLoaders/pageLoaderOverview.md b/docs/studio/pageLoaders/pageLoaderOverview.md
index bb7e418914..a9ad5a12b5 100644
--- a/docs/studio/pageLoaders/pageLoaderOverview.md
+++ b/docs/studio/pageLoaders/pageLoaderOverview.md
@@ -86,6 +86,14 @@ The Page Editor enhances your application by providing a versatile toolkit for i
+### Localization (i18n)
+
+The Localization button
in the header panel lets you preview your application in the different locales you created from the Localization page.
+
+:::info
+For further details, refer to the [Localization (i18n)](../localization.md) section.
+:::
+
### Dialogs
The Dialog button
in the header panel provides access to a list of Dialogs. Each Dialog is designed as a popup overlay, aimed at enhancing user engagement by displaying additional content within the existing Page.
diff --git a/docs/studio/pageLoaders/qodlySources.md b/docs/studio/pageLoaders/qodlySources.md
index 7708949a04..29e6df6bbd 100644
--- a/docs/studio/pageLoaders/qodlySources.md
+++ b/docs/studio/pageLoaders/qodlySources.md
@@ -76,13 +76,13 @@ The `Qodly` namespace
.
+Within the **Qodly** namespace, you'll find the predefined qodlysource named **Location**
.
The Location qodlysource is specifically designed to facilitate handling URL-related data, making it simple to interact with different URL segments.
@@ -114,7 +114,90 @@ The Location qodlysource is specifically designed to facilitate handling URL-rel
```
:::info Restrictions:
-The **Location** datasource is shared across your entire application and **cannot be edited or deleted**. This ensures uniform behavior and prevents accidental modifications.
+The **Location** qodlysource is shared across your entire application and **cannot be edited or deleted**. This ensures uniform behavior and prevents accidental modifications.
+:::
+
+### Qodlysource: UserLanguage
+
+Within the **Qodly** namespace, you'll find the predefined qodlysource named **UserLanguage**
.
+
+The UserLanguage qodlysource is specifically designed to manage multilingual behavior within your application by storing the currently selected language and the list of available supported languages.
+
+It provides a seamless way to bind user-selected languages at runtime without requiring manual coding or session handling.
+
+#### Key Attributes of UserLanguage:
+
+- **selected** *(Object)*: Stores the currently active locale chosen by the user. This object contains information about the selected language.
+
+ **Structure:**
+ ```javascript
+ {
+ isocode: "en",
+ locale: "anglais",
+ native: "English"
+ }
+ ```
+
+ Each locale entry include:
+ - `isocode`: Standard two-letter language code (e.g., "en" for English).
+ - `locale`: Display name for the language.
+ - `native`: Native name for the language (as spoken in that locale).
+
+ **Example:**
+ ```javascript
+ UserLanguage.selected // → { isocode: "fr", locale: "français", native: "Français" }
+ ```
+
+- **supported** (Array): Lists all the available supported locales that the user has created in the **Localization page**. Each entry in the array represents one locale and must follow the same structure as the `selected` object.
+
+ **Structure:**
+ ```javascript
+ [
+ {
+ isocode: "en",
+ locale: "anglais",
+ native: "English"
+ },
+ {
+ isocode: "de",
+ locale: "allemand",
+ native: "Deutsch"
+ }
+ ]
+ ```
+
+ **Example:**
+ ```javascript
+ UserLanguage.supported // → [
+ // { isocode: "en", locale: "anglais", native: "English" },
+ // { isocode: "es", locale: "espagnol", native: "Español" }
+ // ]
+ ```
+
+:::info Restrictions:
+The **UserLanguage** qodlysource is shared across your entire application and **cannot be deleted or edited manually**.
+
+To modify the list of supported languages (adding or removing locales), you must update the configuration from the [Localization page](../localization.md#accessing-the-localization-page).
+Changes made in the Localization page will automatically be reflected in the `UserLanguage.supported` array.
+:::
+
+### Qodlysource: Title
+
+Within the Qodly namespace, you'll find the predefined qodlysource named Title.
+
+The Title qodlysource is specifically designed to control the browser tab title dynamically. By default, the browser tab title is derived from the name of the current Page. When the Qodly.Title qodlysource is defined, it overrides this behavior and sets the tab title based on its value.
+
+#### Key Behavior of Title:
+
+- **Override tab title**: When a value is set in Qodly.Title, it becomes the browser tab title, replacing the default Page-based title.
+
+- **Fallback behavior**: If Qodly.Title is not defined, the default behavior remains in place, and the tab title is derived from the Page name.
+
+
+:::info Restrictions:
+The **Title** qodlysource is shared across your entire application and **cannot be deleted or edited manually**.
+
+It is of type String and its value is editable at runtime to allow dynamic updates to the tab title.
:::
@@ -274,6 +357,24 @@ For Entity Selection or Entity types, make sure to also configure additional set
+
+
+ If the value is long or complex, a Maximize button
appears (only for object and array types), opening a popup editor to give you more editing space.
+
+
+
+
+
+
+
+
+ The popup itself can also be maximized to cover the full contextual panel for better visibility.
+
+
+
+
+
+
### Renaming a Qodly Source
You can easily rename a qodlysource from the contextual panel. In doing so, Qodly Studio will automatically update references to the renamed qodlysource:
diff --git a/docs/studio/rendering.md b/docs/studio/rendering.md
index 714a59be83..8447793f61 100644
--- a/docs/studio/rendering.md
+++ b/docs/studio/rendering.md
@@ -179,4 +179,27 @@ Understanding the lifecycle of a page is crucial for diagnosing and fixing rende
- **Loading JSON of Sub Pages**: In some cases, additional sub pages need to be loaded dynamically based on user interactions or specific conditions. This involves fetching and loading JSON files for sub pages, allowing for the dynamic expansion of content.
- - **Restarting Initialization for Sub Pages**: Once the JSON of sub pages is loaded, the initialization process restarts from **initializing local Qodly sources** for these sub pages. This ensures that each sub page has access to the necessary data and components, repeating the initialization steps to prepare the sub page for display.
\ No newline at end of file
+ - **Restarting Initialization for Sub Pages**: Once the JSON of sub pages is loaded, the initialization process restarts from **initializing local Qodly sources** for these sub pages. This ensures that each sub page has access to the necessary data and components, repeating the initialization steps to prepare the sub page for display.
+
+## Connection Status Handling
+
+The Qodly Renderer displays system messages when the client loses or regains network connectivity during rendering.
+
+These messages appear as colored banners at the top of the page and provide immediate feedback without interrupting the current page state.
+
+#### When the connection is lost:
+
+* A red banner is displayed at the top of the rendered page.
+* The message shown is:
+ **Connection lost**
+* The banner remains visible until:
+
+ * The connection is restored, or
+ * The user manually closes it using the close button located in the top-right corner of the banner.
+
+#### When the connection is re-established:
+
+* A green banner is displayed with the message:
+ **Connection restored**
+* This message automatically disappears after a few seconds.
+* No user action is required to dismiss it.
\ No newline at end of file
diff --git a/docs/studio/roles/example-of-configuration.md b/docs/studio/roles/example-of-configuration.md
index b119c57aea..8e3612d5a7 100644
--- a/docs/studio/roles/example-of-configuration.md
+++ b/docs/studio/roles/example-of-configuration.md
@@ -101,10 +101,17 @@ Only the *Doctor* role can view the patient's confidential data (gathered in a *
-2. Assign it to the *Doctor* role (see [roles](#roles) below). This will exclude all other roles).
+2. Assign it to the *Doctor* role (see [roles](#roles) below). This will exclude all other roles.
+:::info Why are all other roles excluded?
+
+Once a resource is associated with a privilege, that privilege is required to access the resource, which blocks roles that do not have that privilege. It's like putting a lock on a door: you need to have the key to open it. In this case, we created the *viewConfidentialInfo* privilege and associated it to the `Patients.confidentialInfo` attribute, so it automatically impacts roles that do not have this privilege (i.e., Secretary).
+Usually, when reading entities, if a privilege is missing to read certain attributes, they are excluded (filtered) from the query response.
+
+:::
+
### Roles
Here are the corresponding role definitions.
diff --git a/docs/studio/roles/img/example-viewsecretinfo.png b/docs/studio/roles/img/example-viewsecretinfo.png
index 387027079e..9eecd28761 100644
Binary files a/docs/studio/roles/img/example-viewsecretinfo.png and b/docs/studio/roles/img/example-viewsecretinfo.png differ
diff --git a/sidebars.js b/sidebars.js
index aeae91a5c5..67c83f58ae 100644
--- a/sidebars.js
+++ b/sidebars.js
@@ -183,6 +183,11 @@ const sidebars = {
id: 'studio/httpHandlers',
label: "HTTP Handlers"
},
+ {
+ type: 'doc',
+ id: 'studio/localization',
+ label: "Localization (i18n)"
+ },
{
type: 'doc',
id: 'studio/settings',
@@ -534,13 +539,13 @@ const sidebars = {
},
'qodlyLookerStudio/qodlyLookerStudioConnector',
{
- type: "link",
- label: "Third-party Authentication",
- href: "https://github.com/4d/4D-NetKit/tree/20R8#oauth2provider"
+ type: 'link',
+ label: 'OAuth 2.0',
+ href: 'https://github.com/4d/4D-NetKit/tree/20R8#oauth2provider'
},
{
type: 'category',
- label: 'Email Integration',
+ label: 'Email',
items: [
{
type: 'link',
diff --git a/versioned_docs/version-1.1.0/studio/roles/example-of-configuration.md b/versioned_docs/version-1.1.0/studio/roles/example-of-configuration.md
index b119c57aea..8e3612d5a7 100644
--- a/versioned_docs/version-1.1.0/studio/roles/example-of-configuration.md
+++ b/versioned_docs/version-1.1.0/studio/roles/example-of-configuration.md
@@ -101,10 +101,17 @@ Only the *Doctor* role can view the patient's confidential data (gathered in a *
-2. Assign it to the *Doctor* role (see [roles](#roles) below). This will exclude all other roles).
+2. Assign it to the *Doctor* role (see [roles](#roles) below). This will exclude all other roles.
+:::info Why are all other roles excluded?
+
+Once a resource is associated with a privilege, that privilege is required to access the resource, which blocks roles that do not have that privilege. It's like putting a lock on a door: you need to have the key to open it. In this case, we created the *viewConfidentialInfo* privilege and associated it to the `Patients.confidentialInfo` attribute, so it automatically impacts roles that do not have this privilege (i.e., Secretary).
+Usually, when reading entities, if a privilege is missing to read certain attributes, they are excluded (filtered) from the query response.
+
+:::
+
### Roles
Here are the corresponding role definitions.
diff --git a/versioned_docs/version-1.1.0/studio/roles/img/example-viewsecretinfo.png b/versioned_docs/version-1.1.0/studio/roles/img/example-viewsecretinfo.png
index 387027079e..9eecd28761 100644
Binary files a/versioned_docs/version-1.1.0/studio/roles/img/example-viewsecretinfo.png and b/versioned_docs/version-1.1.0/studio/roles/img/example-viewsecretinfo.png differ