Skip to content

Commit 6bb3de4

Browse files
TASK-1884601: add support for checkbox multiselect
1 parent 193ff58 commit 6bb3de4

File tree

10 files changed

+343
-74
lines changed

10 files changed

+343
-74
lines changed

core/src/commonMain/kotlin/com/pega/constellation/sdk/kmp/core/api/ComponentEvent.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,18 @@ data class ComponentEvent(
5050
)
5151
)
5252

53+
fun forItemClick(itemIndex: Int, isSelected: Boolean) =
54+
ComponentEvent(
55+
type = CLICK_ITEM_EVENT,
56+
componentData = mapOf(
57+
"clickedItemIndex" to itemIndex.toString(),
58+
"isSelected" to isSelected.toString()
59+
)
60+
)
61+
5362
private const val FIELD_CHANGE = "FieldChange"
5463
private const val FIELD_CHANGE_WITH_FOCUS = "FieldChangeWithFocus"
5564
private const val ACTION_BUTTON_CLICK = "ActionButtonClick"
65+
private const val CLICK_ITEM_EVENT = "ClickItem"
5666
}
5767
}

core/src/commonMain/kotlin/com/pega/constellation/sdk/kmp/core/components/containers/ListViewComponent.kt

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,9 @@ class ListViewComponent(context: ComponentContext) : BaseComponent(context) {
4949
}
5050

5151
fun onItemClick(itemIndex: Int, isSelected: Boolean) {
52-
context.sendComponentEvent(clickItemEvent(itemIndex, isSelected))
52+
context.sendComponentEvent(ComponentEvent.forItemClick(itemIndex, isSelected))
5353
}
5454

55-
private fun clickItemEvent(itemIndex: Int, isSelected: Boolean) =
56-
ComponentEvent(
57-
type = CLICK_ITEM_EVENT,
58-
componentData = mapOf(
59-
"clickedItemIndex" to itemIndex.toString(),
60-
"isSelected" to isSelected.toString()
61-
)
62-
)
63-
6455
private fun JsonObject.selectionMode() =
6556
getString("selectionMode").toSelectionMode()
6657

@@ -77,9 +68,11 @@ class ListViewComponent(context: ComponentContext) : BaseComponent(context) {
7768
}
7869
element.value.toFoldedItemContent(accumulator, nextPath)
7970
}
71+
8072
is JsonArray -> jsonArray.foldIndexed(initialResult) { index, accumulator, element ->
8173
element.toFoldedItemContent(accumulator, "$currentPath[$index]")
8274
}
75+
8376
else -> initialResult + mapOf(currentPath to jsonPrimitive.content)
8477
}
8578

@@ -95,6 +88,5 @@ class ListViewComponent(context: ComponentContext) : BaseComponent(context) {
9588

9689
companion object {
9790
private const val TAG = "ListViewComponent"
98-
private const val CLICK_ITEM_EVENT = "ClickItem"
9991
}
10092
}

