From ddd58664848294925df6ed9c90e7552c18776e90 Mon Sep 17 00:00:00 2001 From: allan Date: Tue, 30 Jun 2026 13:39:38 +0100 Subject: [PATCH] feat: 7.9 updates --- docs/dcc-dates.md | 8 +++++ docs/dcc-validations.md | 4 +++ docs/dcu-tableviewer.md | 2 ++ docs/dynamic-cell-dropdown.md | 47 ++++++++++++---------------- docs/embed-va.md | 58 +++++++++++++++++++++++++++++++++++ docs/filter.md | 2 +- docs/tables/mpe_security.md | 2 +- mkdocs.yml | 1 + 8 files changed, 95 insertions(+), 29 deletions(-) create mode 100644 docs/embed-va.md diff --git a/docs/dcc-dates.md b/docs/dcc-dates.md index 1660b51..fa99461 100644 --- a/docs/dcc-dates.md +++ b/docs/dcc-dates.md @@ -39,6 +39,14 @@ run; !!! note Data Controller does not support decimals when EDITING. For datetimes, this means that values must be rounded to 1 second (milliseconds are not supported). + +In the LOAD screen these dates display as **ISO 8601** (`YYYY-MM-DD`, `HH:mm:ss`, `YYYY-MM-DDTHH:mm:ss`) regardless of the user's locale. This guarantees: + +- Consistent CSV / Excel exports across geographies +- Predictable copy / paste between cells and into external tools +- No more `1/2/2026` vs `2/1/2026` ambiguity at edit time + +If you need a locale-specific *display* (eg `DD/MM/YYYY`) on a per-column basis, use the new [`NUMBER_FORMAT`](/dcc-validations/) rule with an `Intl.DateTimeFormat`-compatible JSON value. If you have other dates / datetimes / times you would like us to support, do [get in touch](https://datacontroller.io/contact)! diff --git a/docs/dcc-validations.md b/docs/dcc-validations.md index 3dfe629..2b40f0e 100644 --- a/docs/dcc-validations.md +++ b/docs/dcc-validations.md @@ -31,6 +31,10 @@ Check back frequently as we plan to keep growing this list of checks. |NOTNULL|(defaultval)|Will prevent submission if null values are present. Optional - provide a default value.| |MINVAL|1|Defines a minimum value for a numeric cell| |MAXVAL|1000000|Defines a maximum value for a numeric cell| +|READONLY|(defaultval) |Renders the column read-only in the editor. The defaultval is used when rows are added. | +|HIDDEN|(defaultval) |Hides the column from the editor grid while still submitting its data. The defaultval is used when rows are added. | +|ROUND|2 |Rounds numeric input on paste/edit. Positive digits round to number of decimal places (eg 2 rounds to 0.01) Negative digits round to the nearest ten/hundred etc. Half-away-from-zero rounding is applied so `-0.5 → -1` and `2.5 → 3`. | +|NUMBER_FORMAT|`{"style":"currency","currency":"GBP"}` |Display-only [`Intl.NumberFormat` renderer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat). RULE_VALUE is the JSON options object passed straight to `Intl.NumberFormat`. Does not change the stored value. | |HARDSELECT|sashelp.class.name|A distinct list of values (max 1000) are taken from this library.member.column reference, and the value **must** be in this list. This list may be supplemented by entries in the MPE_SELECTBOX table.| |SOFTSELECT|dcdemo.mpe_tables.libref|A distinct list of values (max 1000) are taken from this library.member.column reference, and the user-provided value may (or may not) be in this list. This list may be supplemented by entries in the MPE_SELECTBOX table.| |[HARDSELECT_HOOK](/dynamic-cell-dropdown)|/logical/folder/stpname|A SAS service (STP or Viya Job) or a path to a SAS program on the filesystem. User provided values **must** be in this list. Cannot be used alongside a SOFTSELECT_HOOK.| diff --git a/docs/dcu-tableviewer.md b/docs/dcu-tableviewer.md index e1ad29f..9ff0e31 100644 --- a/docs/dcu-tableviewer.md +++ b/docs/dcu-tableviewer.md @@ -37,6 +37,8 @@ The Download button gives several options for obtaining the current view of data Note - if the table is registered in Data Controller as being TXTEMPORAL (SCD2) then the download option will prefilter for the _current_ records and removes the valid from / valid to variables. This makes the CSV suitable for DC file upload, if desired. +Note that all the above items are exported from backend. There is also a _frontend_ context menu that can be used in the VIEW screen (right click menu) for quick export into CSV or Excel formats. + ### Web Query URL This option gives you a URL that can be used to import data directly into third party tools such as Power BI or Microsoft Excel (as a "web query"). You can set up a filter, eg for a particular month, and refresh the query on demand using client tooling such as VBA. diff --git a/docs/dynamic-cell-dropdown.md b/docs/dynamic-cell-dropdown.md index 2566d98..f3139dc 100644 --- a/docs/dynamic-cell-dropdown.md +++ b/docs/dynamic-cell-dropdown.md @@ -49,15 +49,14 @@ The following tables should be created in the WORK library as outputs: This output table can contain up to three columns: * `display_index` (optional, mandatory if using `dynamic_extended_values`). Is a numeric key used to join the two tables. -* `display_value` - always character * `raw_value` - unformatted character or numeric according to source data type Example values: -|DISPLAY_INDEX:best.|DISPLAY_VALUE:$|RAW_VALUE| -|---|---|---| -|1|$77.43|77.43| -|2|$88.43|88.43| +|DISPLAY_INDEX:best.|RAW_VALUE| +|---|---| +|1|77.43| +|2|88.43| ### `WORK.DYNAMIC_EXTENDED_VALUES` This output table is optional. If provided, it will map the DISPLAY_INDEX from the DYNAMIC_VALUES table to additional column/value pairs, that will be used to populate dropdowns for _other_ cells in the _same_ row. @@ -66,7 +65,6 @@ The following columns should be provided: * `display_index` - a numeric key joining each value to the `dynamic_values` table * `extra_col_name` - the name of the additional variable(s) to contain the extra dropdown(s) -* `display_value` - the value to display in the dropdown. Always character. * `display_type` - Either C or N depending on the raw value type * `raw_value_num` - The unformatted value if numeric * `raw_value_char` - The unformatted value if character @@ -74,17 +72,17 @@ The following columns should be provided: Example Values: -|DISPLAY_INDEX:best.|EXTRA_COL_NAME:$32|DISPLAY_VALUE:$|DISPLAY_TYPE:$1.|RAW_VALUE_NUM|RAW_VALUE_CHAR:$5000|FORCED_VALUE| -|---|---|---|---|---|---|---| -|1|DISCOUNT_RT|"50%"|N|0.5||.| -|1|DISCOUNT_RT|"40%"|N|0.4||0| -|1|DISCOUNT_RT|"30%"|N|0.3||1| -|1|CURRENCY_SYMBOL|"GBP"|C||"GBP"|.| -|1|CURRENCY_SYMBOL|"RSD"|C||"RSD"|.| -|2|DISCOUNT_RT|"50%"|N|0.5||.| -|2|DISCOUNT_RT|"40%"|N|0.4||1| -|2|CURRENCY_SYMBOL|"EUR"|C||"EUR"|.| -|2|CURRENCY_SYMBOL|"HKD"|C||"HKD"|1| +|DISPLAY_INDEX:best.|EXTRA_COL_NAME:$32|DISPLAY_TYPE:$1.|RAW_VALUE_NUM|RAW_VALUE_CHAR:$5000|FORCED_VALUE| +|---|---|---|---|---|---| +|1|DISCOUNT_RT|N|0.5||.| +|1|DISCOUNT_RT|N|0.4||0| +|1|DISCOUNT_RT|N|0.3||1| +|1|CURRENCY_SYMBOL|C||"GBP"|.| +|1|CURRENCY_SYMBOL|C||"RSD"|.| +|2|DISCOUNT_RT|N|0.5||.| +|2|DISCOUNT_RT|N|0.4||1| +|2|CURRENCY_SYMBOL|C||"EUR"|.| +|2|CURRENCY_SYMBOL|C||"HKD"|1| ### Code Examples @@ -107,9 +105,9 @@ Simple dropdown Output should be a single table called "work.dynamic_values" in the format below. - |DISPLAY_VALUE:$|RAW_VALUE:??| - |---|---| - |$44.00|44| + |RAW_VALUE:??| + |---| + |44| **/ @@ -133,37 +131,33 @@ create table work.source as where tx_to > "%sysfunc(datetime(),E8601DT26.6)"dt order by 1,2; -data work.DYNAMIC_VALUES (keep=display_index raw_value display_value); +data work.DYNAMIC_VALUES (keep=display_index raw_value); set work.source end=last; by libref; if last.libref then do; display_index+1; raw_value=libref; - display_value=libref; output; end; if last then do; display_index+1; raw_value='*ALL*'; - display_value='*ALL*'; output; end; run; data work.dynamic_extended_values(keep=display_index extra_col_name display_type - display_value RAW_VALUE_CHAR raw_value_num forced_value); + RAW_VALUE_CHAR raw_value_num forced_value); set work.source end=last; by libref dsn; retain extra_col_name 'ALERT_DS'; retain display_type 'C'; retain raw_value_num .; raw_value_char=dsn; - display_value=dsn; forced_value=0; if first.libref then display_index+1; if last.libref then do; - display_value='*ALL*'; raw_value_char='*ALL*'; forced_value=1; output; @@ -171,7 +165,6 @@ data work.dynamic_extended_values(keep=display_index extra_col_name display_type else output; if last then do; - display_value='*ALL*'; raw_value_char='*ALL*'; forced_value=1; output; diff --git a/docs/embed-va.md b/docs/embed-va.md new file mode 100644 index 0000000..f682117 --- /dev/null +++ b/docs/embed-va.md @@ -0,0 +1,58 @@ +--- +layout: article +title: SAS Visual Analytics Embed +description: Embed the Data Controller editor inside a SAS VA report as a data-driven content object. Row selections in the VA report drive filters and column visibility in the editor. +--- + +# Embedding inside SAS Visual Analytics + +Data Controller can be embedded inside a SAS Visual Analytics report as a +**data-driven content** (DDC) object. This unlocks scenarios where a user +selects a row in a VA visualisation and is immediately able to edit the +corresponding row(s) in a SAS table - all from inside the same report. + +## URL + +Open the editor as a DDC by appending `?embed=va` to the editor route: + +``` + +`https://yourserver/DC/#/editor//?embed=va` + +``` + +The `?embed=` parameter accepts three values: + +| Value | Behaviour | +|---|---| +| `true` | Chrome (header, back button, sub-nav) is hidden. Editor opens in its normal read-only / Filter mode. | +| `va` | Same chrome-hiding as `true`, **plus** editor starts in edit mode, "Add Row" / Cancel / top action buttons are hidden, and a single bottom **Submit** button is rendered. | +| `false` (or omitted) | Standard interactive UI. | + +## How VA drives the editor + +VA pushes a JSON payload to the iframe via `window.postMessage` whenever the +selected rows change. Data Controller listens for these messages and: + +1. Resolves each VA `parameter` to a DC column by matching on column label. +2. Builds a filter (using existing [Filter](/filter/) machinery) over the + selected primary-key values. +3. Hides any VA columns marked as `brush` so the grid stays focused on the + user-editable columns (except primary key cols which are always shown) +4. Navigates to `/editor/
/?embed=va` so the filtered view is + shareable and survives reloads. + +If VA sends an empty / unmatched message the editor falls back to the unfiltered +view but stays in VA mode. + +## Security + +Only postMessage events from the hosting parent frame (or the same origin in +dev/tests) are honoured - see [`VaMessagingService.isTrustedSource()`]( +https://git.datacontroller.io/dc/dc/src/branch/main/client/src/app/services/va-messaging.service.ts). + +## Configuration in VA + +In the VA Report Designer, add a **Data-Driven Content** object and set the URL +to the editor route shown above. Map the report data items so they include the +primary key column(s) of the target DC table. \ No newline at end of file diff --git a/docs/filter.md b/docs/filter.md index 86230de..848bfe0 100644 --- a/docs/filter.md +++ b/docs/filter.md @@ -7,7 +7,7 @@ og_image: https://docs.datacontroller.io/img/filter_dynamic_on.png # Filtering -Data Controller for SAS® enables you to create complex table filters. The "dynamic" setting enables the dropdown values to be pre-filtered by previous filter clauses. Filtered views are shareable! +Data Controller for SAS® enables you to create complex table filters. The "dynamic" setting enables the dropdown values to be pre-filtered by previous filter clauses. Filtered views are shareable! They are also used when [embedded in VA.](/embed-va) ## Shared Filters diff --git a/docs/tables/mpe_security.md b/docs/tables/mpe_security.md index 72966e1..fb13fe6 100644 --- a/docs/tables/mpe_security.md +++ b/docs/tables/mpe_security.md @@ -22,4 +22,4 @@ Edits to this table are covered by a (backend) post edit hook, which will automa - 🔑 `DSN char(32)`: The name of the target dataset (or format catalog) - 🔑 `ACCESS_LEVEL char(100)`: Either VIEW, EDIT or APPROVE - 🔑 `SAS_GROUP char(100)`: The SAS Group to which to provide access - - `TX_TO num`: SCD2 close datetime \ No newline at end of file + - `TX_TO num`: SCD2 close datetime diff --git a/mkdocs.yml b/mkdocs.yml index b8ea6ef..f497059 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -54,6 +54,7 @@ nav: - Selectboxes: dcc-selectbox.md - Tables: dcc-tables.md - Validations: dcc-validations.md + - Visual Analytics: embed-va.md - Macros: macros.md - Installation: - System Requirements: dci-requirements.md