feat: configurable link actions#2321
Conversation
There was a problem hiding this comment.
Hey - I've found 2 issues, and left some high level feedback:
- Using
encodeURIComponenton each substituted segment will encode path separators (e.g./), which may break URLs like thesourceFolder/filesexample; considerencodeURIor more targeted encoding depending on how these variables are intended to be used. - When an array index is out of range you currently substitute an empty string, which can silently produce malformed URLs; consider either leaving the placeholder intact or surfacing an error so the misconfiguration is easier to detect.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Using `encodeURIComponent` on each substituted segment will encode path separators (e.g. `/`), which may break URLs like the `sourceFolder/files` example; consider `encodeURI` or more targeted encoding depending on how these variables are intended to be used.
- When an array index is out of range you currently substitute an empty string, which can silently produce malformed URLs; consider either leaving the placeholder intact or surfacing an error so the misconfiguration is easier to detect.
## Individual Comments
### Comment 1
<location path="src/app/shared/modules/configurable-actions/configurable-action.component.ts" line_range="523-532" />
<code_context>
type_link() {
- window.open(this.actionConfig.url, this.actionConfig.target || "_self");
+ const url = this.actionConfig.url.replace(
+ /\{\{\s*([@#]\w+(?:\[\d+\])?)\s*\}\}/g,
+ (_, variableName) => {
+ // Handle array indexing like @files[0]
+ const arrayMatch = variableName.match(/^([@#]\w+)\[(\d+)\]$/);
+ if (arrayMatch) {
+ const baseVariable = arrayMatch[1];
+ const index = parseInt(arrayMatch[2], 10);
+ const value = this.get_value_from_definition(baseVariable);
+
+ if (Array.isArray(value) && index < value.length) {
+ return encodeURIComponent(value[index]);
+ }
+ return "";
+ }
+
+ return encodeURIComponent(this.get_value_from_definition(variableName));
+ },
+ );
+ window.open(url, this.actionConfig.target || "_self");
}
</code_context>
<issue_to_address>
**issue (bug_risk):** Guard against undefined or non-string values from get_value_from_definition before passing to encodeURIComponent.
If `get_value_from_definition` returns `undefined`, `null`, or non-primitive values, `encodeURIComponent` will stringify them to values like `"undefined"` or `"[object Object]"`, which can corrupt the URL. Consider normalizing to a safe default (e.g. `""` or a specific fallback) and/or explicitly handling non-string types before encoding.
</issue_to_address>
### Comment 2
<location path="src/app/shared/modules/configurable-actions/configurable-action.component.ts" line_range="522" />
<code_context>
}
type_link() {
- window.open(this.actionConfig.url, this.actionConfig.target || "_self");
+ const url = this.actionConfig.url.replace(
</code_context>
<issue_to_address>
**issue (complexity):** Consider extracting the URL templating and variable resolution logic into separate helper methods so that `type_link` remains a simple wrapper that just builds and opens the URL.
You can reduce the complexity of `type_link` by extracting the templating logic into focused helpers while keeping behavior identical.
For example:
```ts
type_link() {
const url = this.buildActionUrl(this.actionConfig.url);
window.open(url, this.actionConfig.target || "_self");
}
private buildActionUrl(template: string): string {
return template.replace(
/\{\{\s*([@#]\w+(?:\[\d+\])?)\s*\}\}/g,
(_, variableName) => this.resolveTemplateVariable(variableName),
);
}
private resolveTemplateVariable(variableName: string): string {
const arrayMatch = variableName.match(/^([@#]\w+)\[(\d+)\]$/);
if (arrayMatch) {
const baseVariable = arrayMatch[1];
const index = parseInt(arrayMatch[2], 10);
const value = this.get_value_from_definition(baseVariable);
if (Array.isArray(value) && index < value.length) {
return encodeURIComponent(value[index]);
}
return "";
}
return encodeURIComponent(this.get_value_from_definition(variableName));
}
```
This keeps `type_link` focused on “open URL”, isolates regex/substitution into `buildActionUrl`, and makes the array-index logic reusable and easier to test in `resolveTemplateVariable`.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
80a8946 to
1aa4909
Compare
nitrosx
left a comment
There was a problem hiding this comment.
Good feature!!!
The changes assumes that we have only one instrument.
I think we should implement the feature assuming that we can have a list of instruments.
Could you please make the appropriate changes
Thanks for the review ! I see your point ! however it seems supporting multiple Instruments for now might be a bit too early, since we are still using |
|
@abdellah257 No problem!!! |
nitrosx
left a comment
There was a problem hiding this comment.
I was wondering if it would make more sense to change the configuration to the following:
"url": "https://<host_name>/{{ @instrumentCode }}/{{ @year) }}/{{ @proposalIds[0] }}",
"type": "link",
"variables": {
"instrumentCode": "#InstrumentField[uniqueName]",
"date": "#Dataset[0]Field[creationTime]",
"year" "#date_format(@date,"+%Y")",
"proposalIds": "#Dataset[0]Field[proposalIds]"
},
This way the computation is moved to the variable definition and not when you build the url, which requires only substitution.
|
3267f9a to
ee0d65a
Compare
ee0d65a to
f8cf265
Compare
Description
Add the option to configure the url of
linktype actionsMotivation
Support dynamic links that are selection dependent
example:
Changes:
Changes to:
src/app/shared/modules/configurable-actions/configurable-action.component.tsTests included
Documentation
official documentation info
If you have updated the official documentation, please provide PR # and URL of the pages where the updates are included
Summary by Sourcery
New Features: