#50673 Issue 50592 - Port Replication Tab to ReactJS
Merged a month ago by mreynolds. Opened 2 months ago by mreynolds.
mreynolds/389-ds-base ui  into  master

file modified
+2

@@ -246,6 +246,8 @@ 

  Requires:         perl-Mozilla-LDAP

  # for setup-ds.pl

  Requires:         bind-utils

+ %global __provides_exclude_from %{_libdir}/%{pkgname}/perl

+ %global __requires_exclude perl\\((DSCreate|DSMigration|DSUpdate|DSUtil|Dialog|DialogManager|FileConn|Inf|Migration|Resource|Setup|SetupLog)

  %{?perl_default_filter}

  %endif

  # End use perl

@@ -0,0 +1,45 @@ 

+ #!/bin/sh

+ #

+ # Do a fresh build of the UI, and run it.  While in this state all updates made

+ # are built immediately.  Just refresh the browser to test them.

+ 

+ AUDIT=0

+ while (( "$#" )); do

+     case "$1" in

+         -a|--audit)

+         AUDIT=1

+         break

+         ;;

+     -h|--help)

+         echo Usage:

+         echo This is a development script to quickly refresh the UI and watch it live

+         echo Options:

+         echo    -a|--audit    Audit the build

+         exit 0

+         ;;

+     -*|--*=)

+         echo "Error: Unsupported argument $1" >&2

+         echo "Available Options:" >&2

+         echo "   -a|--audit    Audit the build" >&2

+         exit 1

+         ;;

+     esac

+ done

+ 

+ printf "\nCleaning and installing npm packages ...\n\n"

+ make -f node_modules.mk clean > /dev/null

+ make -f node_modules.mk install > /dev/null

+ if [ $? != 0 ]; then

+     exit 1

+ fi

+ 

+ if [ $AUDIT == 1 ]; then

+     printf "\nAuditing npm packages ...\n\n"

+     make -f node_modules.mk build-cockpit-plugin

+     if [ $? != 0 ]; then

+         exit 1

+     fi

+ fi

+ 

+ printf "\nBuilding and watching ...\n"

+ node_modules/webpack/bin/webpack.js --watch

@@ -19,6 +19,10 @@ 

      vertical-align: top !important;

  }

  

+ .ds-left-align {

+     right: 0 !important;

+ }

+ 

  /* Main nav page index.html */

  .ds-content {

      padding: 0;

@@ -116,6 +120,10 @@ 

      width: 525px;

  }

  

+ .ds-no-padding {

+     padding: 0px !important;

+ }

+ 

  .ds-tree {

      font-size: 0.5;

      background-color: #f8f8f8;

@@ -131,6 +139,11 @@ 

      padding-top: 5px;

  }

  

+ .ds-disabled {

+     pointer-events: none;

+     opacity: 0.7;

+ }

+ 

  .ds-split {

      width: 400px;

  }

@@ -142,12 +155,12 @@ 

  }

  

  .ds-input-bad {

-     border-color: red;

+     border-color: red !important;

  }

  

  .ds-input-auto-bad {

      width: 100%;

-     border-color: red;

+     border-color: red !important;

      padding-left: 5px;

  }

  

@@ -238,20 +251,6 @@ 

      overflow: auto;

  }

  

- .ds-agmt-wiz-dropdown {

-     width: 175px !important;

-     text-align: left;

- }

- 

- .ds-agmt-wiz-dropdown a {

-     padding: 0px !important;

-     padding-left: 10px !important;

-     line-height: 0 !important;

-     height: 40px;

-     width: 175px !important;

-     text-align: left;

- }

- 

  .ds-dblink-dropdown {

      width: 140px !important;

      text-align: left;

@@ -594,6 +593,17 @@ 

      float: left;

  }

  

+ .ds-inline-btn {

+     margin-top: -3px;

+     margin-left: 10px;

+     display: inline-block;

+ }

+ 

+ .spinner-sm {

+     height: 18px !important;

+     Width: 18px !important;

+ }

+ 

  .ds-footer {

      background-color: #f5f5f5 !important;

      margin-left: -25px;

@@ -635,7 +645,7 @@ 

      border: 0;

      position: relative;

      overflow: hidden;

-     width: 700px;

+     width: 100%;

      text-align: left;

      font: inherit;

  }

@@ -646,7 +656,7 @@ 

      height: 1px;

      background: #228bc0;

      position: absolute;

-     width: 700px;

+     width: 100%;

      top: 50% !important;

      margin-left: 10px;

      text-align: left;

@@ -671,7 +681,7 @@ 

  }

  

  .ds-margin-top {

-     margin-top: 10px;

+     margin-top: 10px !important;

  }

  

  .ds-margin-top-med {

@@ -686,6 +696,10 @@ 

      margin-top: 35px !important;

  }

  

+ .ds-margin-top-xxlg {

+     margin-top: 45px !important;

+ }

+ 

  .ds-modal-spinner {

      margin-top: 10px;

      text-align: center;

@@ -736,6 +750,10 @@ 

      margin-left: 15px !important;

  }

  

+ .ds-left-indent-md {

+     margin-left: 30px !important;

+ }

+ 

  .ds-right-indent {

      margin-right: 15px !important;

  }

@@ -798,6 +816,10 @@ 

      color: red;

  }

  

+ .ds-clear-text {

+      opacity: 0;

+ }

+ 

  .ds-margin-left-sm {

      margin-left: 30px !important;

  }

@@ -807,7 +829,7 @@ 

  }

  

  .ds-margin-left-piechart {

-     margin-left: 130px !important;

+     margin-left: 140px !important;

  }

  

  .ds-nested-modal {

@@ -839,6 +861,13 @@ 

      transform: translate(-25%, -50%);

  }

  

+ .ds-loading-spinner-tree {

+     position: fixed;

+     top: 40%;

+     left: 40%;

+     transform: translate(-40%, -40%);

+ }

+ 

  .ds-loading {

      position: fixed;

      top: 25%;

@@ -870,6 +899,10 @@ 

      margin-left: 80px;

  }

  

+ .ds-h4 {

+     font-size: 18px !important;

+ }

+ 

  @media screen and (max-width: 1300px) {

      .ds-plugin-spinner {

          margin-left: 0px;

@@ -955,12 +988,12 @@ 

  

  .ds-word-wrap {

      word-wrap: break-word;

-     padding-top: 3px;

  }

  

  .ds-suffix-header {

-     font-size: 16px;

+     font-size: 18px;

      margin-bottom: 15px;

+     padding-top: 5px;

  }

  

  .ds-header {

@@ -1018,3 +1051,22 @@ 

  th {

      text-align: center;

  }

+ 

+ td {

+     text-align: center;

+ }

+ 

+ hr {

+     margin-top: 20px;

+     margin-bottom: 20px;

+ }

+ 

+ h3 {

+     margin-top: 20px;

+     margin-bottom: 20px;

+ }

+ 

+ h4 {

+     margin-top: 15px;

+     margin-bottom: 15px;

+ }

@@ -48,6 +48,7 @@ 

              createSuffixEntry: false,

              createSampleEntries: false,

              noSuffixInit: true,

+             disableTree: false,

  

              // DB config

              globalDBConfig: {},

@@ -83,7 +84,6 @@ 

          // Suffix

          this.showSuffixModal = this.showSuffixModal.bind(this);

          this.closeSuffixModal = this.closeSuffixModal.bind(this);

-         this.handleChange = this.handleChange.bind(this);

          this.createSuffix = this.createSuffix.bind(this);

          this.loadSuffix = this.loadSuffix.bind(this);

          this.loadSuffixConfig = this.loadSuffixConfig.bind(this);

@@ -102,6 +102,7 @@ 

  

          // Other

          this.loadSuffixTree = this.loadSuffixTree.bind(this);

+         this.enableTree = this.enableTree.bind(this);

      }

  

      componentWillMount () {

@@ -449,6 +450,13 @@ 

      }

  

      selectNode(selectedNode) {

+         if (selectedNode.selected) {

+             return;

+         }

+         this.setState({

+             disableTree: true // Disable the tree to allow node to be fully loaded

+         });

+ 

          if (selectedNode.id == "dbconfig" ||

              selectedNode.id == "chaining-config" ||

              selectedNode.id == "backups") {

@@ -976,8 +984,38 @@ 

                                                              suffixLoading: false

                                                          });

                                                      });