core/src/commonMain/kotlin/com/pega/constellation/sdk/kmp/core/components/fields/Checkbox.kt

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ import androidx.compose.runtime.getValue
44
import androidx.compose.runtime.mutableStateOf
55
import androidx.compose.runtime.setValue
66
import com.pega.constellation.sdk.kmp.core.api.ComponentContext
7+
import com.pega.constellation.sdk.kmp.core.api.ComponentEvent
8+
import com.pega.constellation.sdk.kmp.core.components.getBoolean
9+
import com.pega.constellation.sdk.kmp.core.components.getJSONArray
10+
import com.pega.constellation.sdk.kmp.core.components.getJsonObject
11+
import com.pega.constellation.sdk.kmp.core.components.getString
712
import com.pega.constellation.sdk.kmp.core.components.optBoolean
813
import com.pega.constellation.sdk.kmp.core.components.optString
914
import kotlinx.serialization.json.JsonObject
@@ -18,11 +23,47 @@ class CheckboxComponent(context: ComponentContext) : FieldComponent(context) {
1823
var hideLabel: Boolean by mutableStateOf(false)
1924
private set
2025

26+
var selectionMode: SelectionMode by mutableStateOf(SelectionMode.SINGLE)
27+
private set
28+
var checkboxGroupOptions: List<Option> by mutableStateOf(emptyList())
29+
private set
30+
2131
override fun applyProps(props: JsonObject) {
2232
super.applyProps(props)
23-
caption = props.optString("caption")
24-
trueLabel = props.optString("trueLabel", default = "True")
25-
falseLabel = props.optString("falseLabel", default = "False")
26-
hideLabel = props.optBoolean("hideLabel", default = false)
33+
34+
selectionMode = SelectionMode.valueOf(
35+
props.optString("selectionMode", default = "single").uppercase()
36+
)
37+
if (selectionMode == SelectionMode.SINGLE) {
38+
caption = props.optString("caption")
39+
trueLabel = props.optString("trueLabel", default = "True")
40+
falseLabel = props.optString("falseLabel", default = "False")
41+
hideLabel = props.optBoolean("hideLabel", default = false)
42+
} else {
43+
checkboxGroupOptions = props.getJSONArray("items").mapWithIndex { index ->
44+
getJsonObject(index).let {
45+
Option(
46+
key = it.getString("key"),
47+
text = it.getString("text"),
48+
value = it.getString("value"),
49+
selected = it.getBoolean("selected"))
50+
}
51+
}
52+
}
53+
}
54+
55+
fun onOptionClick(itemIndex: Int, isSelected: Boolean) {
56+
context.sendComponentEvent(ComponentEvent.forItemClick(itemIndex, isSelected))
57+
}
58+
59+
data class Option(
60+
val key: String,
61+
val text: String,
62+
val value: String,
63+
val selected: Boolean
64+
)
65+
66+
enum class SelectionMode {
67+
SINGLE, MULTI
2768
}
2869
}

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#SDK
2-
version=2.0.0
2+
version=3.0.1
33

44
#Kotlin
55
kotlin.code.style=official

