From b844aab6eaf47c8991c3ba99da7f281ad3c5dfcf Mon Sep 17 00:00:00 2001 From: Simon Pichugin Date: Nov 30 2018 10:02:04 +0000 Subject: Issue 50041 - Set the React dataflow foundation and add basic plugin UI Description: Add basic plugin functionality - Table and Modal. Add Notificationcontroller component which can be used by other components in the future. Add cockpit component for onoff switch. Add custoTableToolbar component with search field and loading spinner. Add edit option to Plugin CLI. Fix ds.css according to eslint. Remove custom OnOffSwitch component because Patternfly seems to work okay. Move the start/stop/restart and change server-select event listners to the "document is ready" part. React requires the change. https://pagure.io/389-ds-base/issue/50041 Reviewed by: mreynolds, mhonek (Thanks!) --- diff --git a/src/cockpit/389-console/.eslintrc.json b/src/cockpit/389-console/.eslintrc.json index 3b7538e..11a82c8 100644 --- a/src/cockpit/389-console/.eslintrc.json +++ b/src/cockpit/389-console/.eslintrc.json @@ -33,6 +33,7 @@ "jsx-quotes": "off", "key-spacing": "off", "no-console": "off", + "no-debugger": "off", "quotes": "off", "react/jsx-curly-spacing": "off", "react/jsx-indent-props": "off", diff --git a/src/cockpit/389-console/src/banner.html b/src/cockpit/389-console/src/banner.html index f919ed8..d609aec 100644 --- a/src/cockpit/389-console/src/banner.html +++ b/src/cockpit/389-console/src/banner.html @@ -14,4 +14,3 @@
  • Create Instance
  • - diff --git a/src/cockpit/389-console/src/css/ds.css b/src/cockpit/389-console/src/css/ds.css index de35f07..e75853b 100644 --- a/src/cockpit/389-console/src/css/ds.css +++ b/src/cockpit/389-console/src/css/ds.css @@ -1,643 +1,640 @@ - .ds-logo { - margin: 5px; - background-color: white !important; + margin: 5px; + background-color: white !important; } .ds-logo-style { - margin: 10px; - margin-bottom: 20px; + margin: 10px; + margin-bottom: 20px; } .ds-logo-hr { - padding: 0 !important; - margin-top: -20px !important; - line-height:0; + padding: 0 !important; + margin-top: -20px !important; + line-height: 0; } .ds-title-hr { - margin: 0 !important; - padding: 0 !important; - margin-right: 10px !important; - margin-bottom: 10px !important; + margin: 0 !important; + padding: 0 !important; + margin-right: 10px !important; + margin-bottom: 10px !important; } .ds-container { - margin: 0; - padding: 0 !important; - display: flex; + margin: 0; + padding: 0 !important; + display: flex; } .ds-inline { - display: inline-block !important; - vertical-align: top !important; + display: inline-block !important; + vertical-align: top !important; } .ds-fixed { - padding: 0 !important; - padding-bottom: 10px; - width: 175px !important; - min-width: 175px !important; - margin: 2px 2px 2px 0px !important; - line-height:0; + padding: 0 !important; + padding-bottom: 10px; + width: 175px !important; + min-width: 175px !important; + margin: 2px 2px 2px 0px !important; + line-height: 0; } .ds-content { - padding: 0; - padding-top: 115px; - padding-bottom: 50px; - margin-top: 0; - margin-left: 25px; - margin-right: 10px; - margin-bottom: 10px; + padding: 0; + padding-top: 115px; + padding-bottom: 50px; + margin-top: 0; + margin-left: 25px; + margin-right: 10px; + margin-bottom: 10px; } - .ds-flex { - /* background-color: #f7f7f7; */ - background-color: white !important; - flex-grow: 1; - border: 1px groove black; - border-style: groove; - margin: 6px 2px 2px 10px; - margin-left: 0px !important; - margin-right: 10px; - margin-bottom: 10px; - padding-left: 15px; - padding-right: 15px; - padding-top: 0px; - padding-bottom: 0px; - min-height: 500px; - line-height:0; - border-radius: 5px; + /* background-color: #f7f7f7; */ + background-color: white !important; + flex-grow: 1; + border: 1px groove black; + border-style: groove; + margin: 6px 2px 2px 10px; + margin-left: 0px !important; + margin-right: 10px; + margin-bottom: 10px; + padding-left: 15px; + padding-right: 15px; + padding-top: 0px; + padding-bottom: 0px; + min-height: 500px; + line-height: 0; + border-radius: 5px; } .ds-repl-state-good { - margin: auto; - width: 30px; - height: 30px; - border-radius: 50%; - font-size: 12px; - font-weight: bold; - color: white; - line-height: 1; - text-align: center; - background-color: #4dac26; - border-color: black; - padding-top: 8px; - align-content: center !important; - vertical-align: middle !important; + margin: auto; + width: 30px; + height: 30px; + border-radius: 50%; + font-size: 12px; + font-weight: bold; + color: white; + line-height: 1; + text-align: center; + background-color: #4dac26; + border-color: black; + padding-top: 8px; + align-content: center !important; + vertical-align: middle !important; } .ds-repl-state-bad { - margin: auto; - width: 30px; - height: 30px; - border-radius: 50%; - font-size: 12px; - font-weight: bold; - color: white; - line-height: 1; - text-align: center; - background-color: #d01c8b; - border-color: black; - padding-top: 8px; - align-content: center !important; - vertical-align: middle !important; + margin: auto; + width: 30px; + height: 30px; + border-radius: 50%; + font-size: 12px; + font-weight: bold; + color: white; + line-height: 1; + text-align: center; + background-color: #d01c8b; + border-color: black; + padding-top: 8px; + align-content: center !important; + vertical-align: middle !important; } .ds-chart-right { - margin-left: 90px; + margin-left: 90px; } .ds-chart-left { - margin-left: 25px; - margin-bottom: 9px; + margin-left: 25px; + margin-bottom: 9px; } .ds-chart-center { - margin-left: 100px; - margin-bottom: 15px; + margin-left: 100px; + margin-bottom: 15px; } .ds-repl-lag-bad { - font-weight: bold; - color: #7b3294; + font-weight: bold; + color: #7b3294; } .ds-button-border { - line-height:0; - margin: 0px; - padding-top: 0px; - padding-bottom: 10px; + line-height: 0; + margin: 0px; + padding-top: 0px; + padding-bottom: 10px; } .ds-button { - height: 30px; - width: 160px !important; - margin-top: 5px; - float:none; - left:auto; - line-height:normal; - overflow:visible; - position:static; + height: 30px; + width: 160px !important; + margin-top: 5px; + float: none; + left: auto; + line-height: normal; + overflow: visible; + position: static; } .ds-oc-add-del-btn { - padding: 0 !important; - margin: 10px !important; - width: 130px; - height: 26px; - text-align: center; + padding: 0 !important; + margin: 10px !important; + width: 130px; + height: 26px; + text-align: center; } .ds-oc-must-buttons { - padding: 0 !important; - padding-left: 3px; - margin-top: 70px; - margin-bottom: 75px; - margin-left: 5px; - margin-right: 9px; + padding: 0 !important; + padding-left: 3px; + margin-top: 70px; + margin-bottom: 75px; + margin-left: 5px; + margin-right: 9px; } .ds-oc-may-buttons { - padding 0: !important; - padding-left: 3px; - margin-top: 4px; - margin-left: 5px; - margin-right: 9px; + padding0: !important; + padding-left: 3px; + margin-top: 4px; + margin-left: 5px; + margin-right: 9px; } .ds-panel { - margin: 0px 0px 0px 0px; - padding-top: 10px; - padding-left: 10px; - line-height:0; + margin: 0px 0px 0px 0px; + padding-top: 10px; + padding-left: 10px; + line-height: 0; } .ds-dropdown { - padding: 0px; - padding-left: 5px; - height: 35px; - width: 300px !important; - margin-top: 10px; - text-align: left; - outline: 0 !important; + padding: 0px; + padding-left: 5px; + height: 35px; + width: 300px !important; + margin-top: 10px; + text-align: left; + outline: 0 !important; } .ds-dropdown-server { - margin-top: 0px !important; - margin-left: 6px; - padding: 0px !important; - padding-left: 10px !important; - padding-right: 10px !important; - height: 30px; - text-align: left; + margin-top: 0px !important; + margin-left: 6px; + padding: 0px !important; + padding-left: 10px !important; + padding-right: 10px !important; + height: 30px; + text-align: left; } .ds-passwd-dropdown { - height: 35px !important; - padding: 0px !important; - outline: 0 !important; - width: 150px !important; + height: 35px !important; + padding: 0px !important; + outline: 0 !important; + width: 150px !important; } .ds-log-dropdown { - margin-left: 10px; - padding: 0px !important; - outline: 0 !important; - width: 65px !important; + margin-left: 10px; + padding: 0px !important; + outline: 0 !important; + width: 65px !important; } .ds-rootdn-passwd-dropdown { - margin-left: 30px; - margin-top: 5px; - padding: 10px; - outline: 0 !important; - width: 175px; - border-radius: 5px; + margin-left: 30px; + margin-top: 5px; + padding: 10px; + outline: 0 !important; + width: 175px; + border-radius: 5px; } .ds-table { - padding: 0px; - border: 1px solid #909090; - line-height:1; - margin-top: 10px !important; - margin-bottom: 10px !important; + padding: 0px; + border: 1px solid #909090; + line-height: 1; + margin-top: 10px !important; + margin-bottom: 10px !important; } .ds-referral-table { - padding: 0px !important; - margin-top: 10px !important; - margin-bottom: 10px !important; - border: 1px solid #909090; - line-height:1; + padding: 0px !important; + margin-top: 10px !important; + margin-bottom: 10px !important; + border: 1px solid #909090; + line-height: 1; } .dataTables_wrapper { - padding: 0px !important; - margin-bottom: 10px !important; + padding: 0px !important; + margin-bottom: 10px !important; } td { - white-space:normal; - word-wrap: break-word !important; - max-width: 400px !important; - + white-space: normal; + word-wrap: break-word !important; + max-width: 400px !important; } .ds-hr { - margin-top: 0.5em; - margin-bottom: 0.5em; - border-style: inset; - border-width: 1px; - padding: 0px !important; + margin-top: 0.5em; + margin-bottom: 0.5em; + border-style: inset; + border-width: 1px; + padding: 0px !important; } .ds-hr-logs { - display: block; - margin-left:0; - margin-top: 0.5em; - margin-bottom: 0.5em; - border-style: inset; - border-width: 1px; - padding: 0px !important; - width: 525px; + display: block; + margin-left: 0; + margin-top: 0.5em; + margin-bottom: 0.5em; + border-style: inset; + border-width: 1px; + padding: 0px !important; + width: 525px; } .ds-hr-pwp { - display: block; - margin-top: 0.5em; - margin-bottom: 0.5em; - margin-left: 0 !important; - border-style: inset; - border-width: 1px; - padding: 0px !important; - width: 835px; + display: block; + margin-top: 0.5em; + margin-bottom: 0.5em; + margin-left: 0 !important; + border-style: inset; + border-width: 1px; + padding: 0px !important; + width: 835px; } .ds-tree { - font-size: 0.5; - background-color: #F8F8F8; - border: 1px solid #909090 ; - color: black; - line-height: 2; - width: 300px; - min-width: 300px; - min-height: 400px; - max-height: 400px; - margin: 23px 10px 2px 0px; - overflow: auto; + font-size: 0.5; + background-color: #f8f8f8; + border: 1px solid #909090; + color: black; + line-height: 2; + width: 300px; + min-width: 300px; + min-height: 400px; + max-height: 400px; + margin: 23px 10px 2px 0px; + overflow: auto; } .ds-monitor-tree { - font-size: 0.5; - background-color: #F8F8F8; - border: 1px solid #909090 ; - color: black; - line-height: 2; - width: 275px; - min-width: 275px; - min-height: 400px; - max-height: 400px; - margin: 10px; - overflow: auto; + font-size: 0.5; + background-color: #f8f8f8; + border: 1px solid #909090; + color: black; + line-height: 2; + width: 275px; + min-width: 275px; + min-height: 400px; + max-height: 400px; + margin: 10px; + overflow: auto; } .ds-treenode { - border: 0 !important; + border: 0 !important; } .ds-treenode ul { - border: 0 !important; + border: 0 !important; } .ds-treenode li { - border: 0 !important; + border: 0 !important; } .ds-split { - width: 400px; + width: 400px; } .ds-modal-header { - font-size: 16px; + font-size: 16px; } .ds-input { - margin-top: 5px !important; - padding-right: 5px !important; - padding-left: 5px !important; + margin-top: 5px !important; + padding-right: 5px !important; + padding-left: 5px !important; } .ds-pw-input { - margin-top: 5px; - padding-right: 5px; - padding-left: 5px !important; - min-width: 65px !important; - max-width: 65px !important; + margin-top: 5px; + padding-right: 5px; + padding-left: 5px !important; + min-width: 65px !important; + max-width: 65px !important; } .ds-pw-list-input { - margin-top: 5px; - padding-right: 5px; - padding-left: 5px !important; - min-width: 150px !important; - max-width: 150px !important; + margin-top: 5px; + padding-right: 5px; + padding-left: 5px !important; + min-width: 150px !important; + max-width: 150px !important; } .ds-ro-input { - margin-top: 5px; - padding-left: 5px; - margin-right: 5px; - background-color: #F8F8F8 !important; + margin-top: 5px; + padding-left: 5px; + margin-right: 5px; + background-color: #f8f8f8 !important; } .ds-input-lrg { - width: 315px !important; - height: 37px !important; - margin-top: 5px; - padding-right: 10px; - height: 37px !important; + width: 315px !important; + height: 37px !important; + margin-top: 5px; + padding-right: 10px; + height: 37px !important; } .ds-input-long { - width: 500px !important; + width: 500px !important; } .ds-input-max { - margin-left: 10px; - margin-bottom: 20px; - width: 500px; - max-width: 600px; + margin-left: 10px; + margin-bottom: 20px; + width: 500px; + max-width: 600px; } .ds-repl-mgr { - max-width: 600px !important; + max-width: 600px !important; } .ds-role-input { - height: 30px !important; - min-height: 30px; - margin-top: 5px; - margin-left: 7px; - border-radius: 3px; - padding-left: 5px !important; + height: 30px !important; + min-height: 30px; + margin-top: 5px; + margin-left: 7px; + border-radius: 3px; + padding-left: 5px !important; } .ds-ref-input { - width: 300px !important; - padding-left: 5px; + width: 300px !important; + padding-left: 5px; } .ds-history-input { - margin-top: !important; - margin-right: 5px; - margin-left: 40px; + margin-top: !important; + margin-right: 5px; + margin-left: 40px; } .ds-form-input { - margin-left: 10px; + margin-left: 10px; } .ds-divider { - width: 35px; + width: 35px; } .ds-divider-med { - width: 15px; + width: 15px; } .ds-div-right { - width: 50% !important; - margin: 2px 2px 2px 2px; + width: 50% !important; + margin: 2px 2px 2px 2px; } .ds-div { - width: 50% !important; - margin: 2px 2px 2px 2px; + width: 50% !important; + margin: 2px 2px 2px 2px; } .ds-button-save { - width: 100px; - margin: 2px 2px 2px 215px; + width: 100px; + margin: 2px 2px 2px 215px; } .ds-changelog-button { - width: 150px; - height: 32px; - margin-top: 0px !important; - margin-left: 5px; - margin-bottom: 4px; + width: 150px; + height: 32px; + margin-top: 0px !important; + margin-left: 5px; + margin-bottom: 4px; } .ds-ref-button { - margin-right: 20px; - min-width: 110px !important; - max-width: 110px !important; + margin-right: 20px; + min-width: 110px !important; + max-width: 110px !important; } .ds-repl-manager { - margin-top: 5px; - padding: 5px; - resize: none; - width: 305px; - height: 100px; - white-space: pre !important; + margin-top: 5px; + padding: 5px; + resize: none; + width: 305px; + height: 100px; + white-space: pre !important; } .ds-roles { - padding: 5px !important; - margin-bottom: 5px; + padding: 5px !important; + margin-bottom: 5px; } .ds-radio { - margin: 5px !important; + margin: 5px !important; } .ds-repl-managers-list { - width: 420px; - height: 200px; + width: 420px; + height: 200px; } .ds-repl-managers-button { - margin-top: -15px; - margin-bottom: 10px; - margin-left: 0px; + margin-top: -15px; + margin-bottom: 10px; + margin-left: 0px; } .ds-repl-manager-checkbox { - margin-top: 20px !important; - padding-top: 20px !important; - margin-left: 10px !important; - margin-right: 10px !important; + margin-top: 20px !important; + padding-top: 20px !important; + margin-left: 10px !important; + margin-right: 10px !important; } .ds-label { - vertical-align: middle !important; /* Fixes any weird issues in Firefox and IE */ + vertical-align: middle !important; /* Fixes any weird issues in Firefox and IE */ } /* Replication styles */ -.ds-agmt-dropdown { - padding: 0px !important; - line-height: 0 !important; - overflow: visible !important; - width: auto !important; +.ds-agmt-dropdown { + padding: 0px !important; + line-height: 0 !important; + overflow: visible !important; + width: auto !important; } .ds-oc-dropdown { - margin-top: 5px; - color: #181818 !important; - padding: 0px !important; - line-height: 0 !important; - height: 30px; - max-height: 200px !important; - width: 315px !important; - text-align: left; - outline: 0 !important; - overflow:auto; + margin-top: 5px; + color: #181818 !important; + padding: 0px !important; + line-height: 0 !important; + height: 30px; + max-height: 200px !important; + width: 315px !important; + text-align: left; + outline: 0 !important; + overflow: auto; } .ds-ref-dropdown { - width: 300px !important; - text-align: left; + width: 300px !important; + text-align: left; } .ds-agmt-wiz-dropdown { - width: 175px !important; - text-align: left; + 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; + padding: 0px !important; + padding-left: 10px !important; + line-height: 0 !important; + height: 40px; + width: 175px !important; + text-align: left; } .ds-dblink-dropdown { - padding: 0px !important; - padding-right: 5px !important; - line-height: 0 !important; - width: 140px !important; - text-align: left; - outline: 0 !important; - margin-top: 5px; + padding: 0px !important; + padding-right: 5px !important; + line-height: 0 !important; + width: 140px !important; + text-align: left; + outline: 0 !important; + margin-top: 5px; } .ds-dblink-dropdown a { - padding: 0px !important; - padding-left: 10px !important; - line-height: 0 !important; - width: 140px !important; - text-align: left; + padding: 0px !important; + padding-left: 10px !important; + line-height: 0 !important; + width: 140px !important; + text-align: left; } .ds-dblink-form-input { - width: 415px !important; - margin-top: 5px; - padding-right: 10px; - height: 37px !important; + width: 415px !important; + margin-top: 5px; + padding-right: 10px; + height: 37px !important; } .ds-agmt-dropdown-button { - width: 120px; + width: 120px; } .ds-agmt-button { - height: 40px; - width: 210px; + height: 40px; + width: 210px; } .ds-sasl-button { - height: 35px; - width: 175px; -} - -.ds-repl-table { - background-color: white !important; - padding: 0px !important; - border: 1px solid #909090; - table-layout: fixed; - width: 100%; - clear: both; - word-wrap : break-word !important; - text-align: center; - margin-top: -10px !important; - line-height:1; -} - -.ds-sasl-table { - background-color: white !important; - padding: 0px; - border: 1px solid #909090; - table-layout: fixed; - clear: both; - word-wrap : break-word !important; - text-align: center; -} - -.ds-table { - background-color: white !important; - padding: 0px; - border: 1px solid #909090; - table-layout: fixed; - clear: both; - word-wrap : break-word !important; - text-align: center; - line-height:1; + height: 35px; + width: 175px; +} + +.ds-repl-table { + background-color: white !important; + padding: 0px !important; + border: 1px solid #909090; + table-layout: fixed; + width: 100%; + clear: both; + word-wrap: break-word !important; + text-align: center; + margin-top: -10px !important; + line-height: 1; +} + +.ds-sasl-table { + background-color: white !important; + padding: 0px; + border: 1px solid #909090; + table-layout: fixed; + clear: both; + word-wrap: break-word !important; + text-align: center; +} + +.ds-table { + background-color: white !important; + padding: 0px; + border: 1px solid #909090; + table-layout: fixed; + clear: both; + word-wrap: break-word !important; + text-align: center; + line-height: 1; } .ds-table-header th { - text-align: center !important; - background-color: white; + text-align: center !important; + background-color: white; } .ds-plugin-table { - padding: 0px; - border: 1px solid #909090; - line-height:1; - table-layout: fixed; - clear: both; - word-wrap : break-word; - text-align: center; + padding: 0px; + border: 1px solid #909090; + line-height: 1; + table-layout: fixed; + clear: both; + word-wrap: break-word; + text-align: center; } .ds-plugin-header th { - width: 100%; - text-align: center !important; + width: 100%; + text-align: center !important; } .ds-plugin-panel { - background-color: #f7f7f7; - flex-grow: 1; - border: 1px groove black; - border-style: groove; - margin: 6px 2px 2px 10px; - margin-left: 10px; - margin-right: 10px; - margin-bottom: 10px; - padding-left: 15px; - padding-right: 15px; - padding-top: 0px; - padding-bottom: 0px; + background-color: #f7f7f7; + flex-grow: 1; + border: 1px groove black; + border-style: groove; + margin: 6px 2px 2px 10px; + margin-left: 10px; + margin-right: 10px; + margin-bottom: 10px; + padding-left: 15px; + padding-right: 15px; + padding-top: 0px; + padding-bottom: 0px; } .ds-monitor-panel { - background-color: #f7f7f7; - flex-grow: 1; - border: 1px groove black; - border-style: groove; - margin: 6px 2px 2px 10px; - margin-left: 10px; - margin-right: 10px; - margin-bottom: 10px; - padding-left: 15px; - padding-right: 15px; - padding-top: 0px; - padding-bottom: 10px; + background-color: #f7f7f7; + flex-grow: 1; + border: 1px groove black; + border-style: groove; + margin: 6px 2px 2px 10px; + margin-left: 10px; + margin-right: 10px; + margin-bottom: 10px; + padding-left: 15px; + padding-right: 15px; + padding-top: 0px; + padding-bottom: 10px; } /* @@ -646,780 +643,798 @@ td { /* Extra styles for the cancel button */ .cancelbtn { - padding: 14px 20px; - background-color: #f44336; + padding: 14px 20px; + background-color: #f44336; } /* Float cancel and signup buttons and add an equal width */ -.cancelbtn,.savebtn { - float: left; - width: 50%; +.cancelbtn, +.savebtn { + float: left; + width: 50%; } /* Add padding to container elements */ .container { - width: 650px; - padding-left: 10px; - padding-right: 10px; - padding-bottom: 10px; + width: 650px; + padding-left: 10px; + padding-right: 10px; + padding-bottom: 10px; } .ds-modal { - width: 450px; + width: 450px; } .ds-modal-wide { - min-width: 850px; - vertical-align: middle; + min-width: 850px; + vertical-align: middle; } .modal-content { - position: absolute; - max-height: 750px; - max-width: 550px; - min-width: 400px; - overflow: auto; + position: absolute; + max-height: 750px; + max-width: 550px; + min-width: 400px; + overflow: auto; } .ds-log-panel { - padding: 0 18px; - max-height: 0 !important; - overflow: hidden !important; - transition: max-height 0.2s ease-out !important; - margin: 2px; - display: none; + padding: 0 18px; + max-height: 0 !important; + overflow: hidden !important; + transition: max-height 0.2s ease-out !important; + margin: 2px; + display: none; } .ds-suffix-panel { - padding: 0 18px; - max-height: 0 !important; - overflow: hidden !important; - transition: max-height 0.2s ease-out !important; - margin: 2px; - display: none !important; + padding: 0 18px; + max-height: 0 !important; + overflow: hidden !important; + transition: max-height 0.2s ease-out !important; + margin: 2px; + display: none !important; } .ds-agmt-wiz-button { - height: 40px; - width: 630px; - font-weight: bold; + height: 40px; + width: 630px; + font-weight: bold; } .ds-button-right { - width: 120px !important; - margin-top: 5px; - float: right !important; - display:inline-block !important; + width: 120px !important; + margin-top: 5px; + float: right !important; + display: inline-block !important; } .ds-close-button-right { - height: 40px; - width: 150px !important; - margin-top: 5px; - margin-bottom: 5px; - float: right !important; + height: 40px; + width: 150px !important; + margin-top: 5px; + margin-bottom: 5px; + float: right !important; } .ds-button-left { - width: 120px; - max-width: 150px; - margin-top: 5px; - float: left !important; - display:inline-block !important; + width: 120px; + max-width: 150px; + margin-top: 5px; + float: left !important; + display: inline-block !important; } .ds-panel-left { - width:50% + width: 50%; } .ds-panel-right { - width:50%; + width: 50%; } .ds-fractional-panel { - background-color: white; - width: 50%; - margin: 2px 2px 2px 2px; - padding-left: 10px; + background-color: white; + width: 50%; + margin: 2px 2px 2px 2px; + padding-left: 10px; } .ds-fractional-panel p { - padding: 0px !important; - margin-left: 0 !important; + padding: 0px !important; + margin-left: 0 !important; } .ds-fractional-list { - width: 230px; - min-height: 100px !important; - max-height: 100px !important; - overflow-y: scroll; + width: 230px; + min-height: 100px !important; + max-height: 100px !important; + overflow-y: scroll; } .ds-fractional-btn { - width: 150px; - height: 30px; - margin: 5px 5px 5px 10px; + width: 150px; + height: 30px; + margin: 5px 5px 5px 10px; } .ds-agmt-schedule-time { - width: 75px; - padding: 10px; - margin: 5px; + width: 75px; + padding: 10px; + margin: 5px; } .ds-agmt-schedule-checkbox { - margin: 8px !important; - padding: 5px; + margin: 8px !important; + padding: 5px; } .ds-config-checkbox { - margin-top: 10px !important; - margin-bottom: 10px !important; - margin-right: 5px !important; + margin-top: 10px !important; + margin-bottom: 10px !important; + margin-right: 5px !important; } .ds-mgr-checkbox { - margin-left: 10px !important; - margin-top: 10px !important; - margin-bottom: 10px !important; - margin-right: 5px !important; + margin-left: 10px !important; + margin-top: 10px !important; + margin-bottom: 10px !important; + margin-right: 5px !important; } .ds-server-checkbox { - margin-top: 15px !important; - margin-right: 12px !important; - padding: 5px; + margin-top: 15px !important; + margin-right: 12px !important; + padding: 5px; } .ds-send-expiring-checkbox { - margin-top: 12px !important; - margin-right: 12px !important; - padding: 5px; + margin-top: 12px !important; + margin-right: 12px !important; + padding: 5px; } .ds-nowrap-td { - overflow: hidden !important; - white-space: nowrap !important; + overflow: hidden !important; + white-space: nowrap !important; } .ds-repl-bind-group-label { - width: 85px; - margin-bottom: 25px !important; + width: 85px; + margin-bottom: 25px !important; } .ds-config-label { - margin-top: 10px; - width: 200px !important; - margin-bottom: 10px !important; + margin-top: 10px; + width: 200px !important; + margin-bottom: 10px !important; } .ds-config-label-xlrg { - margin-top: 10px; - width: 180px !important; - margin-bottom: 10px !important; + margin-top: 10px; + width: 180px !important; + margin-bottom: 10px !important; } .ds-config-label-lrg { - margin-top: 10px; - width: 160px !important; - margin-bottom: 10px !important; + margin-top: 10px; + width: 160px !important; + margin-bottom: 10px !important; } .ds-config-label-med { - margin-top: 10px; - width: 100px !important; - margin-bottom: 10px !important; + margin-top: 10px; + width: 100px !important; + margin-bottom: 10px !important; } .ds-config-label-sm { - margin-top: 10px; - margin-right: 10px; - margin-bottom: 10px !important; + margin-top: 10px; + margin-right: 10px; + margin-bottom: 10px !important; } .ds-config-sub-label { - margin-top: 10px; - width: 200px !important; - margin-bottom: 10px !important; - padding-left: 20px; + margin-top: 10px; + width: 200px !important; + margin-bottom: 10px !important; + padding-left: 20px; } .ds-label-lrg { - width: 200px; - margin-bottom: 10px !important; + width: 200px; + margin-bottom: 10px !important; } .ds-label-med { - width: 180px; - margin-bottom: 10px !important; + width: 180px; + margin-bottom: 10px !important; } .ds-monitor-label { - width: 155px; - margin-top: 10px; - margin-bottom: 10px !important; + width: 155px; + margin-top: 10px; + margin-bottom: 10px !important; } .ds-monitor-label-med { - width: 175px; - margin-top: 10px; - margin-bottom: 10px !important; + width: 175px; + margin-top: 10px; + margin-bottom: 10px !important; } .ds-label-sm { - width: 130px !important; - margin-bottom: 10px !important; + width: 130px !important; + margin-bottom: 10px !important; } .ds-label-xsm { - width: 100px !important; - margin-bottom: 10px !important; + width: 100px !important; + margin-bottom: 10px !important; } .ds-cleanallruv-label { - width: 110px !important; - margin-bottom: 10px !important; + width: 110px !important; + margin-bottom: 10px !important; } .ds-cache-label { - width: 210px !important; - margin-left: 20px !important; + width: 210px !important; + margin-left: 20px !important; } .ds-repl-config-label { - width: 210px !important; - margin-top: 20px; - margin-bottom: 20px; + width: 210px !important; + margin-top: 20px; + margin-bottom: 20px; } .ds-expire-label { - margin-top: 7px; - margin-bottom: 7px; - width: 285px !important; + margin-top: 7px; + margin-bottom: 7px; + width: 285px !important; } .ds-pw-list-label { - margin-top: 7px !important; - margin-bottom: 7px !important; - width: 200px !important; + margin-top: 7px !important; + margin-bottom: 7px !important; + width: 200px !important; } .ds-passwd-label { - width: 300px !important; + width: 300px !important; } .ds-minage-label { - padding: 10px; + padding: 10px; } .ds-history-label { - padding: 10px; - margin-left: 50px; + padding: 10px; + margin-left: 50px; } .ds-lockout-label { - padding: 10px; - margin-left: 20px; + padding: 10px; + margin-left: 20px; } .ds-server-label { - padding-top: 20px; - padding-bottom: 10px; - padding-right: 60px !important; + padding-top: 20px; + padding-bottom: 10px; + padding-right: 60px !important; } .ds-config-diskmon-label { - width: 210px !important; - padding-left: 30px; - margin-top: 10px; + width: 210px !important; + padding-left: 30px; + margin-top: 10px; } .ds-config-ndn-label { - padding-left: 40px; - padding-right: 10px; + padding-left: 40px; + padding-right: 10px; } .ds-config-indent-sm-label { - margin-top: 10px; - margin-bottom: 10px; - width: 175px; - margin-left: 40px !important; - padding-right: 10px !important; + margin-top: 10px; + margin-bottom: 10px; + width: 175px; + margin-left: 40px !important; + padding-right: 10px !important; } .ds-config-indent-med-label { - margin-left: 80px !important; - padding-right: 10px !important + margin-left: 80px !important; + padding-right: 10px !important; } .ds-config-indent-large-label { - margin-top: 7px; - margin-bottom: 7px; - margin-left: 120px !important; - padding-right: 10px !important; - width: 175px; + margin-top: 7px; + margin-bottom: 7px; + margin-left: 120px !important; + padding-right: 10px !important; + width: 175px; } .ds-expired-div { - padding-left: 30px !important; + padding-left: 30px !important; } .ds-config-diskmon-checkbox { - margin: 12px !important; - padding: 5px; - margin-left: 30px !important; + margin: 12px !important; + padding: 5px; + margin-left: 30px !important; } .ds-loglevel-list { - width: 400px; - margin-top: 10px; - margin-left: 20px; - min-height: 400px !important; + width: 400px; + margin-top: 10px; + margin-left: 20px; + min-height: 400px !important; } .ds-accordion-spacing { - margin-bottom: 10px !important; - padding-bottom: 10px !important; + margin-bottom: 10px !important; + padding-bottom: 10px !important; } - .ds-button-wide { - margin: 10px; - height: 40px; - width: 210px; +.ds-button-wide { + margin: 10px; + height: 40px; + width: 210px; } .ds-adj-btn { - padding: 0 !important; - margin-left: 10px !important; - width: 100px !important; + padding: 0 !important; + margin-left: 10px !important; + width: 100px !important; } .ds-task-panel { - background-color: white; - border: 1px groove black; - border-style: groove; - margin: 10px; - width: 235px; - line-height:0; + background-color: white; + border: 1px groove black; + border-style: groove; + margin: 10px; + width: 235px; + line-height: 0; } .ds-accordian-div { - margin-left: 20px; + margin-left: 20px; } .ds-chaining-list { - width: 350px; - height: 100px !important; + width: 350px; + height: 100px !important; } .ds-chaining-split { - width: 350px; + width: 350px; } .ds-chaining-divider { - width: 85px; + width: 85px; } .ds-chaining-form-list { - width: 355px; - height: 400px; + width: 355px; + height: 400px; } .ds-index-form-list { - width: 363px; - height: 500px; + width: 363px; + height: 500px; } .ds-oc-form-list { - width: 232px !important; - max-height: 350px !important; - min-height: 350px !important; + width: 232px !important; + max-height: 350px !important; + min-height: 350px !important; } .ds-oc-form-list:focus { - max-height: 350px !important; - min-height: 350px !important; + max-height: 350px !important; + min-height: 350px !important; } .ds-may-must-list { - width: 232px !important; - height: 150px !important; - margin: 0 !important; - padding: 0 !important; + width: 232px !important; + height: 150px !important; + margin: 0 !important; + padding: 0 !important; } - p { - line-height: 1; - white-space: normal; + line-height: 1; + white-space: normal; } textarea { - margin-top: 5px; - padding-top: 5px; - vertical-align: top; - width: 315px; - height: 80px; - resize: none; - word-wrap: break-word !important; - line-height: 1; + margin-top: 5px; + padding-top: 5px; + vertical-align: top; + width: 315px; + height: 80px; + resize: none; + word-wrap: break-word !important; + line-height: 1; } .ds-agmt-textarea { - width: 100%; + width: 100%; } .ds-logarea { - margin-top: 5px; - padding-top: 5px; - vertical-align: top; - width: 100% !important; - height: 600px !important; - max-height: 600px !important; - resize: none; - word-wrap: break-word !important; - line-height: 1; - font-family: monospace !important; - overflow-y: scroll; + margin-top: 5px; + padding-top: 5px; + vertical-align: top; + width: 100% !important; + height: 600px !important; + max-height: 600px !important; + resize: none; + word-wrap: break-word !important; + line-height: 1; + font-family: monospace !important; + overflow-y: scroll; } /* Removes dotted outline border of the text */ select { - text-shadow: 0 0 0 #000 !important; - max-height: 200px !important; - line-height: 1; - padding: 5px; + text-shadow: 0 0 0 #000 !important; + max-height: 200px !important; + line-height: 1; + padding: 5px; } option { - color: #181818; + color: #181818; } .jstree-wholerow-hovered { - background: linear-gradient(to right, #0a676f 0%, #e5e5e5 100%) !important; - opacity: .05; + background: linear-gradient(to right, #0a676f 0%, #e5e5e5 100%) !important; + opacity: 0.05; } .jstree-wholerow-clicked { - background-color: #0a676f !important; - background: linear-gradient(to right, #0a676f 0%, #e5e5e5 100%) !important; - opacity: .15 !important; - transition: opacity .25s ease-in-out !important; + background-color: #0a676f !important; + background: linear-gradient(to right, #0a676f 0%, #e5e5e5 100%) !important; + opacity: 0.15 !important; + transition: opacity 0.25s ease-in-out !important; } .ds-server-action { - padding: 0 !important; - margin-left: 10px; - display: inline-block; - align-content: right; + padding: 0 !important; + margin-left: 10px; + display: inline-block; + align-content: right; } .ds-action-btn { - margin-left: 10px; - margin-right: 0px; - /* border-radius: 5px !important; */ - padding: 0px 10px 0px 10px !important; - min-height: 30px !important; + margin-left: 10px; + margin-right: 0px; + /* border-radius: 5px !important; */ + padding: 0px 10px 0px 10px !important; + min-height: 30px !important; } .ds-nav { - padding: 0 !important + padding: 0 !important; } .ds-nav-tab a { - text-align: center; - min-width: 125px !important; + text-align: center; + min-width: 125px !important; } .ds-float-right { - float: right; + float: right; +} + +.ds-float-left { + float: left; } .ds-footer { - background-color: #e5e5e5 !important; - margin-left: -25px; - padding: 10px; - position: fixed; - bottom: 0; - width: 100%; - height: 50px; - border-top: 1px solid #999 !important; + background-color: #e5e5e5 !important; + margin-left: -25px; + padding: 10px; + position: fixed; + bottom: 0; + width: 100%; + height: 50px; + border-top: 1px solid #999 !important; +} + +.ds-no-horizontal-scrollbar { + overflow-x: hidden; } .ds-modal-footer { - background-color: #f5f5f5 !important; - padding: 10px; - bottom: 0; - width: 100%; - height: 50px; - border-top: 1px solid #999 !important; + background-color: #f5f5f5 !important; + padding: 10px; + bottom: 0; + width: 100%; + height: 50px; + border-top: 1px solid #999 !important; } .ds-nav-bar { - position: fixed; - top: 0; - width: 100%; - background-color: white; - z-index:1 + position: fixed; + top: 0; + width: 100%; + background-color: white; + z-index: 1; } .ds-nav-item a { - text-align: left; + text-align: left; } .ds-config-header { - margin-bottom: 25px; + margin-bottom: 25px; } .ds-sub-header { - margin-top: 25px; - margin-bottom: 10px; + margin-top: 25px; + margin-bottom: 10px; } .ds-accordion { - margin-top: 20px; - color: #228bc0 !important; - background-color: white; - border: 0; - position: relative; - overflow: hidden; - width:700px; - text-align:left; + margin-top: 20px; + color: #228bc0 !important; + background-color: white; + border: 0; + position: relative; + overflow: hidden; + width: 700px; + text-align: left; } .ds-accordion:after { - display: inline-block; - content: ""; - height: 1px; - background: #228bc0; - position: absolute; - width: 700px; - top: 50% !important; - margin-left: 10px; - text-align:left; + display: inline-block; + content: ""; + height: 1px; + background: #228bc0; + position: absolute; + width: 700px; + top: 50% !important; + margin-left: 10px; + text-align: left; } .ds-accordion:focus { - outline: none !important; - border: 0 !important; - -moz-outline: none !important; - -webkit-box-shadow: none !important; - box-shadow: 0 !important; + outline: none !important; + border: 0 !important; + -moz-outline: none !important; + -webkit-box-shadow: none !important; + box-shadow: 0 !important; } .ds-accordion-panel { - padding-left: 25px; - margin-top: 10px; + padding-left: 25px; + margin-top: 10px; } .ds-accordion-header { - margin-bottom: 15px; - margin-top: 0px; + margin-bottom: 15px; + margin-top: 0px; } /* wizard accordions are narrower */ .ds-wiz-accordion { - margin-top: 20px; - color: #228bc0 !important; - background-color: white; - border: 0; - position: relative; - overflow: hidden; - width:500px; - text-align:left; + margin-top: 20px; + color: #228bc0 !important; + background-color: white; + border: 0; + position: relative; + overflow: hidden; + width: 500px; + text-align: left; } .ds-wiz-accordion:after { - display: inline-block; - content: ""; - height: 1px; - background: #228bc0; - position: absolute; - width: 500px; - top: 50% !important; - margin-left: 10px; - text-align:left; + display: inline-block; + content: ""; + height: 1px; + background: #228bc0; + position: absolute; + width: 500px; + top: 50% !important; + margin-left: 10px; + text-align: left; } .ds-wiz-accordion:focus { - outline: none !important; - border: 0 !important; - -moz-outline: none !important; - -webkit-box-shadow: none !important; - box-shadow: 0 !important; + outline: none !important; + border: 0 !important; + -moz-outline: none !important; + -webkit-box-shadow: none !important; + box-shadow: 0 !important; } .ds-indent { - margin-left: 15px !important; - margin-right: 15px !important; + margin-left: 15px !important; + margin-right: 15px !important; } .ds-left-indent { - margin-left: 15px !important; + margin-left: 15px !important; +} + +.ds-right-indent { + margin-right: 15px !important; } .ds-gap { - margin-bottom: 40px !important; + margin-bottom: 40px !important; } .ds-tree-content { - margin: 33px; - margin-top: 20px; + margin: 33px; + margin-top: 20px; } .ds-select { - height: 30px; - outline: 0 !important; - padding: 0px !important; - padding-left: 5px; - padding-right: 10px; - text-align: left; + height: 30px; + outline: 0 !important; + padding: 0px !important; + padding-left: 5px; + padding-right: 10px; + text-align: left; } .ds-center { - text-align: center; + text-align: center; } .ds-left-margin { - margin-left: 10px !important; + margin-left: 10px !important; } .ds-sm-left-margin { - margin-left: 5px !important; + margin-left: 5px !important; } .ds-table-btn { - height: 30px; + height: 30px; } .ds-td { - padding-left: 10px !important; - padding-top: 8px !important; - padding-bottom: 0px ~important; - valign: middle !important; + padding-left: 10px !important; + padding-top: 8px !important; + padding-bottom: 0px ~important; + valign: middle !important; } .ds-mgr-table { - max-width: 600px; - min-width: 600px; + max-width: 600px; + min-width: 600px; } .ds-loglevel-table { - max-width: 500px; - min-width: 500px; - table-layout: fixed; - margin-top: 20px; - margin-left: 20px; + max-width: 500px; + min-width: 500px; + table-layout: fixed; + margin-top: 20px; + margin-left: 20px; } .ds-table-checkbox { - width: 35px; - text-align: center; + width: 35px; + text-align: center; } .ds-table-btn { - width: 110px; - text-align: center; + width: 110px; + text-align: center; } .ds-page-content { - margin-top: 30px !important; + margin-top: 30px !important; } .ds-checkbox-group { - margin-top: 10px !important; + margin-top: 10px !important; } .ds-alert-header { - background-color: #f2dede; + background-color: #f2dede; } .ds-sec-dropdown { - width: 80px; + width: 80px; } .ds-agmt-dropdown { - width: 120px; + width: 120px; } .ds-first { - margin-top: 10px; + margin-top: 10px; } .ds-spacing-sm { - margin-right: 10px; + margin-right: 10px; } .ds-spacing-med { - margin-right: 20px; + margin-right: 20px; } - .navbar-default { - margin-bottom: 0px; + margin-bottom: 0px; } .ds-center { - text-align: center; + text-align: center; } .ds-modal-error { - color: red; + color: red; } .ds-margin-left { - margin-left: 40px !important; + margin-left: 40px !important; } .ds-nested-modal { - margin-top: 100px; - margin-left: 100px; - min-width: 275px; + margin-top: 100px; + margin-left: 100px; + min-width: 275px; } .ds-attr-select { - min-height: 300px; - max-height: 300px; - width: 265px; - overflow: auto; + min-height: 300px; + max-height: 300px; + width: 265px; + overflow: auto; } .ds-center { - text-align: center; + text-align: center; } .ds-trailing-btn { - margin-left: 10px; - margin-top: -2px; + margin-left: 10px; + margin-top: -2px; } .ds-suffix-cfg-div { - min-width: 500px; + min-width: 500px; } .ds-loading-spinner { - position: fixed; - top: 25%; - left: 50%; - transform: translate(-25%, -50%); + position: fixed; + top: 25%; + left: 50%; + transform: translate(-25%, -50%); } .ds-loader { - font-size: 15px; + font-size: 15px; } .ds-popup { - min-width: 350px !important; + min-width: 350px !important; } .ds-disable-repl-btn { - margin-left: 15px !important; - max-height: 25px !important; + margin-left: 15px !important; + max-height: 25px !important; } .ds-repl-form { - max-width: 350px !important; + max-width: 350px !important; } .ds-input-auto { - width: 100%; - margin-right: 10px; + width: 100%; + margin-right: 10px; } +.content-view-pf-pagination > div > span { + margin-left: 8px; +} + +tbody:nth-child(even) { + background: #f1f1f1; +} diff --git a/src/cockpit/389-console/src/ds.js b/src/cockpit/389-console/src/ds.js index 46233ff..3fed897 100644 --- a/src/cockpit/389-console/src/ds.js +++ b/src/cockpit/389-console/src/ds.js @@ -142,7 +142,7 @@ function get_date_string (timestamp) { function set_no_insts () { $("#select-server").empty(); $("#select-server").append(''); - $("#select-server").prop('selectedIndex',0); + $("#select-server select").val('No instances'); server_id = ""; server_inst = ""; @@ -222,8 +222,18 @@ function get_insts() { $("#select-server").empty(); for (i = 0; i < insts.length; i++) { $("#select-server").append(''); + $("#select-server select").val(insts[i]); + // We have to dispatch an event for the React components rerender + server_select_elem = document.getElementById('select-server'); + server_select_elem.dispatchEvent(new Event('change')); } - $("#select-server").prop('selectedIndex',0); + + // Handle changing instance here + document.getElementById("select-server").addEventListener("change", function() { + server_id = $(this).val(); + server_inst = server_id.replace("slapd-", ""); + load_config(); + }); if (insts[0] === undefined) { set_no_insts(); diff --git a/src/cockpit/389-console/src/index.es6 b/src/cockpit/389-console/src/index.es6 index 4188848..057c771 100644 --- a/src/cockpit/389-console/src/index.es6 +++ b/src/cockpit/389-console/src/index.es6 @@ -2,9 +2,31 @@ import React from "react"; import ReactDOM from "react-dom"; import { Plugins } from "./plugins.jsx"; -document.addEventListener("DOMContentLoaded", function() { - ReactDOM.render( - React.createElement(Plugins, {}), - document.getElementById("plugins") +var serverIdElem; + +function renderReactDOM() { + serverIdElem = document.getElementById("select-server"); + const element = ( + ); + ReactDOM.render(element, document.getElementById("plugins")); +} + +document.addEventListener("DOMContentLoaded", function() { + var init_config = setInterval(function() { + serverIdElem = document.getElementById("select-server"); + if (serverIdElem != null && serverIdElem.value.startsWith("slapd-")) { + document + .getElementById("select-server") + .addEventListener("change", renderReactDOM); + document + .getElementById("start-server-btn") + .addEventListener("click", renderReactDOM); + document + .getElementById("restart-server-btn") + .addEventListener("click", renderReactDOM); + renderReactDOM(); + clearInterval(init_config); + } + }, 250); }); diff --git a/src/cockpit/389-console/src/lib/customTableToolbar.jsx b/src/cockpit/389-console/src/lib/customTableToolbar.jsx new file mode 100644 index 0000000..a15f018 --- /dev/null +++ b/src/cockpit/389-console/src/lib/customTableToolbar.jsx @@ -0,0 +1,61 @@ +import React from "react"; +import PropTypes from "prop-types"; +import classNames from "classnames"; +import { noop, Spinner, FormControl } from "patternfly-react"; + +class CustomTableToolbar extends React.Component { + render() { + const { + className, + placeholder, + modelToSearch, + searchFilterValue, + handleValueChange, + loading + } = this.props; + + const classes = classNames("form-group toolbar-pf-find", className); + + return ( +
    + +
    + +
    +
    + ); + } +} + +CustomTableToolbar.propTypes = { + className: PropTypes.string, + placeholder: PropTypes.string, + modelToSearch: PropTypes.string, + searchFilterValue: PropTypes.string, + handleValueChange: PropTypes.func, + loading: PropTypes.bool +}; + +CustomTableToolbar.defaultProps = { + className: "", + placeholder: "", + modelToSearch: "", + searchFilterValue: "", + handleValueChange: noop, + loading: false +}; + +export default CustomTableToolbar; diff --git a/src/cockpit/389-console/src/lib/notifications.jsx b/src/cockpit/389-console/src/lib/notifications.jsx new file mode 100644 index 0000000..06ad141 --- /dev/null +++ b/src/cockpit/389-console/src/lib/notifications.jsx @@ -0,0 +1,44 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { + TimedToastNotification, + ToastNotificationList +} from "patternfly-react"; + +class NotificationController extends React.Component { + render() { + const { notifications, removeNotificationAction } = this.props; + + return ( + + {notifications.map(notification => ( + removeNotificationAction(notification)} + timerdelay={notification.timerdelay} // By default - 8000 + > + + {notification.header && ( + {notification.header} + )} + {notification.message} + + + ))} + + ); + } +} + +NotificationController.propTypes = { + removeNotificationAction: PropTypes.func, + notifications: PropTypes.array +}; + +NotificationController.defaultProps = { + notifications: [] +}; + +export default NotificationController; diff --git a/src/cockpit/389-console/src/lib/plugins/pluginModal.jsx b/src/cockpit/389-console/src/lib/plugins/pluginModal.jsx new file mode 100644 index 0000000..aa8e090 --- /dev/null +++ b/src/cockpit/389-console/src/lib/plugins/pluginModal.jsx @@ -0,0 +1,220 @@ +import cockpit from "cockpit"; +import React from "react"; +import { + Modal, + Icon, + Button, + Switch, + noop, + Form, + FormControl, + FormGroup, + ControlLabel, + Col +} from "patternfly-react"; +import PropTypes from "prop-types"; +import { log_cmd } from "../tools.jsx"; +import "../../css/ds.css"; + +var cmd; + +class PluginEditModal extends React.Component { + constructor(props) { + super(props); + this.savePlugin = this.savePlugin.bind(this); + } + + savePlugin() { + const { + currentPluginName, + currentPluginType, + currentPluginEnabled, + currentPluginPath, + currentPluginInitfunc, + currentPluginId, + currentPluginVendor, + currentPluginVersion, + currentPluginDescription, + pluginListHandler, + closeHandler, + addNotification + } = this.props; + cmd = [ + "dsconf", + "-j", + "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket", + "plugin", + "edit", + currentPluginName, + "--enabled", + currentPluginEnabled ? "on" : "off", + "--type", + currentPluginType, + "--path", + currentPluginPath, + "--initfunc", + currentPluginInitfunc, + "--id", + currentPluginId, + "--vendor", + currentPluginVendor, + "--version", + currentPluginVersion, + "--description", + currentPluginDescription + ]; + log_cmd("savePlugin", "Edit the plugin from the modal form", cmd); + cockpit + .spawn(cmd, { superuser: true, err: "message" }) + .done(content => { + console.info("savePlugin", "Result", content); + addNotification( + "success", + `Plugin ${currentPluginName} was successfully modified` + ); + pluginListHandler(); + closeHandler(); + }) + .fail(err => { + addNotification( + "error", + `Error during plugin ${currentPluginName} modification - ${err}` + ); + closeHandler(); + }); + } + + render() { + const modalFields = { + currentPluginType: this.props.currentPluginType, + currentPluginPath: this.props.currentPluginPath, + currentPluginInitfunc: this.props.currentPluginInitfunc, + currentPluginId: this.props.currentPluginId, + currentPluginVendor: this.props.currentPluginVendor, + currentPluginVersion: this.props.currentPluginVersion, + currentPluginDescription: this.props.currentPluginDescription + }; + const { + showModal, + closeHandler, + currentPluginName, + currentPluginEnabled, + handleChange, + handleSwitchChange + } = this.props; + return ( + +
    + + + + Edit Plugin - {currentPluginName} + + + +
    + + + Plugin Status + + + + handleSwitchChange( + currentPluginEnabled + ) + } + animate={false} + /> + + + {Object.entries(modalFields).map(([id, value]) => ( + + + Plugin {id.replace("currentPlugin", "")} + + + + + + ))} +
    +
    + + + + +
    +
    + ); + } +} + +PluginEditModal.propTypes = { + handleChange: PropTypes.func, + handleSwitchChange: PropTypes.func, + currentPluginName: PropTypes.string, + currentPluginType: PropTypes.string, + currentPluginEnabled: PropTypes.bool, + currentPluginPath: PropTypes.string, + currentPluginInitfunc: PropTypes.string, + currentPluginId: PropTypes.string, + currentPluginVendor: PropTypes.string, + currentPluginVersion: PropTypes.string, + currentPluginDescription: PropTypes.string, + serverId: PropTypes.string, + closeHandler: PropTypes.func, + pluginListHandler: PropTypes.func, + showModal: PropTypes.bool +}; + +PluginEditModal.defaultProps = { + handleChange: noop, + handleSwitchChange: noop, + currentPluginName: "", + currentPluginType: "", + currentPluginEnabled: false, + currentPluginPath: "", + currentPluginInitfunc: "", + currentPluginId: "", + currentPluginVendor: "", + currentPluginVersion: "", + currentPluginDescription: "", + serverId: "", + closeHandler: noop, + pluginListHandler: noop, + showModal: false +}; + +export default PluginEditModal; diff --git a/src/cockpit/389-console/src/lib/plugins/pluginTable.jsx b/src/cockpit/389-console/src/lib/plugins/pluginTable.jsx new file mode 100644 index 0000000..0b67eeb --- /dev/null +++ b/src/cockpit/389-console/src/lib/plugins/pluginTable.jsx @@ -0,0 +1,376 @@ +import React from "react"; +import { + PaginationRow, + paginate, + Table, + noop, + actionHeaderCellFormatter, + customHeaderFormattersDefinition, + defaultSortingOrder, + sortableHeaderCellFormatter, + tableCellFormatter, + TABLE_SORT_DIRECTION, + PAGINATION_VIEW +} from "patternfly-react"; +import PropTypes from "prop-types"; +import { orderBy } from "lodash"; +import * as sort from "sortabular"; +import * as resolve from "table-resolver"; +import { compose } from "recompose"; +import { searchFilter } from "../tools.jsx"; +import CustomTableToolbar from "../customTableToolbar.jsx"; +import "../../css/ds.css"; + +class PluginTable extends React.Component { + constructor(props) { + super(props); + + // Point the transform to your sortingColumns. React state can work for this purpose + // but you can use a state manager as well. + const getSortingColumns = () => this.state.sortingColumns || {}; + + const sortableTransform = sort.sort({ + getSortingColumns, + onSort: selectedColumn => { + this.setState({ + sortingColumns: sort.byColumn({ + sortingColumns: this.state.sortingColumns, + sortingOrder: defaultSortingOrder, + selectedColumn + }) + }); + }, + // Use property or index dependening on the sortingColumns structure specified + strategy: sort.strategies.byProperty + }); + + const sortingFormatter = sort.header({ + sortableTransform, + getSortingColumns, + strategy: sort.strategies.byProperty + }); + + // Enables our custom header formatters extensions to reactabular + this.customHeaderFormatters = customHeaderFormattersDefinition; + + this.handleSearchValueChange = this.handleSearchValueChange.bind(this); + this.hideDropdown = this.hideDropdown.bind(this); + this.toggleDropdownShown = this.toggleDropdownShown.bind(this); + this.totalPages = this.totalPages.bind(this); + this.onPageInput = this.onPageInput.bind(this); + this.onSubmit = this.onSubmit.bind(this); + this.setPage = this.setPage.bind(this); + this.onPerPageSelect = this.onPerPageSelect.bind(this); + this.onFirstPage = this.onFirstPage.bind(this); + this.onPreviousPage = this.onPreviousPage.bind(this); + this.onNextPage = this.onNextPage.bind(this); + this.onLastPage = this.onLastPage.bind(this); + this.currentRows = this.currentRows.bind(this); + this.filteredSearchedRows = this.filteredSearchedRows.bind(this); + + this.state = { + dropdownShown: false, + searchFilterValue: "", + fieldsToSearch: ["cn", "nsslapd-pluginType"], + // Sort the first column in an ascending way by default. + sortingColumns: { + name: { + direction: TABLE_SORT_DIRECTION.ASC, + position: 0 + } + }, + columns: [ + { + property: "cn", + header: { + label: "Plugin Name", + props: { + index: 0, + rowSpan: 1, + colSpan: 1, + sort: true + }, + transforms: [sortableTransform], + formatters: [sortingFormatter], + customFormatters: [sortableHeaderCellFormatter] + }, + cell: { + props: { + index: 0 + }, + formatters: [tableCellFormatter] + } + }, + { + property: "nsslapd-pluginType", + header: { + label: "Plugin Type", + props: { + index: 1, + rowSpan: 1, + colSpan: 1, + sort: true + }, + transforms: [sortableTransform], + formatters: [sortingFormatter], + customFormatters: [sortableHeaderCellFormatter] + }, + cell: { + props: { + index: 1 + }, + formatters: [tableCellFormatter] + } + }, + { + property: "nsslapd-pluginEnabled", + header: { + label: "Enabled", + props: { + index: 2, + rowSpan: 1, + colSpan: 1, + sort: true + }, + transforms: [sortableTransform], + formatters: [sortingFormatter], + customFormatters: [sortableHeaderCellFormatter] + }, + cell: { + props: { + index: 2 + }, + formatters: [tableCellFormatter] + } + }, + { + property: "actions", + header: { + label: "Actions", + props: { + index: 3, + rowSpan: 1, + colSpan: 1 + }, + formatters: [actionHeaderCellFormatter] + }, + cell: { + props: { + index: 3 + }, + formatters: [ + (value, { rowData }) => { + return [ + + { + this.props.loadModalHandler( + rowData + ); + }} + > + Edit Plugin + + + ]; + } + ] + } + } + ], + + // pagination default states + pagination: { + page: 1, + perPage: 12, + perPageOptions: [6, 12, 24] + }, + + // page input value + pageChangeValue: 1 + }; + } + + handleSearchValueChange(event) { + this.setState({ searchFilterValue: event.target.value }); + } + + hideDropdown() { + const { onExit } = this.props; + this.setState({ dropdownShown: false }); + onExit(); + } + + toggleDropdownShown() { + this.setState(prevState => ({ + dropdownShown: !prevState.dropdownShown + })); + } + + totalPages() { + const { rows } = this.props; + const { perPage } = this.state.pagination; + return Math.ceil(rows.length / perPage); + } + + onPageInput(e) { + this.setState({ pageChangeValue: e.target.value }); + } + + onSubmit() { + this.setPage(this.state.pageChangeValue); + } + + setPage(value) { + const page = Number(value); + if ( + !Number.isNaN(value) && + value !== "" && + page > 0 && + page <= this.totalPages() + ) { + let newPaginationState = Object.assign({}, this.state.pagination); + newPaginationState.page = page; + this.setState({ + pagination: newPaginationState, + pageChangeValue: page + }); + } + } + + onPerPageSelect(eventKey, e) { + let newPaginationState = Object.assign({}, this.state.pagination); + newPaginationState.perPage = eventKey; + newPaginationState.page = 1; + this.setState({ pagination: newPaginationState }); + } + + onFirstPage() { + this.setPage(1); + } + + onPreviousPage() { + if (this.state.pagination.page > 1) { + this.setPage(this.state.pagination.page - 1); + } + } + + onNextPage() { + const { page } = this.state.pagination; + if (page < this.totalPages()) { + this.setPage(this.state.pagination.page + 1); + } + } + + onLastPage() { + const { page } = this.state.pagination; + const totalPages = this.totalPages(); + if (page < totalPages) { + this.setPage(totalPages); + } + } + + currentRows(filteredRows) { + const { sortingColumns, columns, pagination } = this.state; + return compose( + paginate(pagination), + sort.sorter({ + columns: columns, + sortingColumns, + sort: orderBy, + strategy: sort.strategies.byProperty + }) + )(filteredRows); + } + + filteredSearchedRows() { + const { rows } = this.props; + const { fieldsToSearch, searchFilterValue } = this.state; + if (searchFilterValue) { + return searchFilter(searchFilterValue, fieldsToSearch, rows); + } + return rows; + } + + render() { + const { + columns, + pagination, + sortingColumns, + pageChangeValue + } = this.state; + + const filteredRows = this.filteredSearchedRows(); + const sortedPaginatedRows = this.currentRows(filteredRows); + + return ( +
    + + { + return this.customHeaderFormatters({ + cellProps, + columns, + sortingColumns, + rows: sortedPaginatedRows.rows + }); + } + } + }} + > + + + + +
    + ); + } +} + +PluginTable.propTypes = { + rows: PropTypes.array, + loadModalHandler: PropTypes.func, + loading: PropTypes.bool +}; + +PluginTable.defaultProps = { + rows: [], + loadModalHandler: noop, + loading: false +}; + +export default PluginTable; diff --git a/src/cockpit/389-console/src/lib/tools.jsx b/src/cockpit/389-console/src/lib/tools.jsx new file mode 100644 index 0000000..442d032 --- /dev/null +++ b/src/cockpit/389-console/src/lib/tools.jsx @@ -0,0 +1,58 @@ +export function searchFilter(searchFilterValue, columnsToSearch, rows) { + if (searchFilterValue && rows && rows.length) { + const filteredRows = []; + rows.forEach(row => { + var rowToSearch = []; + if (columnsToSearch && columnsToSearch.length) { + columnsToSearch.forEach(column => + rowToSearch.push(row[column]) + ); + } else { + rowToSearch = row; + } + const match = Object.values(rowToSearch).some(value => + value + .join() + .toLowerCase() + .includes(searchFilterValue.toLowerCase()) + ); + if (match) { + filteredRows.push(row); + } + }); + return filteredRows; + } + return rows; +} + +export function log_cmd(js_func, desc, cmd_array) { + if (console) { + var pw_args = ["--passwd", "--bind-pw"]; + var cmd_list = []; + var converted_pw = false; + + for (var idx in cmd_array) { + var cmd = cmd_array[idx]; + converted_pw = false; + for (var arg_idx in pw_args) { + if (cmd.startsWith(pw_args[arg_idx])) { + // We are setting a password, if it has a value we need to hide it + var arg_len = cmd.indexOf("="); + var arg = cmd.substring(0, arg_len); + if (cmd.length != arg_len + 1) { + // We are setting a password value... + cmd_list.push(arg + "=**********"); + converted_pw = true; + } + break; + } + } + if (!converted_pw) { + cmd_list.push(cmd); + } + } + console.log( + "CMD: " + js_func + ": " + desc + " ==> " + cmd_list.join(" ") + ); + } +} diff --git a/src/cockpit/389-console/src/plugins.jsx b/src/cockpit/389-console/src/plugins.jsx index c0a43ce..ffb67a5 100644 --- a/src/cockpit/389-console/src/plugins.jsx +++ b/src/cockpit/389-console/src/plugins.jsx @@ -1,35 +1,198 @@ import cockpit from "cockpit"; import React from "react"; -import "./plugins.scss"; +import PropTypes from "prop-types"; +import { log_cmd } from "./lib/tools.jsx"; +import PluginEditModal from "./lib/plugins/pluginModal.jsx"; +import PluginTable from "./lib/plugins/pluginTable.jsx"; +import NotificationController from "./lib/notifications.jsx"; +import "./css/ds.css"; -const _ = cockpit.gettext; +var cmd; export class Plugins extends React.Component { + componentWillMount() { + this.pluginList(); + } + + componentDidUpdate(prevProps) { + if (this.props.serverId !== prevProps.serverId) { + this.pluginList(); + } + } + constructor() { super(); + + this.handleFieldChange = this.handleFieldChange.bind(this); + this.handleSwitchChange = this.handleSwitchChange.bind(this); + this.openPluginModal = this.openPluginModal.bind(this); + this.closePluginModal = this.closePluginModal.bind(this); + this.pluginList = this.pluginList.bind(this); + this.removeNotification = this.removeNotification.bind(this); + this.addNotification = this.addNotification.bind(this); + this.state = { - hostname: _("Unknown") + notifications: [], + loading: false, + showPluginModal: false, + // Sort the first column in an ascending way by default. + // rows and row selection state + rows: [], + + // Plugin attributes + currentPluginName: "", + currentPluginType: "", + currentPluginEnabled: false, + currentPluginPath: "", + currentPluginInitfunc: "", + currentPluginId: "", + currentPluginVendor: "", + currentPluginVersion: "", + currentPluginDescription: "" }; + } + + addNotification(type, message, timerdelay, persistent) { + this.setState(prevState => ({ + notifications: [ + ...prevState.notifications, + { + key: prevState.notifications.length + 1, + type: type, + persistent: persistent, + timerdelay: timerdelay, + message: message + } + ] + })); + } + + removeNotification(notificationToRemove) { + this.setState({ + notifications: this.state.notifications.filter( + notification => notificationToRemove.key !== notification.key + ) + }); + } + + handleFieldChange(e) { + this.setState({ + [e.target.id]: e.target.value + }); + } + handleSwitchChange(value) { + this.setState({ + currentPluginEnabled: !value + }); + } + + closePluginModal() { + this.setState({ + showPluginModal: false + }); + } + + openPluginModal(rowData) { + var pluginEnabled; + if (rowData["nsslapd-pluginEnabled"][0] === "on") { + pluginEnabled = true; + } else if (rowData["nsslapd-pluginEnabled"][0] === "off") { + pluginEnabled = false; + } else { + console.error( + "openPluginModal failed", + "wrong nsslapd-pluginenabled attribute value", + rowData["nsslapd-pluginEnabled"][0] + ); + } + this.setState({ + currentPluginName: rowData.cn[0], + currentPluginType: rowData["nsslapd-pluginType"][0], + currentPluginEnabled: pluginEnabled, + currentPluginPath: rowData["nsslapd-pluginPath"][0], + currentPluginInitfunc: rowData["nsslapd-pluginInitfunc"][0], + currentPluginId: rowData["nsslapd-pluginId"][0], + currentPluginVendor: rowData["nsslapd-pluginVendor"][0], + currentPluginVersion: rowData["nsslapd-pluginVersion"][0], + currentPluginDescription: rowData["nsslapd-pluginDescription"][0], + showPluginModal: true + }); + } + + pluginList() { + this.setState({ + loading: true + }); + cmd = [ + "dsconf", + "-j", + "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket", + "plugin", + "list" + ]; + log_cmd("pluginList", "Get plugins for table rows", cmd); cockpit - .file("/etc/hostname") - .read() + .spawn(cmd, { superuser: true, err: "message" }) .done(content => { - this.setState({ hostname: content.trim() }); + var myObject = JSON.parse(content); + this.setState({ + rows: myObject.items, + loading: false + }); + }) + .fail(err => { + if (err != 0) { + console.error("pluginList failed", err); + } + this.setState({ + loading: false + }); }); } render() { return (
    +

    Plugins

    -

    - {cockpit.format( - _("Setting up plugins on server $0"), - this.state.hostname - )} -

    + +
    ); } } + +Plugins.propTypes = { + serverId: PropTypes.string +}; + +Plugins.defaultProps = { + serverId: "" +}; diff --git a/src/cockpit/389-console/src/plugins.scss b/src/cockpit/389-console/src/plugins.scss deleted file mode 100644 index 87b46f4..0000000 --- a/src/cockpit/389-console/src/plugins.scss +++ /dev/null @@ -1,3 +0,0 @@ -p { - font-weight: bold; -} diff --git a/src/cockpit/389-console/src/servers.js b/src/cockpit/389-console/src/servers.js index 1b72453..8dbd1bf 100644 --- a/src/cockpit/389-console/src/servers.js +++ b/src/cockpit/389-console/src/servers.js @@ -417,6 +417,57 @@ $(document).ready( function() { monitor_page_loaded == 1) { get_insts(); + + /* + * Stop, Start, and Restart server + */ + document.getElementById("start-server-btn").addEventListener("click", function() { + $("#ds-start-inst").html(" Starting instance " + server_id + "..."); + $("#start-instance-form").modal('toggle'); + var cmd = [DSCTL, server_inst, 'start']; + log_cmd('#start-server-btn (click)', 'Start server instance', cmd); + cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).done(function(data) { + $("#start-instance-form").modal('toggle'); + load_config(); + popup_success("Started instance \"" + server_id + "\""); + }).fail(function(data) { + $("#start-instance-form").modal('toggle'); + popup_err("Failed to start instance \"" + server_id, data.message); + }); + }); + + document.getElementById("stop-server-btn").addEventListener("click", function() { + $("#ds-stop-inst").html(" Stopping instance " + server_id + "..."); + $("#stop-instance-form").modal('toggle'); + var cmd = [DSCTL, server_inst, 'stop']; + log_cmd('#stop-server-btn (click)', 'Stop server instance', cmd); + cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).done(function(data) { + $("#stop-instance-form").modal('toggle'); + popup_success("Stopped instance \"" + server_id + "\""); + check_inst_alive(); + }).fail(function(data) { + $("#stop-instance-form").modal('toggle'); + popup_err("Error", "Failed to stop instance \"" + server_id+ "\"", data.message); + check_inst_alive(); + }); + }); + + + document.getElementById("restart-server-btn").addEventListener("click", function() { + $("#ds-restart-inst").html(" Retarting instance " + server_id + "..."); + $("#restart-instance-form").modal('toggle'); + var cmd = [DSCTL, server_inst, 'restart']; + log_cmd('#restart-server-btn (click)', 'Restart server instance', cmd); + cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).done(function(data) { + $("#restart-instance-form").modal('toggle'); + load_config(); + popup_success("Restarted instance \"" + server_id + "\""); + }).fail(function(data) { + $("#restart-instance-form").modal('toggle'); + popup_err("Failed to restart instance \"" + server_id + "\"", data.message); + }); + }); + clearInterval(init_config); } }, 250); @@ -484,13 +535,6 @@ $(document).ready( function() { } ] }); - // Handle changing instance here - $('#select-server').on("change", function() { - server_id = $(this).val(); - server_inst = server_id.replace("slapd-", ""); - load_config(); - }); - $('.disk-monitoring').hide(); $(".all-pages").hide(); $("#server-content").show(); @@ -1193,55 +1237,6 @@ $(document).ready( function() { } }); - /* - * Stop, Start, and Restart server - */ - $("#start-server-btn").on("click", function () { - $("#ds-start-inst").html(" Starting instance " + server_id + "..."); - $("#start-instance-form").modal('toggle'); - var cmd = [DSCTL, server_inst, 'start']; - log_cmd('#start-server-btn (click)', 'Start server instance', cmd); - cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).done(function(data) { - $("#start-instance-form").modal('toggle'); - load_config(); - popup_success("Started instance \"" + server_id + "\""); - }).fail(function(data) { - $("#start-instance-form").modal('toggle'); - popup_err("Failed to start instance \"" + server_id, data.message); - }); - }); - - $("#stop-server-btn").on("click", function () { - $("#ds-stop-inst").html(" Stopping instance " + server_id + "..."); - $("#stop-instance-form").modal('toggle'); - var cmd = [DSCTL, server_inst, 'stop']; - log_cmd('#stop-server-btn (click)', 'Stop server instance', cmd); - cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).done(function(data) { - $("#stop-instance-form").modal('toggle'); - popup_success("Stopped instance \"" + server_id + "\""); - check_inst_alive(); - }).fail(function(data) { - $("#stop-instance-form").modal('toggle'); - popup_err("Error", "Failed to stop instance \"" + server_id+ "\"", data.message); - check_inst_alive(); - }); - }); - - $("#restart-server-btn").on("click", function () { - $("#ds-restart-inst").html(" Retarting instance " + server_id + "..."); - $("#restart-instance-form").modal('toggle'); - var cmd = [DSCTL, server_inst, 'restart']; - log_cmd('#restart-server-btn (click)', 'Restart server instance', cmd); - cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).done(function(data) { - $("#restart-instance-form").modal('toggle'); - load_config(); - popup_success("Restarted instance \"" + server_id + "\""); - }).fail(function(data) { - $("#restart-instance-form").modal('toggle'); - popup_err("Failed to restart instance \"" + server_id + "\"", data.message); - }); - }); - /* Backup server */ $("#ds-backup-btn").on('click', function () { var backup_name = $("#backup-name").val(); diff --git a/src/lib389/lib389/cli_conf/plugin.py b/src/lib389/lib389/cli_conf/plugin.py index 4d6a623..8f59433 100644 --- a/src/lib389/lib389/cli_conf/plugin.py +++ b/src/lib389/lib389/cli_conf/plugin.py @@ -6,7 +6,9 @@ # See LICENSE for details. # --- END COPYRIGHT BLOCK --- +import json from lib389.plugins import Plugin, Plugins +from lib389.utils import ensure_dict_str from lib389.cli_base import ( _generic_list, _generic_get, @@ -25,7 +27,26 @@ RDN = 'cn' def plugin_list(inst, basedn, log, args): - _generic_list(inst, basedn, log.getChild('plugin_list'), MANY, args) + plugin_log = log.getChild('plugin_list') + mc = MANY(inst, basedn) + plugins = mc.list() + if len(plugins) == 0: + if args and args.json: + print(json.dumps({"type": "list", "items": []})) + else: + plugin_log.info("No objects to display") + elif len(plugins) > 0: + # We might sort this in the future + if args and args.json: + json_result = {"type": "list", "items": []} + for plugin in plugins: + plugin_data = ensure_dict_str(dict(plugin.get_all_attrs())) + if args and args.json: + json_result['items'].append(plugin_data) + else: + plugin_log.info(plugin_data) + if args and args.json: + print(json.dumps(json_result)) def plugin_get(inst, basedn, log, args): @@ -38,6 +59,44 @@ def plugin_get_dn(inst, basedn, log, args): _generic_get_dn(inst, basedn, log.getChild('plugin_get_dn'), MANY, dn, args) +def vaidate_args(plugin, attr_arg_list): + """Check if the attribute needs to be changed + Return mods for the replace_many() method + """ + + mods = [] + for attr_name, arg in attr_arg_list.items(): + if arg is not None and plugin.get_attr_val_utf8_l(attr_name) != arg.lower(): + mods.append((attr_name, arg)) + return mods + + +def plugin_edit(inst, basedn, log, args): + log = log.getChild('plugin_edit') + rdn = _get_arg(args.selector, msg="Enter %s to retrieve" % RDN) + plugins = Plugins(inst) + plugin = plugins.get(rdn) + + if args.enabled is not None and args.enabled.lower() not in ["on", "off"]: + raise ValueError("Plugin enabled argument should be 'on' or 'off'") + + plugin_args = {'nsslapd-pluginInitfunc': args.initfunc, + 'nsslapd-pluginEnabled': args.enabled, + 'nsslapd-pluginPath': args.path, + 'nsslapd-pluginType': args.type, + 'nsslapd-pluginId': args.id, + 'nsslapd-pluginVersion': args.version, + 'nsslapd-pluginVendor': args.vendor, + 'nsslapd-pluginDescription': args.description} + mods = vaidate_args(plugin, plugin_args) + + if len(mods) > 0: + plugin.replace_many(*mods) + log.info("Successfully changed the plugin %s", rdn) + else: + raise ValueError("Nothing to change") + + # Plugin enable def plugin_enable(inst, basedn, log, args): dn = _get_arg(args.dn, msg="Enter plugin dn to enable") @@ -121,6 +180,19 @@ def create_parser(subparsers): get_dn_parser.set_defaults(func=plugin_get_dn) get_dn_parser.add_argument('dn', nargs='?', help='The plugin dn to get') + edit_parser = subcommands.add_parser('edit', help='get') + edit_parser.set_defaults(func=plugin_edit) + edit_parser.add_argument('selector', nargs='?', help='The plugin to edit') + edit_parser.add_argument('--type', help='The type of plugin.') + edit_parser.add_argument('--enabled', + help='Identifies whether or not the plugin is enabled. It should have "on" or "off" values.') + edit_parser.add_argument('--path', help='The plugin library name (without the library suffix).') + edit_parser.add_argument('--initfunc', help='An initialization function of the plugin.') + edit_parser.add_argument('--id', help='The plugin ID.') + edit_parser.add_argument('--vendor', help='The vendor of plugin.') + edit_parser.add_argument('--version', help='The version of plugin.') + edit_parser.add_argument('--description', help='The description of the plugin.') + enable_parser = subcommands.add_parser('enable', help='enable a plugin in the server') enable_parser.set_defaults(func=plugin_enable) enable_parser.add_argument('dn', nargs='?', help='The dn to enable') @@ -128,5 +200,3 @@ def create_parser(subparsers): disable_parser = subcommands.add_parser('disable', help='disable the plugin configuration') disable_parser.set_defaults(func=plugin_disable) disable_parser.add_argument('dn', nargs='?', help='The dn to disable') - -