+                                         })

+                                         .fail(err => {

+                                             let errMsg = JSON.parse(err);

+                                             this.addNotification(

+                                                 "error",

+                                                 `Error attribute encryption for ${suffix} - ${errMsg.desc}`

+                                             );

+                                             this.setState({

+                                                 suffixLoading: false

+                                             });

                                          });

+                             })

+                             .fail(err => {

+                                 let errMsg = JSON.parse(err);

+                                 this.addNotification(

+                                     "error",

+                                     `Error loading VLV indexes for ${suffix} - ${errMsg.desc}`

+                                 );

+                                 this.setState({

+                                     suffixLoading: false

+                                 });

                              });

+                 })

+                 .fail(err => {

+                     let errMsg = JSON.parse(err);

+                     this.addNotification(

+                         "error",

+                         `Error loading config for ${suffix} - ${errMsg.desc}`

+                     );

+                     this.setState({

+                         suffixLoading: false

+                     });

                  });

      }

  

@@ -1047,9 +1085,20 @@ 

                  });

      }

  

+     enableTree () {

+         this.setState({

+             disableTree: false

+         });

+     }

+ 

      render() {

          const { nodes } = this.state;

          let db_element = "";

+         let disabled = "tree-view-container";

+         if (this.state.disableTree) {

+             disabled = "tree-view-container ds-disabled";

+         }

+ 

          if (this.state.loaded) {

              if (this.state.node_name == DB_CONFIG || this.state.node_name == "") {

                  db_element =

@@ -1058,6 +1107,7 @@ 

                          addNotification={this.addNotification}

                          reload={this.loadGlobalConfig}

                          data={this.state.globalDBConfig}

+                         enableTree={this.enableTree}

                          key={this.state.configUpdated}

                      />;

              } else if (this.state.node_name == CHAINING_CONFIG) {

@@ -1067,6 +1117,7 @@ 

                          addNotification={this.addNotification}

                          reload={this.loadChainingConfig}

                          data={this.state.chainingConfig}

+                         enableTree={this.enableTree}

                          key={this.state.chainingUpdated}

                      />;

              } else if (this.state.node_name == BACKUP_CONFIG) {

@@ -1077,6 +1128,7 @@ 

                          backups={this.state.BackupRows}

                          suffixes={this.state.suffixList}

                          ldifs={this.state.LDIFRows}

+                         enableTree={this.enableTree}

                          reload={this.loadBackups}

                      />;

              } else if (this.state.node_name != "") {

@@ -1084,10 +1136,9 @@ 

                  if (this.state.dbtype == "suffix" || this.state.dbtype == "subsuffix") {

                      if (this.state.suffixLoading) {

                          db_element =

-                             <div className="ds-loading-spinner ds-center">

-                                 <p />

+                             <div className="ds-margin-top ds-loading-spinner ds-center">

                                  <h4>Loading suffix configuration for <b>{this.state.node_text} ...</b></h4>

-                                 <Spinner loading size="md" />

+                                 <Spinner className="ds-margin-top-lg" loading size="md" />

                              </div>;

                      } else {

                          db_element =

@@ -1107,6 +1158,7 @@ 

                                  dbtype={this.state.dbtype}

                                  data={this.state[this.state.node_text]}

                                  attrs={this.state.attributes}

+                                 enableTree={this.enableTree}

                                  key={this.state.node_text}

                              />;

                      }

@@ -1114,10 +1166,9 @@ 

                      // Chaining

                      if (this.state.chainingLoading) {

                          db_element =

-                             <div className="ds-loading-spinner ds-center">

-                                 <p />

+                             <div className="ds-margin-top ds-loading-spinner ds-center">

                                  <h4>Loading chaining configuration for <b>{this.state.node_text} ...</b></h4>

-                                 <Spinner loading size="md" />

+                                 <Spinner className="ds-margin-top-lg" loading size="md" />

                              </div>;

                      } else {

                          db_element =

@@ -1128,6 +1179,7 @@ 

                                  loadSuffixTree={this.loadSuffixTree}

                                  addNotification={this.addNotification}

                                  data={this.state[this.state.node_text]}

+                                 enableTree={this.enableTree}

                                  reload={this.loadChainingLink}

                              />;

                      }

@@ -1144,7 +1196,7 @@ 

                  <div className="ds-container">

                      <div>

                          <div className="ds-tree">

-                             <div className="tree-view-container" id="db-tree"

+                             <div className={disabled} id="db-tree"

                                  style={treeViewContainerStyles}>

                                  <TreeView

                                      nodes={nodes}

@@ -1219,8 +1271,7 @@ 

                                      <input onChange={handleChange} className={error.createSuffix ? "ds-input-bad" : "ds-input"} type="text" id="createSuffix" size="40" />

                                  </Col>

                              </Row>

-                             <p />

-                             <Row title="The name for the backend database, like 'userroot'.  The name can be a combination of alphanumeric characters, dashes (-), and underscores (_). No other characters are allowed, and the name must be unique across all backends.">

+                             <Row className="ds-margin-top" title="The name for the backend database, like 'userroot'.  The name can be a combination of alphanumeric characters, dashes (-), and underscores (_). No other characters are allowed, and the name must be unique across all backends.">

                                  <Col sm={3}>

                                      <ControlLabel>Database Name</ControlLabel>

                                  </Col>

@@ -10,7 +10,7 @@ 

  var server_page_loaded = 0;

  var security_page_loaded = 1;

  var db_page_loaded = 1;

- var repl_page_loaded = 0;

+ var repl_page_loaded = 1;

  var plugin_page_loaded = 1;

  var schema_page_loaded = 0;

  var monitor_page_loaded = 1;

@@ -355,39 +355,6 @@ 

      save_config();  // Server Config Page

  }

  

- function load_repl_suffix_dropdowns() {

-   // Update replication drop downs (agmts mainly)

-   var repl_dropdowns = ['select-repl-agmt-suffix', 'select-repl-winsync-suffix',

-                         'cleanallruv-suffix', 'monitor-repl-backend-list'];

-   var repl_cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id + '.socket','replication', 'list'];

-   log_cmd('load_repl_suffix_dropdowns', 'get replicated suffix list', repl_cmd);

-   cockpit.spawn(repl_cmd, { superuser: true, "err": "message", "environ": [ENV]}).done(function(data) {

-     // Update dropdowns

-     for (var idx in repl_dropdowns) {

-       $("#" + repl_dropdowns[idx]).find('option').remove();

-     }

-     var obj = JSON.parse(data);

-     for (var idx in obj['items']) {

-       for (var list in repl_dropdowns){

-         $("#" + repl_dropdowns[list]).append('<option value="' + obj['items'][idx] + '" selected="selected">' + obj['items'][idx] +'</option>');

-       }

-     }

-     get_and_set_repl_agmts();

-     get_and_set_repl_winsync_agmts();

-     if (obj['items'].length == 0){

-       // Disable create agmt buttons

-       $("#create-agmt").prop("disabled", true);

-       $("#winsync-create-agmt").prop("disabled", true);

-       $("#create-cleanallruv-btn").prop("disabled", true);

-     } else {

-       // Enable repl agmt buttons

-       $("#create-agmt").prop("disabled", false);

-       $("#winsync-create-agmt").prop("disabled", false);

-       $("#create-cleanallruv-btn").prop("disabled", false);

-     }

-   });

- }

- 

  var progress = 10;

  

  function update_progress () {

@@ -449,11 +416,6 @@ 

      get_and_set_schema_tables();

      update_progress();

  

-     // Replication page

-     get_and_set_repl_config();

-     get_and_set_cleanallruv();

-     update_progress();

- 

      // Initialize the tabs

      $(".ds-tab-list").css( 'color', '#777');

      $("#server-tab").css( 'color', '#228bc0');

@@ -510,4 +472,8 @@ 

      $(".all-pages").hide();

      $("#security-content").show();

    });

+   $("#replication-tab").on("click", function() {

+     $(".all-pages").hide();

+     $("#replication-content").show();

+   });

  });