scripts/dxcomponents/components/containers/templates/data-reference.component.js

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,8 @@ export class DataReferenceComponent extends ContainerBaseComponent {
2424
propName = "";
2525
firstChildPConnect;
2626
children;
27-
displaySingleRef;
28-
displayMultiRef;
2927
refList;
28+
displayAs;
3029

3130
constructor(componentsManager, pConn) {
3231
super(componentsManager, pConn);
@@ -40,24 +39,15 @@ export class DataReferenceComponent extends ContainerBaseComponent {
4039
);
4140
this.componentsManager.onComponentAdded(this);
4241

43-
// added
4442
this.children = this.pConn.getChildren();
4543
this.#updateSelf();
4644

47-
if (
48-
this.firstChildMeta?.type === "Dropdown" &&
45+
if ((['Dropdown', 'Checkbox'].includes(this.firstChildMeta?.type)) &&
4946
this.rawViewMetadata.config?.parameters &&
50-
!this.firstChildMeta.config.deferDatasource
51-
) {
47+
!this.firstChildMeta.config.deferDatasource) {
5248
const { value, key, text } = this.firstChildMeta.config.datasource.fields;
5349
PCore.getDataApiUtils()
54-
.getData(
55-
this.refList,
56-
{
57-
dataViewParameters: this.parameters,
58-
},
59-
""
60-
)
50+
.getData(this.refList, { dataViewParameters: this.parameters }, "")
6151
.then((res) => {
6252
if (res.data.data !== null) {
6353
const ddDataSource = res.data.data
@@ -110,7 +100,7 @@ export class DataReferenceComponent extends ContainerBaseComponent {
110100
const theConfigProps = this.pConn.getConfigProps();
111101
this.#updatePropertiesFromProps(theConfigProps);
112102

113-
const displayAs = theConfigProps.displayAs;
103+
this.displayAs = theConfigProps.displayAs;
114104
const displayMode = theConfigProps.displayMode;
115105
this.rawViewMetadata = this.pConn.getRawMetadata();
116106
this.viewName = this.rawViewMetadata.name;
@@ -128,6 +118,10 @@ export class DataReferenceComponent extends ContainerBaseComponent {
128118
if (this.firstChildMeta.config?.readOnly) {
129119
delete this.firstChildMeta.config.readOnly;
130120
}
121+
122+
// todo pelcm add readonly handling
123+
this.#setChildDatasource();
124+
131125
if (this.firstChildMeta?.type === "Dropdown" && !this.firstChildMeta.config.deferDatasource) {
132126
this.firstChildMeta.config.datasource.source = this.rawViewMetadata.config?.parameters
133127
? this.dropDownDataSource
@@ -194,6 +188,22 @@ export class DataReferenceComponent extends ContainerBaseComponent {
194188
}
195189
}
196190

191+
192+
193+
#setChildDatasource() {
194+
const { type, config } = this.firstChildMeta;
195+
196+
if (['Dropdown', 'Checkbox'].includes(type) && !config.deferDatasource && config.datasource) {
197+
const hasParameters = this.rawViewMetadata.config?.parameters;
198+
config.datasource.source = hasParameters ? this.dropDownDataSource : `@DATASOURCE ${this.refList}.pxResults`;
199+
} else if (type === 'AutoComplete') {
200+
config.datasource = this.refList;
201+
if (this.rawViewMetadata.config?.parameters) {
202+
config.parameters = this.parameters;
203+
}
204+
}
205+
}
206+
197207
// Re-create first child with overridden props
198208
// Memoized child in order to stop unmount and remount of the child component when data reference
199209
// rerenders without any actual change
@@ -205,17 +215,19 @@ export class DataReferenceComponent extends ContainerBaseComponent {
205215
category: "",
206216
context: "",
207217
});
208-
if (
209-
!this.canBeChangedInReviewMode &&
210-
this.isDisplayModeEnabled &&
211-
this.selectionMode === SELECTION_MODE.SINGLE
212-
) {
213-
this.displaySingleRef = true;
214-
}
215218

216-
if (this.isDisplayModeEnabled && this.selectionMode === SELECTION_MODE.MULTI) {
217-
this.displayMultiRef = true;
218-
}
219+
this.#setReadOnlyDisplayFlags();
220+
// if (
221+
// !this.canBeChangedInReviewMode &&
222+
// this.isDisplayModeEnabled &&
223+
// this.selectionMode === SELECTION_MODE.SINGLE
224+
// ) {
225+
// this.displaySingleRef = true;
226+
// }
227+
//
228+
// if (this.isDisplayModeEnabled && this.selectionMode === SELECTION_MODE.MULTI) {
229+
// this.displayMultiRef = true;
230+
// }
219231

220232
// In the case of a datasource with parameters you cannot load the dropdown before the parameters
221233
if (type === "Dropdown" && this.rawViewMetadata.config?.parameters && this.dropDownDataSource === null) {
@@ -246,6 +258,19 @@ export class DataReferenceComponent extends ContainerBaseComponent {
246258
}
247259
}
248260

261+
#setReadOnlyDisplayFlags() {
262+
const isSingleMode = this.selectionMode === SELECTION_MODE.SINGLE;
263+
const isMultiMode = this.selectionMode === SELECTION_MODE.MULTI;
264+
265+
if (isSingleMode && (this.displayAs === 'readonly' || this.isDisplayModeEnabled) && !this.canBeChangedInReviewMode) {
266+
this.props.displayOnlySingle = true;
267+
}
268+
269+
if (isMultiMode && (['readonly', 'readonlyMulti', 'map'].includes(this.displayAs) || this.isDisplayModeEnabled)) {
270+
this.props.displayOnlyMulti = true;
271+
}
272+
}
273+
249274
#handleSelection(event) {
250275
const caseKey = this.pConn.getCaseInfo().getKey();
251276
const refreshOptions = { autoDetectRefresh: true };

0 commit comments

Comments
 (0)