From 320364a7a2fdcbef076017ad7a33b57ea31557b4 Mon Sep 17 00:00:00 2001
From: Ilija Lazoroski <ilija.la@live.com>
Date: Wed, 21 Sep 2022 16:48:47 +0200
Subject: [PATCH 1/2] UI: Get derived state from props in AdvancedMultiSelect

---
 .../components/ui-components/AdvancedMultiSelect.js   | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/AdvancedMultiSelect.js b/monkey/monkey_island/cc/ui/src/components/ui-components/AdvancedMultiSelect.js
index bd6933ac2..cb5ef1594 100644
--- a/monkey/monkey_island/cc/ui/src/components/ui-components/AdvancedMultiSelect.js
+++ b/monkey/monkey_island/cc/ui/src/components/ui-components/AdvancedMultiSelect.js
@@ -32,7 +32,6 @@ function AdvancedMultiSelectHeader(props) {
 class AdvancedMultiSelect extends React.Component {
   constructor(props) {
     super(props);
-
     let selectedPluginNames = this.props.value.map(v => v.name);
     let allPluginNames = this.props.options.enumOptions.map(v => v.value);
 
@@ -162,6 +161,16 @@ class AdvancedMultiSelect extends React.Component {
     this.onChange(safePluginNames);
   }
 
+  static getDerivedStateFromProps(props, current_state) {
+    let propsPluginNames = props.value.map(v => v.name);
+    if (current_state.selectedPluginNames !== propsPluginNames) {
+      return {
+      selectedPluginNames: propsPluginNames
+      }
+    }
+    return null
+  }
+
   render() {
     const {
       autofocus,

From 56af6fd2c49c656ef0d303c6ebb272fdf4eabb7e Mon Sep 17 00:00:00 2001
From: vakarisz <vakarisz@yahoo.com>
Date: Thu, 22 Sep 2022 12:16:11 +0300
Subject: [PATCH 2/2] UI: Don't use derived state for selected plugin names

---
 .../ui-components/AdvancedMultiSelect.js      | 33 +++++++------------
 1 file changed, 12 insertions(+), 21 deletions(-)

diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/AdvancedMultiSelect.js b/monkey/monkey_island/cc/ui/src/components/ui-components/AdvancedMultiSelect.js
index cb5ef1594..87d836e6d 100644
--- a/monkey/monkey_island/cc/ui/src/components/ui-components/AdvancedMultiSelect.js
+++ b/monkey/monkey_island/cc/ui/src/components/ui-components/AdvancedMultiSelect.js
@@ -32,21 +32,23 @@ function AdvancedMultiSelectHeader(props) {
 class AdvancedMultiSelect extends React.Component {
   constructor(props) {
     super(props);
-    let selectedPluginNames = this.props.value.map(v => v.name);
     let allPluginNames = this.props.options.enumOptions.map(v => v.value);
 
     this.state = {
       infoPaneParams: getDefaultPaneParams(
         this.props.schema.items,
-        this.isUnsafeOptionSelected(selectedPluginNames)
+        this.isUnsafeOptionSelected(this.getSelectedPluginNames())
       ),
       allPluginNames: allPluginNames,
-      masterCheckboxState: this.getMasterCheckboxState(selectedPluginNames),
-      pluginDefinitions: this.props.schema.items.pluginDefs,
-      selectedPluginNames: selectedPluginNames
+      masterCheckboxState: this.getMasterCheckboxState(this.getSelectedPluginNames()),
+      pluginDefinitions: this.props.schema.items.pluginDefs
     };
   }
 
+  getSelectedPluginNames = () => {
+    return this.props.value.map(v => v.name);
+  }
+
   getOptionList = () => {
     return this.props.options.enumOptions.sort(this.compareOptions);
   }
@@ -54,7 +56,6 @@ class AdvancedMultiSelect extends React.Component {
   onChange = (strValues) => {
     let pluginArray = this.namesToPlugins(strValues, this.state.pluginDefinitions);
     this.props.onChange(pluginArray)
-    this.setState({selectedPluginNames: pluginArray.map(v => v.name)});
   }
 
   namesToPlugins = (names, allPlugins) => {
@@ -79,7 +80,7 @@ class AdvancedMultiSelect extends React.Component {
   }
 
   onMasterCheckboxClick = () => {
-    let checkboxState = this.getMasterCheckboxState(this.state.selectedPluginNames);
+    let checkboxState = this.getMasterCheckboxState(this.getSelectedPluginNames());
     if (checkboxState === MasterCheckboxState.ALL) {
       var newValues = [];
     } else {
@@ -95,7 +96,7 @@ class AdvancedMultiSelect extends React.Component {
   }
 
   getSelectValuesAfterClick(clickedValue) {
-    const valueArray = cloneDeep(this.state.selectedPluginNames);
+    const valueArray = cloneDeep(this.getSelectedPluginNames());
 
     if (valueArray.includes(clickedValue)) {
       return valueArray.filter(e => e !== clickedValue);
@@ -157,19 +158,9 @@ class AdvancedMultiSelect extends React.Component {
 
   setPaneInfoToSafe() {
     let safePluginNames = this.state.allPluginNames.filter(pluginName => this.isSafe(pluginName));
-    this.setState({selectedPluginNames: safePluginNames});
     this.onChange(safePluginNames);
   }
 
-  static getDerivedStateFromProps(props, current_state) {
-    let propsPluginNames = props.value.map(v => v.name);
-    if (current_state.selectedPluginNames !== propsPluginNames) {
-      return {
-      selectedPluginNames: propsPluginNames
-      }
-    }
-    return null
-  }
 
   render() {
     const {
@@ -185,16 +176,16 @@ class AdvancedMultiSelect extends React.Component {
         <AdvancedMultiSelectHeader title={schema.title}
                                    onCheckboxClick={this.onMasterCheckboxClick}
                                    checkboxState={this.getMasterCheckboxState(
-                                     this.state.selectedPluginNames)}
+                                     this.getSelectedPluginNames())}
                                    hideReset={this.getHideResetState(
-                                     this.state.selectedPluginNames)}
+                                     this.getSelectedPluginNames())}
                                    onResetClick={this.onResetClick}/>
 
         <ChildCheckboxContainer id={id} multiple={multiple} required={required}
                                 autoFocus={autofocus} isSafe={this.isSafe}
                                 onPaneClick={this.setPaneInfo}
                                 onCheckboxClick={this.onChildCheckboxClick}
-                                selectedValues={this.state.selectedPluginNames}
+                                selectedValues={this.getSelectedPluginNames()}
                                 enumOptions={this.getOptionList()}/>
 
         <InfoPane title={this.state.infoPaneParams.title}