@@ -4,6 +4,7 @@ 

  import { Database } from "./database.jsx";

  import { Monitor } from "./monitor.jsx";

  import { Security } from "./security.jsx";

+ import { Replication } from "./replication.jsx";

  

  var serverIdElem;

  

@@ -31,6 +32,12 @@ 

          document.getElementById("database")

      );

  

+     // Replication tab

+     ReactDOM.render(

+         <Replication serverId={serverIdElem} key={tabKey} />,

+         document.getElementById("replication")

+     );

+ 

      // Monitor tab

      ReactDOM.render(

          <Monitor serverId={serverIdElem} key={tabKey} />,

@@ -20,7 +20,6 @@ 

    <script src="ds.js"></script>

    <script src="schema.js"></script>

    <script src="servers.js"></script>

-   <script src="replication.js"></script>

    <link href="static/bootstrap.min.css" rel="stylesheet">

    <link href="static/jquery.dataTables.min.css" type="text/css" rel="stylesheet">

    <link href="static/jquery.timepicker.min.css" type="text/css" rel="stylesheet">

@@ -35,9 +34,9 @@ 

    <div id="reload-page" hidden></div>

    <div id="loading-page" class="ds-center ds-loading" hidden>

      <h4 id="loading-msg">Loading Directory Server Configuration...</h4>

-     <p><span class="spinner spinner-lg spinner-inline"></span></p>

+     <p class="ds-margin-top-lg"><span class="spinner spinner-lg spinner-inline"></span></p>

  

-     <div class="progress">

+     <div class="progress ds-margin-top-lg">

          <div class="progress-bar" role="progressbar" id="ds-progress-bar"

              aria-valuenow="20" aria-valuemin="0"

              aria-valuemax="100" style="width: 20%;"

@@ -46,7 +45,6 @@ 

          </div>

      </div>

  

- 

    </div>

    <div id="everything" hidden>

      <div class="ds-nav-bar">

@@ -103,17 +101,10 @@ 

              </li>

  

              <!-- Replication navtab -->

-             <li class="dropdown ds-nav-tab">

-               <a href="#0" class="ds-tab-list" data-toggle="dropdown" id="replication-tab">

-                 Replication

-                 <b class="caret"></b>

-               </a>

-               <ul class="dropdown-menu ds-nav-item">

-                 <li><a href="#0" class="ds-nav-choice" id="repl-config-btn" parent-id="replication-tab">Configuration</a></li>

-                 <li><a href="#0" class="ds-nav-choice" id="repl-agmts-btn" parent-id="replication-tab">Agreements</a></li>

-                 <li><a href="#0" class="ds-nav-choice" id="repl-winsync-btn" parent-id="replication-tab">Winsync Agreements</a></li>

-                 <li><a href="#0" class="ds-nav-choice" id="repl-tasks-btn" parent-id="replication-tab">Replication Tasks</a></li>

-               </ul>

+             <li class="ds-nav-tab">

+                 <a href="#0" class="ds-tab-list ds-tab-standalone" id="replication-tab">

+                     Replication

+                 </a>

              </li>

  

              <!-- Schema navtab -->

@@ -502,6 +493,12 @@ 

        </div>

  

        <div id="server-content" class="all-pages" hidden>

+           <div id="server-settings"></div>

+           <div id="server-tuning"></div>

+           <div id="server-sasl"></div>

+           <div id="server-pwp"></div>

+           <div id="server-ldapi"></div>

+           <div id="server-logs"></div>

        </div>

  

        <div id="security-content" class="all-pages" hidden>

@@ -513,6 +510,7 @@ 

        </div>

  

        <div id="replication-content" class="all-pages" hidden>

+           <div id="replication"></div>

        </div>

  

        <div id="schema-content" class="all-pages" hidden>

@@ -129,8 +129,7 @@ 

                      rows={this.props.rows}

                      loadModalHandler={this.showConfirmAttrDelete}

                  />

-                 <p />

-                 <Row>

+                 <Row className="ds-margin-top">

                      <Col sm={6}>

                          <Typeahead

                              id="attrEncrypt"

@@ -8,6 +8,7 @@ 

      TabContent,

      TabPane,

      TabContainer,

+     Checkbox,

      Col,

      Button,

      Spinner,

@@ -46,6 +47,7 @@ 

              showLDIFDeleteSpinningModal: false,

              showExportModal: false,

              exportSpinner: false,

+             includeReplData: false,

              ldifName: "",

              ldifSuffix: "",

              errObj: {}

@@ -88,12 +90,17 @@ 

          this.closeConfirmLDIFReplace = this.closeConfirmLDIFReplace.bind(this);

      }

  

+     componentDidMount() {

+         this.props.enableTree();

+     }

+ 

      showExportModal () {

          this.setState({

              showExportModal: true,

              exportSpinner: false,

              ldifName: "",

-             ldifSuffix: this.props.suffixes[0]

+             ldifSuffix: this.props.suffixes[0],

+             includeReplData: false,

          });

      }

  

@@ -254,7 +261,7 @@ 

      importLDIF() {

          this.showLDIFSpinningModal();

  

-         const cmd = [

+         let cmd = [

              "dsconf", "-j", "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",

              "backend", "import", this.state.ldifSuffix, this.state.ldifName, "--encrypted"

          ];

@@ -281,7 +288,7 @@ 

      deleteLDIF (e) {

          this.showLDIFDeleteSpinningModal();

  

-         const cmd = [

+         let cmd = [

              "dsctl", this.props.serverId, "ldifs", "--delete", this.state.ldifName

          ];

          log_cmd("deleteLDIF", "Deleting LDIF", cmd);

@@ -491,6 +498,10 @@ 

              "backend", "export", this.state.ldifSuffix, "--encrypted", "--ldif=" + this.state.ldifName

          ];

  

+         if (this.state.includeReplData) {

+             export_cmd.push("--replication");

+         }

+ 

          this.setState({

              exportSpinner: true,

          });

@@ -545,13 +556,22 @@ 

                                          confirmDelete={this.showConfirmBackupDelete}

                                      />

                                  </div>

-                                 <p />

-                                 <Button

-                                     bsStyle="primary"

-                                     onClick={this.showBackupModal}

-                                 >

-                                     Create Backup

-                                 </Button>

+                                 <div className="ds-inline">

+                                     <Button

+                                         bsStyle="primary"

+                                         onClick={this.showBackupModal}

+                                         className="ds-margin-top"

+                                     >

+                                         Create Backup

+                                     </Button>

+                                     <Button

+                                         bsStyle="default"

+                                         onClick={this.props.reload}

+                                         className="ds-left-margin ds-margin-top"

+                                     >

+                                         Refresh Backups

+                                     </Button>

+                                 </div>

                              </TabPane>

  

                              <TabPane eventKey={2}>

@@ -562,13 +582,22 @@ 

                                          confirmDelete={this.showConfirmLDIFDelete}

                                      />

                                  </div>

-                                 <p />

-                                 <Button

-                                     bsStyle="primary"

-                                     onClick={this.showExportModal}

-                                 >

-                                     Create LDIF Export

-                                 </Button>

+                                 <div className="ds-inline">

+                                     <Button

+                                         bsStyle="primary"

+                                         onClick={this.showExportModal}

+                                         className="ds-margin-top"

+                                     >

+                                         Create LDIF Export

+                                     </Button>

+                                     <Button

+                                         bsStyle="default"

+                                         onClick={this.props.reload}

+                                         className="ds-left-margin ds-margin-top"

+                                     >

+                                         Refresh LDIFs

+                                     </Button>

+                                 </div>

                              </TabPane>

                          </TabContent>

                      </div>

@@ -677,7 +706,7 @@ 

          if (spinning) {

              spinner =

                  <Row>

-                     <div className="ds-modal-spinner">

+                     <div className="ds-margin-top ds-modal-spinner">

                          <Spinner loading inline size="md" />Exporting database... <font size="2">(You can safely close this window)</font>

                      </div>

                  </Row>;

@@ -713,8 +742,7 @@ 

                                      </select>

                                  </Col>

                              </Row>

-                             <p />

-                             <Row title="Name of exported LDIF file, if left blank the data and time will be used as the file name">

+                             <Row className="ds-margin-top" title="Name of exported LDIF file, if left blank the data and time will be used as the file name">

                                  <Col sm={3}>

                                      <ControlLabel>LDIF File Name</ControlLabel>

                                  </Col>

@@ -727,7 +755,17 @@ 

                                      />

                                  </Col>

                              </Row>

-                             <p />

+                             <Row className="ds-margin-top-xlg">

+                                 <Col sm={12} className="ds-margin-left">

+                                     <Checkbox

+                                         id="includeReplData"

+                                         onChange={handleChange}

+                                         title="Include the replication metadata needed to restore or initialize another replica."

+                                     >

+                                         Include Replication Data

+                                     </Checkbox>

+                                 </Col>

+                             </Row>

                              {spinner}

                          </Form>

                      </Modal.Body>

@@ -766,7 +804,7 @@ 

          if (spinning) {

              spinner =

                  <Row>

-                     <div className="ds-modal-spinner">

+                     <div className="ds-margin-top ds-modal-spinner">

                          <Spinner loading inline size="md" />Backing up databases... <font size="2">(You can safely close this window)</font>

                      </div>

                  </Row>;

@@ -803,7 +841,6 @@ 

                                      />

                                  </Col>

                              </Row>

-                             <p />

                              {spinner}

                          </Form>

                      </Modal.Body>

@@ -856,8 +893,7 @@ 

                          <Form horizontal autoComplete="off">

                              <div className="ds-modal-spinner">

                                  <Spinner loading inline size="md" /> Restoring backup <b>{msg}</b> ...

-                                 <p />

-                                 <p><font size="2"> (You can safely close this window)</font></p>

+                                 <p className="ds-margin-top"><font size="2"> (You can safely close this window)</font></p>

                              </div>

                          </Form>

                      </Modal.Body>

@@ -904,8 +940,7 @@ 

                          <Form horizontal autoComplete="off">

                              <div className="ds-modal-spinner">

                                  <Spinner loading inline size="md" /> Deleting backup <b>{msg}</b> ...

-                                 <p />

-                                 <p><font size="2"> (You can safely close this window)</font></p>

+                                 <p className="ds-margin-top"><font size="2"> (You can safely close this window)</font></p>

                              </div>

                          </Form>

                      </Modal.Body>

@@ -952,8 +987,7 @@ 

                          <Form horizontal autoComplete="off">

                              <div className="ds-modal-spinner">

                                  <Spinner loading inline size="md" /> Importing LDIF <b>{msg}</b> ...

-                                 <p />

-                                 <p><font size="2"> (You can safely close this window)</font></p>

+                                 <p className="ds-margin-top"><font size="2"> (You can safely close this window)</font></p>

                              </div>

                          </Form>

                      </Modal.Body>

@@ -1000,8 +1034,7 @@ 

                          <Form horizontal autoComplete="off">

                              <div className="ds-modal-spinner">

                                  <Spinner loading inline size="md" /> Deleting LDIF file <b>{msg}</b> ...

-                                 <p />

-                                 <p><font size="2"> (You can safely close this window)</font></p>

+                                 <p className="ds-margin-top"><font size="2"> (You can safely close this window)</font></p>

                              </div>

                          </Form>

                      </Modal.Body>

@@ -1068,11 +1101,13 @@ 

  Backups.propTypes = {

      backups: PropTypes.array,

      ldifs: PropTypes.array,

-     reload: PropTypes.func

+     reload: PropTypes.func,

+     enableTree: PropTypes.func,

  };

  

  Backups.defaultProps = {

      backups: [],

      ldifs: [],

-     reload: noop

+     reload: noop,

+     enableTree: noop,

  };

@@ -1,6 +1,6 @@ 

  import cockpit from "cockpit";

  import React from "react";

- import { ConfirmPopup } from "../notifications.jsx";

+ import { ConfirmPopup, DoubleConfirmModal } from "../notifications.jsx";

  import CustomCollapse from "../customCollapse.jsx";

  import { log_cmd } from "../tools.jsx";

  import {

@@ -11,7 +11,6 @@ 

      Row,

      Col,

      ControlLabel,

-     Checkbox,

      FormControl,

      noop

  } from "patternfly-react";

@@ -98,6 +97,10 @@ 

          this.closeConfirmCompDelete = this.closeConfirmCompDelete.bind(this);

      }

  

+     componentDidMount() {

+         this.props.enableTree();

+     }

+ 

      handleChange(e) {

          // Generic

          const value = e.target.type === 'checkbox' ? e.target.checked : e.target.value;

@@ -454,7 +457,7 @@ 

          );

  

          return (

-             <div id="db-global-page">

+             <div id="chaining-page">

                  <h3 className="ds-config-header">Database Chaining Settings</h3>

                  <hr />

                  <div className="ds-container">

@@ -492,66 +495,143 @@ 

                          </div>

                      </div>

                  </div>

- 

-                 <h4 className="ds-sub-header"><br />Default Database Link Creation Settings</h4>

+                 <h4 className="ds-margin-top ds-sub-header ds-center">Default Database Link Creation Settings</h4>

                  <hr />

-                 <div className="ds-container">

-                     <div className="ds-split">

-                         <label htmlFor="defSizeLimit" className="ds-config-label" title="The size limit of entries returned over a database link (nsslapd-sizelimit).">

-                             Size Limit</label><input className="ds-input" type="text" id="defSizeLimit" onChange={this.handleChange} value={this.state.defSizeLimit} size="15" />

-                         <label htmlFor="defTimeLimit" className="ds-config-label" title="The time limit of an operation over a database link (nsslapd-timelimit).">

-                             Time Limit</label><input className="ds-input" type="text" id="defTimeLimit" onChange={this.handleChange} value={this.state.defTimeLimit} size="15" />

-                         <label htmlFor="defBindConnLimit" className="ds-config-label" title="The maximum number of TCP connections the database link establishes with the remote server.  (nsbindconnectionslimit).">

-                             Max TCP Connections</label><input className="ds-input" id="defBindConnLimit" type="text" onChange={this.handleChange} value={this.state.defBindConnLimit} size="15" />

-                         <label htmlFor="defOpConnLimit" className="ds-config-label" title="The maximum number of connections allowed over the database link.  (nsoperationconnectionslimit).">

-                             Max LDAP Connections</label><input className="ds-input" id="defOpConnLimit" type="text" onChange={this.handleChange} value={this.state.defOpConnLimit} size="15" />

-                         <label htmlFor="defConcurLimit" className="ds-config-label" title="The maximum number of concurrent bind operations per TCP connection. (nsconcurrentbindlimit).">

-                             Max Binds Per Connection</label><input className="ds-input" id="defConcurLimit" type="text" onChange={this.handleChange} value={this.state.defConcurLimit} size="15" />

-                         <label htmlFor="defBindTimeout" className="ds-config-label" title="The amount of time before the bind attempt times out. (nsbindtimeout).">

-                             Bind Timeout</label><input className="ds-input" id="defBindTimeout" type="text" onChange={this.handleChange} value={this.state.defBindTimeout} size="15" />

-                         <label htmlFor="defBindRetryLimit" className="ds-config-label" title="The number of times the database link tries to bind with the remote server after a connection failure. (nsbindretrylimit).">

-                             Bind Retry Limit</label><input className="ds-input" id="defBindRetryLimit" type="text" onChange={this.handleChange} value={this.state.defBindRetryLimit} size="15" />

-                     </div>

-                     <div className="ds-divider" />

-                     <div className="ds-split ds-inline">

-                         <div>

-                             <label htmlFor="defConcurOpLimit" className="ds-config-label" title="The maximum number of operations per connections. (nsconcurrentoperationslimit).">

-                                 Max Operations Per Connection</label><input className="ds-input" id="defConcurOpLimit" type="text" onChange={this.handleChange} value={this.state.defConcurOpLimit} size="15" />

-                         </div>

-                         <div>

-                             <label htmlFor="defConnLife" className="ds-config-label" title="The life of a database link connection to the remote server.  0 is unlimited  (nsconnectionlife).">

-                                 Connection Lifetime (in seconds)</label><input className="ds-input" id="defConnLife" type="text" onChange={this.handleChange} value={this.state.defConnLife} size="15" />

-                         </div>

-                         <div>

-                             <label htmlFor="defSearchCheck" className="ds-config-label" title="The number of seconds that pass before the server checks for abandoned operations.  (nsabandonedsearchcheckinterval).">

-                                 Abandoned Op Check Interval</label><input className="ds-input" id="defSearchCheck" type="text" onChange={this.handleChange} value={this.state.defSearchCheck} size="15" />

-                         </div>

-                         <div>

-                             <label htmlFor="defHopLimit" className="ds-config-label" title="The maximum number of times a request can be forwarded from one database link to another.  (nshoplimit).">

-                                 Database Link Hop Limit</label><input className="ds-input" type="text" onChange={this.handleChange} value={this.state.defHopLimit} id="defHopLimit" size="15" />

-                         </div>

-                         <div>

-                             <p />

-                             <input type="checkbox" onChange={this.handleChange} checked={this.state.defCheckAci} className="ds-config-checkbox" id="defCheckAci" /><label

-                                 htmlFor="defCheckAci" className="ds-label" title="Sets whether ACIs are evaluated on the database link as well as the remote data server (nschecklocalaci)."> Check Local ACIs</label>

-                         </div>

-                         <div>

-                             <input type="checkbox" onChange={this.handleChange} checked={this.state.defRefOnScoped} className="ds-config-checkbox" id="defRefOnScoped" /><label

-                                 htmlFor="defRefOnScoped" className="ds-label" title="Sets whether referrals are returned by scoped searches (meaning 'one-level' or 'subtree' scoped searches). (nsreferralonscopedsearch)."> Send Referral On Scoped Search</label>

-                         </div>

-                         <div>

-                             <input type="checkbox" onChange={this.handleChange} checked={this.state.defProxy} className="ds-config-checkbox" id="defProxy" /><label

-                                 htmlFor="defProxy" className="ds-label" title="Sets whether proxied authentication is allowed (nsproxiedauthorization)."> Allow Proxied Authentication</label>

-                         </div>

-                         <div>

-                             <input type="checkbox" onChange={this.handleChange} checked={this.state.defUseStartTLS} className="ds-config-checkbox" id="defUseStartTLS" /><label

-                                 htmlFor="defUseStartTLS" className="ds-label" title="Sets whether to use Start TLS to initiate a secure, encrypted connection over an insecure port.  (nsusestarttls)."> Use StartTLS</label>

-                         </div>

-                     </div>

-                 </div>

-                 <div className="ds-margin-top-lg">

-                     <button className="btn btn-primary save-button" onClick={this.save_chaining_config}>Save Default Settings</button>

-                 </div>

+                 <Form horizontal>

+                     <Row className="ds-margin-top">

+                         <Col componentClass={ControlLabel} sm={4} title="The size limit of entries returned over a database link (nsslapd-sizelimit).">

+                             Size Limit

+                         </Col>

+                         <Col sm={8}>

+                             <input className="ds-input-auto" type="text" id="defSizeLimit" onChange={this.handleChange} defaultValue={this.state.defSizeLimit} />

+                         </Col>

+                     </Row>

+                     <Row className="ds-margin-top">

+                         <Col componentClass={ControlLabel} sm={4} title="The maximum number of operations per connections. (nsconcurrentoperationslimit).">

+                             Max Operations Per Conn

+                         </Col>

+                         <Col sm={8}>

+                             <input className="ds-input-auto" type="text" id="defConcurOpLimit" onChange={this.handleChange} defaultValue={this.state.defConcurOpLimit} />

+                         </Col>

+                     </Row>

+                     <Row className="ds-margin-top">

+                         <Col componentClass={ControlLabel} sm={4} title="The time limit of an operation over a database link (nsslapd-timelimit).">

+                             Time Limit

+                         </Col>

+                         <Col sm={8}>

+                             <input className="ds-input-auto" type="text" id="defTimeLimit" onChange={this.handleChange} defaultValue={this.state.defTimeLimit} />

+                         </Col>

+                     </Row>

+                     <Row className="ds-margin-top">

+                         <Col componentClass={ControlLabel} sm={4} title="The maximum number of operations per connections. (nsconcurrentoperationslimit).">

+                             Connection Lifetime

+                         </Col>

+                         <Col sm={8}>

+                             <input className="ds-input-auto" type="text" id="defConnLife" onChange={this.handleChange} defaultValue={this.state.defConnLife} />

+                         </Col>

+                     </Row>

+                     <Row className="ds-margin-top">

+                         <Col componentClass={ControlLabel} sm={4} title="The maximum number of TCP connections the database link establishes with the remote server.  (nsbindconnectionslimit).">

+                             Max TCP Connections

+                         </Col>

+                         <Col sm={8}>

+                             <input className="ds-input-auto" type="text" id="defBindConnLimit" onChange={this.handleChange} defaultValue={this.state.defBindConnLimit} />

+                         </Col>

+                     </Row>

+                     <Row className="ds-margin-top">

+                         <Col componentClass={ControlLabel} sm={4} title="The number of seconds that pass before the server checks for abandoned operations.  (nsabandonedsearchcheckinterval).">

+                             Abandoned Op Check Interval

+                         </Col>

+                         <Col sm={8}>

+                             <input className="ds-input-auto" type="text" id="defSearchCheck" onChange={this.handleChange} defaultValue={this.state.defSearchCheck} />

+                         </Col>

+                     </Row>

+                     <Row className="ds-margin-top">

+                         <Col componentClass={ControlLabel} sm={4} title="The maximum number of connections allowed over the database link.  (nsoperationconnectionslimit).">

+                             Max LDAP Connections

+                         </Col>

+                         <Col sm={8}>

+                             <input className="ds-input-auto" type="text" id="defOpConnLimit" onChange={this.handleChange} defaultValue={this.state.defOpConnLimit} />

+                         </Col>

+                     </Row>

+                     <Row className="ds-margin-top">

+                         <Col componentClass={ControlLabel} sm={4} title="The number of seconds that pass before the server checks for abandoned operations.  (nsabandonedsearchcheckinterval).">

+                             Abandoned Op Check Interval

+                         </Col>

+                         <Col sm={8}>

+                             <input className="ds-input-auto" type="text" id="defSearchCheck" onChange={this.handleChange} defaultValue={this.state.defSearchCheck} />

+                         </Col>

+                     </Row>

+                     <Row className="ds-margin-top">

+                         <Col componentClass={ControlLabel} sm={4} title="The maximum number of connections allowed over the database link.  (nsoperationconnectionslimit).">

+                             Max Binds Per Connection

+                         </Col>

+                         <Col sm={8}>

+                             <input className="ds-input-auto" type="text" id="defOpConnLimit" onChange={this.handleChange} defaultValue={this.state.defOpConnLimit} />

+                         </Col>

+                     </Row>

+                     <Row className="ds-margin-top">

+                         <Col componentClass={ControlLabel} sm={4} title="The maximum number of times a request can be forwarded from one database link to another.  (nshoplimit).">

+                             Database Link Hop Limit

+                         </Col>

+                         <Col sm={8}>

+                             <input className="ds-input-auto" type="text" id="defHopLimit" onChange={this.handleChange} defaultValue={this.state.defHopLimit} />

+                         </Col>

+                     </Row>

+                     <Row className="ds-margin-top">

+                         <Col componentClass={ControlLabel} sm={4} title="The amount of time before the bind attempt times out. (nsbindtimeout).">

+                             Bind Timeout

+                         </Col>

+                         <Col sm={8}>

+                             <input className="ds-input-auto" type="text" id="defBindTimeout" onChange={this.handleChange} defaultValue={this.state.defBindTimeout} />

+                         </Col>

+                     </Row>

+                     <Row className="ds-margin-top">

+                         <Col componentClass={ControlLabel} sm={4} title="The number of times the database link tries to bind with the remote server after a connection failure. (nsbindretrylimit).">

+                             Bind Retry Limit

+                         </Col>

+                         <Col sm={8}>

+                             <input className="ds-input-auto" type="text" id="defBindRetryLimit" onChange={this.handleChange} defaultValue={this.state.defBindRetryLimit} />

+                         </Col>

+                     </Row>

+                     <Row className="ds-margin-top">

+                         <Col componentClass={ControlLabel} sm={4} title="Sets whether ACIs are evaluated on the database link as well as the remote data server (nschecklocalaci).">

+                             Check Local ACIs

+                         </Col>

+                         <Col sm={8}>

+                             <input type="checkbox" onChange={this.handleChange} defaultChecked={this.state.defCheckAci} className="ds-config-checkbox" id="nsusdefCheckAciestarttls" />

+                         </Col>

+                     </Row>

+                     <Row className="ds-margin-top">

+                         <Col componentClass={ControlLabel} sm={4} title="Sets whether referrals are returned by scoped searches (meaning 'one-level' or 'subtree' scoped searches). (nsreferralonscopedsearch).">

+                             Send Referral On Scoped Search

+                         </Col>

+                         <Col sm={8}>

+                             <input type="checkbox" onChange={this.handleChange} defaultChecked={this.state.defRefOnScoped} className="ds-config-checkbox" id="defRefOnScoped" />

+                         </Col>

+                     </Row>

+                     <Row className="ds-margin-top">

+                         <Col componentClass={ControlLabel} sm={4} title="Sets whether ACIs are evaluated on the database link as well as the remote data server (nschecklocalaci).">

+                             Allow Proxied Authentication

+                         </Col>

+                         <Col sm={8}>

+                             <input type="checkbox" onChange={this.handleChange} defaultChecked={this.state.defProxy} className="ds-config-checkbox" id="defProxy" />

+                         </Col>

+                     </Row>

+                     <Row className="ds-margin-top">

+                         <Col componentClass={ControlLabel} sm={4} title="Sets whether referrals are returned by scoped searches (meaning 'one-level' or 'subtree' scoped searches). (nsreferralonscopedsearch).">

+                             Use StartTLS

+                         </Col>

+                         <Col sm={8}>

+                             <input type="checkbox" onChange={this.handleChange} defaultChecked={this.state.defUseStartTLS} className="ds-config-checkbox" id="defUseStartTLS" />

+                         </Col>

+                     </Row>

+                     <Row className="ds-margin-top-lg">

+                         <Col sm={5}>

+                             <button className="btn btn-primary save-button" onClick={this.save_chaining_config}>Save Default Settings</button>

+                         </Col>

+                     </Row>

+                 </Form>

  

                  <ChainControlsModal

                      showModal={this.state.showOidModal}

@@ -598,6 +678,8 @@ 

                  errObj: {},

                  showDeleteConfirm: false,

                  linkPwdMatch: true,

+                 modalSpinning: false,

+                 modalChecked: false,

                  // Settings

                  nsfarmserverurl: this.props.data.nsfarmserverurl,

                  nsmultiplexorbinddn: this.props.data.nsmultiplexorbinddn,

@@ -655,15 +737,23 @@ 

          this.closeDeleteConfirm = this.closeDeleteConfirm.bind(this);

      }

  

+     componentDidMount() {

+         this.props.enableTree();

+     }

+ 

      showDeleteConfirm () {

          this.setState({

-             showDeleteConfirm: true

+             showDeleteConfirm: true,

+             modalSpinning: false,

+             modalChecked: false,

          });

      }

  

      closeDeleteConfirm () {

          this.setState({

-             showDeleteConfirm: false

+             showDeleteConfirm: false,

+             modalSpinning: false,

+             modalChecked: false,

          });

      }

  

@@ -874,89 +964,26 @@ 

  

      render () {

          const error = this.state.errObj;

-         let useStartTLSCheckBox;

-         let checkLocalAci;

-         let referralOnScope;

-         let proxiedAuth;

- 

-         // Check local aci's checkbox

-         if (this.state.nschecklocalaci) {

-             checkLocalAci =

-                 <Checkbox id="nschecklocalaci" onChange={this.handleChange} key={this.state.nschecklocalaci} defaultChecked

-                     title="Sets whether ACIs are evaluated on the database link as well as the remote data server (nschecklocalaci).">

-                     Check Local ACIs

-                 </Checkbox>;

-         } else {

-             checkLocalAci =

-                 <Checkbox id="nschecklocalaci" onChange={this.handleChange} key={this.state.nschecklocalaci}

-                     title="Sets whether ACIs are evaluated on the database link as well as the remote data server (nschecklocalaci).">

-                     Check Local ACIs

-                 </Checkbox>;

-         }

-         // Referral on scoped search checkbox

-         if (this.state.nsreferralonscopedsearch) {

-             referralOnScope =

-                 <Checkbox id="nsreferralonscopedsearch" onChange={this.handleChange} defaultChecked

-                     title="Sets whether referrals are returned by scoped searches (meaning 'one-level' or 'subtree' scoped searches). (nsreferralonscopedsearch).">

-                     Send Referral On Scoped Search

-                 </Checkbox>;

-         } else {

-             referralOnScope =

-                 <Checkbox id="nsreferralonscopedsearch" onChange={this.handleChange}

-                     title="Sets whether referrals are returned by scoped searches (meaning 'one-level' or 'subtree' scoped searches). (nsreferralonscopedsearch).">

-                     Send Referral On Scoped Search

-                 </Checkbox>;

-         }

-         // Allow proxied auth checkbox

-         if (this.state.nsproxiedauthorization) {

-             proxiedAuth =

-                 <Checkbox id="nsproxiedauthorization" onChange={this.handleChange} defaultChecked

-                     title="Allow proxied authentication to the remote server. (nsproxiedauthorization).">

-                     Allow Proxied Authentication

-                 </Checkbox>;

-         } else {

-             proxiedAuth =

-                 <Checkbox id="nsproxiedauthorization" onChange={this.handleChange}

-                     title="Allow proxied authentication to the remote server. (nsproxiedauthorization).">

-                     Allow Proxied Authentication

-                 </Checkbox>;

-         }

-         // use startTLS checkbox

-         if (this.state.nsusestarttls) {

-             useStartTLSCheckBox =

-                 <Checkbox id="nsusestarttls" onChange={this.handleChange} title="Use StartTLS for connection to remote server. (nsusestarttls)"

-                     defaultChecked

-                 >

-                     Use StartTLS for remote connection

-                 </Checkbox>;

-         } else {

-             useStartTLSCheckBox =

-                 <Checkbox id="nsusestarttls" onChange={this.handleChange} title="Use StartTLS for connection to remote server. (nsusestarttls)">

-                     Use StartTLS for remote connection

-                 </Checkbox>;

-         }

  

          return (

-             <div className="container-fluid">

+             <div>

                  <Row>

-                     <Col sm={8} className="ds-word-wrap">

+                     <Col sm={10} className="ds-word-wrap">

                          <ControlLabel className="ds-suffix-header"><Icon type="fa" name="link" /> <b>{this.props.suffix}</b> (<i>{this.props.bename}</i>)</ControlLabel>

                      </Col>

                      <Col sm={2}>

                          <Button

-                             bsStyle="primary"

+                             bsStyle="danger"

                              onClick={this.showDeleteConfirm}

                          >

                              Delete Link

                          </Button>

                      </Col>

                  </Row>

-                 <h4>Database Link Configuration</h4>

-                 <hr />

-                 <Form horizontal autoComplete="off">

+                 <Form horizontal autoComplete="off" className="ds-margin-top-xlg">

                      <Row title="The LDAP URL for the remote server.  Add additional failure server URLs by separating them with a space. (nsfarmserverurl)">

-                         <Col sm={4}>

-                             <ControlLabel>Remote Server LDAP URL</ControlLabel>

+                         <Col componentClass={ControlLabel} sm={4}>

+                             Remote Server LDAP URL

                          </Col>

                          <Col sm={8}>

                              <FormControl

@@ -968,10 +995,9 @@ 

                              />

                          </Col>

                      </Row>

-                     <p />

-                     <Row title="The distinguished name (DN) of the entry to authenticate to the remote server. (nsmultiplexorbinddn)">

-                         <Col sm={4}>

-                             <ControlLabel>Remote Server Bind DN</ControlLabel>

+                     <Row className="ds-margin-top" title="The distinguished name (DN) of the entry to authenticate to the remote server. (nsmultiplexorbinddn)">

+                         <Col componentClass={ControlLabel} sm={4}>

+                             Remote Server Bind DN

                          </Col>

                          <Col sm={8}>

                              <FormControl

@@ -983,10 +1009,9 @@ 

                              />

                          </Col>

                      </Row>

-                     <p />

-                     <Row title="The password for the authenticating entry. (nsmultiplexorcredentials)">

-                         <Col sm={4}>

-                             <ControlLabel>Bind DN Password</ControlLabel>

+                     <Row className="ds-margin-top" title="The password for the authenticating entry. (nsmultiplexorcredentials)">

+                         <Col componentClass={ControlLabel} sm={4}>

+                             Bind DN Password

                          </Col>

                          <Col sm={8}>

                              <FormControl

@@ -998,10 +1023,9 @@ 

                              />

                          </Col>

                      </Row>

-                     <p />

-                     <Row title="Confirm the password for the authenticating entry. (nsmultiplexorcredentials)">

-                         <Col sm={4}>

-                             <ControlLabel>Confirm Password</ControlLabel>

+                     <Row className="ds-margin-top" title="Confirm the password for the authenticating entry. (nsmultiplexorcredentials)">

+                         <Col componentClass={ControlLabel} sm={4}>

+                             Confirm Password

                          </Col>

                          <Col sm={8}>

                              <FormControl

@@ -1013,10 +1037,9 @@ 

                              />

                          </Col>

                      </Row>

-                     <p />

-                     <Row title="The authentication mechanism.  Simple (user name and password), SASL/DIGEST-MD5, or SASL>GSSAPI. (nsbindmechanism)">

-                         <Col sm={4}>

-                             <ControlLabel>Bind Mechanism</ControlLabel>

+                     <Row className="ds-margin-top" title="The authentication mechanism.  Simple (user name and password), SASL/DIGEST-MD5, or SASL>GSSAPI. (nsbindmechanism)">

+                         <Col componentClass={ControlLabel} sm={4}>

+                             Bind Mechanism

                          </Col>

                          <Col sm={8}>

                              <select value={this.state.nsbindmechanism}

@@ -1030,87 +1053,214 @@ 

                              </select>

                          </Col>

                      </Row>

-                     <p />

-                     <Row>

-                         <Col sm={9}>

-                             {useStartTLSCheckBox}

+                     <Row className="ds-margin-top" title="Use StartTLS for connections to the remote server. (nsusestarttls)">

+                         <Col componentClass={ControlLabel} sm={4}>

+                             Use StartTLS

+                         </Col>

+                         <Col sm={8}>

+                             <input type="checkbox" onChange={this.props.handleChange} defaultChecked={this.state.nsusestarttls} className="ds-config-checkbox" id="nsusestarttls" />

                          </Col>

                      </Row>

                  </Form>

-                 <p />

  

-                 <CustomCollapse>

-                     <div className="ds-margin-top">

-                         <div className="ds-margin-left">

-                             <div>

-                                 <label htmlFor="sizelimit" className="ds-config-label" title="The size limit of entries returned over a database link (nsslapd-sizelimit).">

-                                     Size Limit</label><input onChange={this.handleChange} defaultValue={this.state.sizelimit} className="ds-input" type="text" id="sizelimit" size="15" />

-                             </div>

-                             <div>

-                                 <label htmlFor="timelimit" className="ds-config-label" title="The time limit of an operation over a database link (nsslapd-timelimit).">

-                                     Time Limit</label><input onChange={this.handleChange} defaultValue={this.state.timelimit} className="ds-input" type="text" id="timelimit" size="15" />

-                             </div>

-                             <div>

-                                 <label htmlFor="bindconnlimit" className="ds-config-label" title="The maximum number of TCP connections the database link establishes with the remote server.  (nsbindconnectionslimit).">

-                                     Max TCP Connections</label><input onChange={this.handleChange} defaultValue={this.state.bindconnlimit} className="ds-input" type="text" id="bindconnlimit" size="15" />

-                             </div>

-                             <div>

-                                 <label htmlFor="opconnlimit" className="ds-config-label" title="The maximum number of connections allowed over the database link.  (nsoperationconnectionslimit).">

-                                     Max LDAP Connections</label><input onChange={this.handleChange} defaultValue={this.state.opconnlimit} className="ds-input" type="text" id="opconnlimit" size="15" />

-                             </div>

-                             <div>

-                                 <label htmlFor="concurrbindlimit" className="ds-config-label" title="The maximum number of concurrent bind operations per TCP connection. (nsconcurrentbindlimit).">

-                                     Max Binds Per Connection</label><input onChange={this.handleChange} defaultValue={this.state.concurrbindlimit} className="ds-input" type="text" id="concurrbindlimit" size="15" />

-                             </div>

-                             <div>

-                                 <label htmlFor="bindtimeout" className="ds-config-label" title="The amount of time before the bind attempt times out. (nsbindtimeout).">

-                                     Bind Timeout</label><input onChange={this.handleChange} defaultValue={this.state.bindtimeout} className="ds-input" type="text" id="bindtimeout" size="15" />

-                             </div>

- 

-                             <div>

-                                 <label htmlFor="bindretrylimit" className="ds-config-label" title="The number of times the database link tries to bind with the remote server after a connection failure. (nsbindretrylimit).">

-                                     Bind Retry Limit</label><input onChange={this.handleChange} defaultValue={this.state.bindretrylimit} className="ds-input" type="text" id="bindretrylimit" size="15" />

-                             </div>

-                             <div>

-                                 <label htmlFor="concurroplimit" className="ds-config-label" title="The maximum number of operations per connections. (nsconcurrentoperationslimit).">

-                                     Max Operations Per Connection</label><input onChange={this.handleChange} defaultValue={this.state.concurroplimit} className="ds-input" type="text" id="concurroplimit" size="15" />

-                             </div>

-                             <div>

-                                 <label htmlFor="connlifetime" className="ds-config-label" title="The life of a database link connection to the remote server.  0 is unlimited  (nsconnectionlife).">

-                                     Connection Lifetime (in seconds)</label><input onChange={this.handleChange} defaultValue={this.state.connlifetime} className="ds-input" type="text" id="connlifetime" size="15" />

-                             </div>

-                             <div>

-                                 <label htmlFor="searchcheckinterval" className="ds-config-label" title="The number of seconds that pass before the server checks for abandoned operations.  (nsabandonedsearchcheckinterval).">

-                                     Abandoned Op Check Interval</label><input onChange={this.handleChange} defaultValue={this.state.searchcheckinterval} className="ds-input" type="text" id="searchcheckinterval" size="15" />

-                             </div>

-                             <div>

-                                 <label htmlFor="hoplimit" className="ds-config-label" title="The maximum number of times a request can be forwarded from one database link to another.  (nshoplimit).">

-                                     Database Link Hop Limit</label><input onChange={this.handleChange} defaultValue={this.state.hoplimit} className="ds-input" type="text" id="hoplimit" size="15" />

-                             </div>

-                             <p />

-                             <div>

-                                 {proxiedAuth}

-                             </div>

-                             <div>

-                                 {checkLocalAci}

-                             </div>

-                             <div>

-                                 {referralOnScope}

-                             </div>

-                         </div>

-                     </div>

+                 <CustomCollapse className="ds-margin-top">

+                     <Form horizontal className="ds-margin-top ds-margin-left">

+                         <Row className="ds-margin-top" title="The size limit of entries returned over a database link (nsslapd-sizelimit).">

+                             <Col componentClass={ControlLabel} sm={4}>

+                                 Size Limit

+                             </Col>

+                             <Col sm={8}>

+                                 <FormControl

+                                     type="text"

+                                     id="sizelimit"

+                                     className="ds-input-auto"

+                                     onChange={this.handleChange}

+                                     defaultValue={this.state.sizelimit}

+                                 />

+                             </Col>

+                         </Row>

+                         <Row className="ds-margin-top" title="The time limit of an operation over a database link (nsslapd-timelimit).">

+                             <Col componentClass={ControlLabel} sm={4}>

+                                 Time Limit

+                             </Col>

+                             <Col sm={8}>

+                                 <FormControl

+                                     type="text"

+                                     id="timelimit"

+                                     className="ds-input-auto"

+                                     onChange={this.handleChange}

+                                     defaultValue={this.state.timelimit}

+                                 />

+                             </Col>

+                         </Row>

+                         <Row className="ds-margin-top" title="The maximum number of TCP connections the database link establishes with the remote server.  (nsbindconnectionslimit).">

+                             <Col componentClass={ControlLabel} sm={4}>

+                                 Max TCP Connections

+                             </Col>

+                             <Col sm={8}>

+                                 <FormControl

+                                     type="text"

+                                     id="bindconnlimit"

+                                     className="ds-input-auto"

+                                     onChange={this.handleChange}

+                                     defaultValue={this.state.bindconnlimit}

+                                 />

+                             </Col>

+                         </Row>

+                         <Row className="ds-margin-top" title="The maximum number of connections allowed over the database link.  (nsoperationconnectionslimit).">

+                             <Col componentClass={ControlLabel} sm={4}>

+                                 Max LDAP Connections

+                             </Col>

+                             <Col sm={8}>

+                                 <FormControl

+                                     type="text"

+                                     id="opconnlimit"

+                                     className="ds-input-auto"

+                                     onChange={this.handleChange}

+                                     defaultValue={this.state.opconnlimit}

+                                 />

+                             </Col>

+                         </Row>

+                         <Row className="ds-margin-top" title="The maximum number of concurrent bind operations per TCP connection. (nsconcurrentbindlimit).">

+                             <Col componentClass={ControlLabel} sm={4}>

+                                 Max Binds Per Connection

+                             </Col>

+                             <Col sm={8}>

+                                 <FormControl

+                                     type="text"

+                                     id="concurrbindlimit"

+                                     className="ds-input-auto"

+                                     onChange={this.handleChange}

+                                     defaultValue={this.state.concurrbindlimit}

+                                 />

+                             </Col>

+                         </Row>

+                         <Row className="ds-margin-top" title="The amount of time before the bind attempt times out. (nsbindtimeout).">

+                             <Col componentClass={ControlLabel} sm={4}>

+                                 Bind Timeout

+                             </Col>

+                             <Col sm={8}>

+                                 <FormControl

+                                     type="text"

+                                     id="bindtimeout"

+                                     className="ds-input-auto"

+                                     onChange={this.handleChange}

+                                     defaultValue={this.state.bindtimeout}

+                                 />

+                             </Col>

+                         </Row>

+                         <Row className="ds-margin-top" title="The number of times the database link tries to bind with the remote server after a connection failure. (nsbindretrylimit).">

+                             <Col componentClass={ControlLabel} sm={4}>

+                                 Bind Retry Limit

+                             </Col>

+                             <Col sm={8}>

+                                 <FormControl

+                                     type="text"

+                                     id="bindretrylimit"

+                                     className="ds-input-auto"

+                                     onChange={this.handleChange}

+                                     defaultValue={this.state.bindretrylimit}

+                                 />

+                             </Col>

+                         </Row>

+                         <Row className="ds-margin-top" title="The maximum number of operations per connections. (nsconcurrentoperationslimit).">

+                             <Col componentClass={ControlLabel} sm={4}>

+                                 Max Operations Per Connection

+                             </Col>

+                             <Col sm={8}>

+                                 <FormControl

+                                     type="text"

+                                     id="concurroplimit"

+                                     className="ds-input-auto"

+                                     onChange={this.handleChange}

+                                     defaultValue={this.state.concurroplimit}

+                                 />

+                             </Col>

+                         </Row>

+                         <Row className="ds-margin-top" title="The life of a database link connection to the remote server in seconds.  0 is unlimited  (nsconnectionlife).">

+                             <Col componentClass={ControlLabel} sm={4}>

+                                 Connection Lifetime

+                             </Col>

+                             <Col sm={8}>

+                                 <FormControl

+                                     type="text"

+                                     id="connlifetime"

+                                     className="ds-input-auto"

+                                     onChange={this.handleChange}

+                                     defaultValue={this.state.connlifetime}

+                                 />

+                             </Col>

+                         </Row>

+                         <Row className="ds-margin-top" title="The number of seconds that pass before the server checks for abandoned operations.  (nsabandonedsearchcheckinterval).">

+                             <Col componentClass={ControlLabel} sm={4}>

+                                 Abandoned Op Check Interval