This is an automated email from the git hooks/post-receive script.
spichugi pushed a commit to branch 389-ds-base-1.4.2
in repository 389-ds-base.
commit 45ce51ca1c5711267842e30f8752d005fe9e3a72
Author: Simon Pichugin <spichugi(a)redhat.com>
AuthorDate: Mon Dec 23 00:28:32 2019 +0100
Issue 50836 - Port Schema UI tab to React
Description: Port the schema UI tab to React and preserve all
existing features.
https://pagure.io/389-ds-base/issue/50836
Reviewed by: mreynolds (Thank you!!)
---
src/cockpit/389-console/src/css/ds.css | 5 +
src/cockpit/389-console/src/ds.js | 10 +-
src/cockpit/389-console/src/index.es6 | 7 +
src/cockpit/389-console/src/index.html | 10 +-
.../389-console/src/lib/schema/schemaModals.jsx | 660 +++++++++++++
.../389-console/src/lib/schema/schemaTables.jsx | 558 +++++++++++
src/cockpit/389-console/src/lib/tools.jsx | 54 +-
src/cockpit/389-console/src/schema.html | 377 -------
src/cockpit/389-console/src/schema.js | 925 -----------------
src/cockpit/389-console/src/schema.jsx | 1042 ++++++++++++++++++++
src/cockpit/389-console/webpack.config.js | 2 -
src/lib389/lib389/schema.py | 10 +-
12 files changed, 2323 insertions(+), 1337 deletions(-)
diff --git a/src/cockpit/389-console/src/css/ds.css
b/src/cockpit/389-console/src/css/ds.css
index 662d8de..a71f615 100644
--- a/src/cockpit/389-console/src/css/ds.css
+++ b/src/cockpit/389-console/src/css/ds.css
@@ -1021,6 +1021,11 @@ option {
width: 120px;
}
+.ds-schema-dropdown {
+ border-color: #06c !important;
+ color: #06c !important;
+}
+
.treeview .list-group-item {
/* remove focus border */
outline: none;
diff --git a/src/cockpit/389-console/src/ds.js b/src/cockpit/389-console/src/ds.js
index 7b4db77..0bddcef 100644
--- a/src/cockpit/389-console/src/ds.js
+++ b/src/cockpit/389-console/src/ds.js
@@ -12,7 +12,7 @@ var security_page_loaded = 1;
var db_page_loaded = 1;
var repl_page_loaded = 1;
var plugin_page_loaded = 1;
-var schema_page_loaded = 0;
+var schema_page_loaded = 1;
var monitor_page_loaded = 1;
var config_loaded = 0;
@@ -412,10 +412,6 @@ function load_config (refresh){
get_and_set_localpwp();
update_progress();
- // Schema page
- get_and_set_schema_tables();
- update_progress();
-
// Initialize the tabs
$(".ds-tab-list").css( 'color', '#777');
$("#server-tab").css( 'color', '#228bc0');
@@ -472,6 +468,10 @@ $(window.document).ready(function() {
$(".all-pages").hide();
$("#security-content").show();
});
+ $("#schema-tab").on("click", function() {
+ $(".all-pages").hide();
+ $("#schema-content").show();
+ });
$("#replication-tab").on("click", function() {
$(".all-pages").hide();
$("#replication-content").show();
diff --git a/src/cockpit/389-console/src/index.es6
b/src/cockpit/389-console/src/index.es6
index 6797dd5..6f2673f 100644
--- a/src/cockpit/389-console/src/index.es6
+++ b/src/cockpit/389-console/src/index.es6
@@ -3,6 +3,7 @@ import ReactDOM from "react-dom";
import { Plugins } from "./plugins.jsx";
import { Database } from "./database.jsx";
import { Monitor } from "./monitor.jsx";
+import { Schema } from "./schema.jsx";
import { Security } from "./security.jsx";
import { Replication } from "./replication.jsx";
@@ -49,6 +50,12 @@ function renderReactDOM(clear) {
<Security serverId={serverIdElem} key={tabKey} />,
document.getElementById("security")
);
+
+ // Schema tab
+ ReactDOM.render(
+ <Schema serverId={serverIdElem} key={tabKey} />,
+ document.getElementById("schema")
+ );
}
// We have to create the wrappers because this is no simple way
diff --git a/src/cockpit/389-console/src/index.html
b/src/cockpit/389-console/src/index.html
index 6a0479c..c1b9952 100644
--- a/src/cockpit/389-console/src/index.html
+++ b/src/cockpit/389-console/src/index.html
@@ -18,7 +18,6 @@
<script src="static/c3.min.js"></script>
<script src="static/d3.min.js"></script>
<script src="ds.js"></script>
- <script src="schema.js"></script>
<script src="servers.js"></script>
<link href="static/bootstrap.min.css" rel="stylesheet">
<link href="static/jquery.dataTables.min.css" type="text/css"
rel="stylesheet">
@@ -109,15 +108,9 @@
<!-- Schema navtab -->
<li class="dropdown ds-nav-tab">
- <a href="#0" class="ds-tab-list"
data-toggle="dropdown" id="schema-tab">
+ <a href="#0" class="ds-tab-list ds-tab-standalone"
id="schema-tab">
Schema
- <b class="caret"></b>
</a>
- <ul class="dropdown-menu ds-nav-item">
- <li><a href="#0"class="ds-nav-choice"
id="objectclass-btn"
parent-id="schema-tab">Objectclasses</a></li>
- <li><a href="#0"class="ds-nav-choice"
id="attribute-btn"
parent-id="schema-tab">Attributes</a></li>
- <li><a href="#0" class="ds-nav-choice"
id="schema-mr-btn" parent-id="schema-tab">Matching
Rules</a></li>
- </ul>
</li>
<!-- Plugins navtab -->
@@ -514,6 +507,7 @@
</div>
<div id="schema-content" class="all-pages" hidden>
+ <div id="schema"></div>
</div>
<div id="plugin-content" class="all-pages" hidden>
diff --git a/src/cockpit/389-console/src/lib/schema/schemaModals.jsx
b/src/cockpit/389-console/src/lib/schema/schemaModals.jsx
new file mode 100644
index 0000000..6b6049a
--- /dev/null
+++ b/src/cockpit/389-console/src/lib/schema/schemaModals.jsx
@@ -0,0 +1,660 @@
+import React from "react";
+import {
+ Row,
+ Spinner,
+ Modal,
+ Icon,
+ Button,
+ Checkbox,
+ noop,
+ Form,
+ FormControl,
+ FormGroup,
+ ControlLabel,
+ Col
+} from "patternfly-react";
+import { Typeahead } from "react-bootstrap-typeahead";
+import PropTypes from "prop-types";
+import "../../css/ds.css";
+
+class ObjectClassModal extends React.Component {
+ render() {
+ const {
+ newOcEntry,
+ ocModalViewOnly,
+ addHandler,
+ editHandler,
+ handleTypeaheadChange,
+ handleFieldChange,
+ objectclasses,
+ attributes,
+ ocName,
+ ocDesc,
+ ocOID,
+ ocParent,
+ ocKind,
+ ocMust,
+ ocMay,
+ objectclassModalShow,
+ closeModal,
+ loading
+ } = this.props;
+ let spinner = "";
+ if (loading) {
+ spinner = (
+ <Row>
+ <div className="ds-margin-top-lg ds-modal-spinner">
+ <Spinner loading inline size="lg" />
+ Saving objectClass...
+ </div>
+ </Row>
+ );
+ }
+
+ return (
+ <div>
+ <Modal show={objectclassModalShow} onHide={closeModal}>
+ <div className="ds-no-horizontal-scrollbar">
+ <Modal.Header>
+ <button
+ className="close"
+ onClick={closeModal}
+ aria-hidden="true"
+ aria-label="Close"
+ >
+ <Icon type="pf" name="close"
/>
+ </button>
+ <Modal.Title>
+ {ocModalViewOnly ? (
+ `View ObjectClass - ${ocName}`
+ ) : (
+ <div>
+ {newOcEntry ? "Add" : "Edit"}
ObjectClass
+ {ocName != "" ? ` - ${ocName}` :
""}{" "}
+ </div>
+ )}
+ </Modal.Title>
+ </Modal.Header>
+ <Modal.Body>
+ <Form horizontal>
+ <FormGroup controlId="ocName">
+ <Col sm={4}>
+ <ControlLabel title="Name of the
objectClass">
+ Objectclass Name
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ id="ocName"
+ type="text"
+ value={ocName}
+ onChange={handleFieldChange}
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup controlId="ocDesc">
+ <Col sm={4}>
+ <ControlLabel title="Describes what is
the objectClass's purpose">
+ Description
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ type="text"
+ value={ocDesc}
+ onChange={handleFieldChange}
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup controlId="ocOID">
+ <Col sm={4}>
+ <ControlLabel title="Object
identifier">
+ OID (optional)
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ type="text"
+ value={ocOID}
+ onChange={handleFieldChange}
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="ocParent"
controlId="ocParent" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An objectClass's
parent">
+ Parent Objectclass
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ allowNew
+ onChange={values => {
+
handleTypeaheadChange("ocParent", values);
+ }}
+ selected={ocParent}
+ newSelectionPrefix="Add a parent:
"
+ options={objectclasses}
+ placeholder="Type a parent
objectClass..."
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="ocKind"
controlId="ocKind" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An objectClass
kind">
+ Objectclass Kind
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <select
+ id="ocKind"
+ className="btn btn-default
dropdown"
+ onChange={handleFieldChange}
+ value={ocKind}
+ disabled={ocModalViewOnly}
+ >
+ <option>STRUCTURAL</option>
+ <option>ABSTRACT</option>
+ <option>AUXILIARY</option>
+ </select>
+ </Col>
+ </FormGroup>
+ <FormGroup key="ocMust"
controlId="ocMust" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="A must attribute
name">
+ Required Attributes
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ allowNew
+ multiple
+ onChange={values => {
+ handleTypeaheadChange("ocMust",
values);
+ }}
+ selected={ocMust}
+ newSelectionPrefix="Add a required
attribute: "
+ options={attributes}
+ placeholder="Type an attribute
name..."
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="ocMay"
controlId="ocMay" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="A may attribute
name">
+ Allowed Attributes
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ allowNew
+ multiple
+ onChange={values => {
+ handleTypeaheadChange("ocMay",
values);
+ }}
+ selected={ocMay}
+ newSelectionPrefix="Add an allowed
attribute: "
+ options={attributes}
+ placeholder="Type an attribute
name..."
+ disabled={ocModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ </Form>
+ {spinner}
+ </Modal.Body>
+ <Modal.Footer>
+ {ocModalViewOnly ? (
+ <Button
+ bsStyle="default"
+ className="btn-cancel"
+ onClick={closeModal}
+ >
+ Close
+ </Button>
+ ) : (
+ <div>
+ <Button
+ bsStyle="default"
+ className="btn-cancel"
+ onClick={closeModal}
+ >
+ Cancel
+ </Button>
+ <Button
+ bsStyle="primary"
+ onClick={newOcEntry ? addHandler : editHandler}
+ >
+ {newOcEntry ? "Add" :
"Save"}
+ </Button>
+ </div>
+ )}
+ </Modal.Footer>
+ </div>
+ </Modal>
+ </div>
+ );
+ }
+}
+
+ObjectClassModal.propTypes = {
+ addHandler: PropTypes.func,
+ editHandler: PropTypes.func,
+ newOcEntry: PropTypes.bool,
+ ocModalViewOnly: PropTypes.bool,
+ handleTypeaheadChange: PropTypes.func,
+ handleFieldChange: PropTypes.func,
+ objectclasses: PropTypes.array,
+ attributes: PropTypes.array,
+ ocName: PropTypes.string,
+ ocDesc: PropTypes.string,
+ ocOID: PropTypes.string,
+ ocParent: PropTypes.array,
+ ocKind: PropTypes.string,
+ ocMust: PropTypes.array,
+ ocMay: PropTypes.array,
+ objectclassModalShow: PropTypes.bool,
+ closeModal: PropTypes.func,
+ loading: PropTypes.bool
+};
+
+ObjectClassModal.defaultProps = {
+ addHandler: noop,
+ editHandler: noop,
+ newOcEntry: true,
+ ocModalViewOnly: false,
+ handleTypeaheadChange: noop,
+ handleFieldChange: noop,
+ objectclasses: [],
+ attributes: [],
+ ocName: "",
+ ocDesc: "",
+ ocOID: "",
+ ocParent: [],
+ ocKind: "",
+ ocMust: [],
+ ocMay: [],
+ objectclassModalShow: false,
+ closeModal: noop,
+ loading: false
+};
+
+class AttributeTypeModal extends React.Component {
+ render() {
+ const {
+ atName,
+ atDesc,
+ atOID,
+ atParent,
+ atSyntax,
+ atUsage,
+ atMultivalued,
+ atNoUserMod,
+ atAlias,
+ atEqMr,
+ atOrder,
+ atSubMr,
+ atModalViewOnly,
+ attributeModalShow,
+ newAtEntry,
+ addHandler,
+ editHandler,
+ handleTypeaheadChange,
+ handleFieldChange,
+ attributes,
+ syntaxes,
+ matchingrules,
+ closeModal,
+ loading
+ } = this.props;
+ let spinner = "";
+ if (loading) {
+ spinner = (
+ <Row>
+ <div className="ds-margin-top-lg ds-modal-spinner">
+ <Spinner loading inline size="lg" />
+ Saving attribute...
+ </div>
+ </Row>
+ );
+ }
+
+ return (
+ <div>
+ <Modal show={attributeModalShow} onHide={closeModal}>
+ <div className="ds-no-horizontal-scrollbar">
+ <Modal.Header>
+ <button
+ className="close"
+ onClick={closeModal}
+ aria-hidden="true"
+ aria-label="Close"
+ >
+ <Icon type="pf" name="close"
/>
+ </button>
+ <Modal.Title>
+ {atModalViewOnly ? (
+ `View Attribute - ${atName}`
+ ) : (
+ <div>
+ {newAtEntry ? "Add" : "Edit"}
Attribute
+ {atName != "" ? ` - ${atName}` :
""}{" "}
+ </div>
+ )}
+ </Modal.Title>
+ </Modal.Header>
+ <Modal.Body>
+ <Form horizontal>
+ <FormGroup controlId="atName">
+ <Col sm={4}>
+ <ControlLabel title="Name of the
attribute">
+ Attribute Name
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ id="atName"
+ type="text"
+ value={atName}
+ onChange={handleFieldChange}
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup controlId="atDesc">
+ <Col sm={4}>
+ <ControlLabel title="Describes what is
the attribute's purpose">
+ Description
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ type="text"
+ value={atDesc}
+ onChange={handleFieldChange}
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup controlId="atOID">
+ <Col sm={4}>
+ <ControlLabel title="Object
identifier">
+ OID (optional)
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <FormControl
+ type="text"
+ value={atOID}
+ onChange={handleFieldChange}
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atParent"
controlId="atParent" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An attribute's
parent">
+ Parent Attribute
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ allowNew
+ onChange={values => {
+
handleTypeaheadChange("atParent", values);
+ }}
+ selected={atParent}
+ newSelectionPrefix="Add a parent:
"
+ options={attributes}
+ placeholder="Type a parent
attribute..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atSyntax"
controlId="atSyntax" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An attribute's
syntax">
+ Syntax Name
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ onChange={values => {
+
handleTypeaheadChange("atSyntax", values);
+ }}
+ selected={atSyntax}
+ newSelectionPrefix="Add a syntax:
"
+ options={syntaxes}
+ placeholder="Type a syntax
name..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atUsage"
controlId="atUsage" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An attribute usage
purpose">
+ Attribute Usage
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <select
+ id="atUsage"
+ className="btn btn-default
dropdown"
+ onChange={handleFieldChange}
+ value={atUsage}
+ disabled={atModalViewOnly}
+ >
+
<option>userApplications</option>
+
<option>directoryOperation</option>
+
<option>distributedOperation</option>
+ <option>dSAOperation</option>
+ </select>
+ </Col>
+ </FormGroup>
+ <FormGroup key="atMultivalued"
controlId="atMultivalued">
+ <Col sm={4}>
+ <ControlLabel title="If attribute can
have a multiple values">
+ Multivalued Attribute
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Checkbox
+ id="atMultivalued"
+ checked={atMultivalued}
+ title="If attribute can have a multiple
values"
+ onChange={handleFieldChange}
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atNoUserMod"
controlId="atNoUserMod">
+ <Col sm={4}>
+ <ControlLabel title="If attribute is not
modifiable by a client application">
+ Not Modifiable By A User
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Checkbox
+ id="atNoUserMod"
+ checked={atNoUserMod}
+ title="If attribute is not modifiable by
a client application"
+ onChange={handleFieldChange}
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atAlias"
controlId="atAlias" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An alias name for
the attribute">
+ Alias Names
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ allowNew
+ multiple
+ onChange={values => {
+
handleTypeaheadChange("atAlias", values);
+ }}
+ selected={atAlias}
+ options={[]}
+ newSelectionPrefix="Add an alias:
"
+ placeholder="Type an alias
name..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atEqMr"
controlId="atEqMr" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An equality matching
rule">
+ Equality Matching Rule
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ onChange={values => {
+ handleTypeaheadChange("atEqMr",
values);
+ }}
+ selected={atEqMr}
+ newSelectionPrefix="Add an matching
rule: "
+ options={matchingrules}
+ placeholder="Type an matching
rule..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atOrder"
controlId="atOrder" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="An order matching
rule">
+ Order Matching Rule
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ onChange={values => {
+
handleTypeaheadChange("atOrder", values);
+ }}
+ selected={atOrder}
+ newSelectionPrefix="Add an matching
rule: "
+ options={matchingrules}
+ placeholder="Type an matching
rule..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ <FormGroup key="atSubMr"
controlId="atSubMr" disabled={false}>
+ <Col sm={4}>
+ <ControlLabel title="A substring matching
rule">
+ Substring Matching Rule
+ </ControlLabel>
+ </Col>
+ <Col sm={8}>
+ <Typeahead
+ onChange={values => {
+
handleTypeaheadChange("atSubMr", values);
+ }}
+ selected={atSubMr}
+ newSelectionPrefix="Add an matching
rule: "
+ options={matchingrules}
+ placeholder="Type an matching
rule..."
+ disabled={atModalViewOnly}
+ />
+ </Col>
+ </FormGroup>
+ </Form>
+ {spinner}
+ </Modal.Body>
+ <Modal.Footer>
+ {atModalViewOnly ? (
+ <Button
+ bsStyle="default"
+ className="btn-cancel"
+ onClick={closeModal}
+ >
+ Close
+ </Button>
+ ) : (
+ <div>
+ <Button
+ bsStyle="default"
+ className="btn-cancel"
+ onClick={closeModal}
+ >
+ Cancel
+ </Button>
+ <Button
+ bsStyle="primary"
+ onClick={newAtEntry ? addHandler : editHandler}
+ >
+ {newAtEntry ? "Add" :
"Save"}
+ </Button>
+ </div>
+ )}
+ </Modal.Footer>
+ </div>
+ </Modal>
+ </div>
+ );
+ }
+}
+
+AttributeTypeModal.propTypes = {
+ addHandler: PropTypes.func,
+ editHandler: PropTypes.func,
+ handleTypeaheadChange: PropTypes.func,
+ handleFieldChange: PropTypes.func,
+ attributes: PropTypes.array,
+ matchingrules: PropTypes.array,
+ syntaxes: PropTypes.array,
+ atName: PropTypes.string,
+ atDesc: PropTypes.string,
+ atOID: PropTypes.string,
+ atParent: PropTypes.array,
+ atSyntax: PropTypes.array,
+ atUsage: PropTypes.string,
+ atMultivalued: PropTypes.bool,
+ atNoUserMod: PropTypes.bool,
+ atAlias: PropTypes.array,
+ atEqMr: PropTypes.array,
+ atOrder: PropTypes.array,
+ atSubMr: PropTypes.array,
+ atModalViewOnly: PropTypes.bool,
+ attributeModalShow: PropTypes.bool,
+ newAtEntry: PropTypes.bool,
+ closeModal: PropTypes.func,
+ loading: PropTypes.bool
+};
+
+AttributeTypeModal.defaultProps = {
+ addHandler: noop,
+ editHandler: noop,
+ handleTypeaheadChange: noop,
+ handleFieldChange: noop,
+ attributes: [],
+ matchingrules: [],
+ syntaxes: [],
+ atName: "",
+ atDesc: "",
+ atOID: "",
+ atParent: [],
+ atSyntax: [],
+ atUsage: "userApplications",
+ atMultivalued: false,
+ atNoUserMod: false,
+ atAlias: [],
+ atEqMr: [],
+ atOrder: [],
+ atSubMr: [],
+ atModalViewOnly: false,
+ attributeModalShow: false,
+ newAtEntry: true,
+ closeModal: noop,
+ loading: false
+};
+
+export { ObjectClassModal, AttributeTypeModal };
diff --git a/src/cockpit/389-console/src/lib/schema/schemaTables.jsx
b/src/cockpit/389-console/src/lib/schema/schemaTables.jsx
new file mode 100644
index 0000000..296845c
--- /dev/null
+++ b/src/cockpit/389-console/src/lib/schema/schemaTables.jsx
@@ -0,0 +1,558 @@
+import React from "react";
+import {
+ Button,
+ DropdownButton,
+ MenuItem,
+ actionHeaderCellFormatter,
+ sortableHeaderCellFormatter,
+ tableCellFormatter,
+ noop
+} from "patternfly-react";
+import { DSTable } from "../dsTable.jsx";
+import PropTypes from "prop-types";
+import "../../css/ds.css";
+
+class ObjectClassesTable extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ searchFilterValue: "",
+ fieldsToSearch: ["name", "oid"],
+ columns: [
+ {
+ property: "name",
+ header: {
+ label: "ObjectClass Name",
+ props: {
+ index: 0,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 0
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "oid",
+ header: {
+ label: "OID",
+ props: {
+ index: 1,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 1
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "must",
+ header: {
+ label: "Required Attributes",
+ props: {
+ index: 2,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 2
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [<td
key={rowData.name[0]}>{value.join(" ")}</td>];
+ }
+ ]
+ }
+ },
+ {
+ property: "may",
+ header: {
+ label: "Allowed Attributes",
+ props: {
+ index: 3,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 3
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [<td
key={rowData.name[0]}>{value.join(" ")}</td>];
+ }
+ ]
+ }
+ },
+ {
+ property: "actions",
+ header: {
+ label: "Actions",
+ props: {
+ index: 4,
+ rowSpan: 1,
+ colSpan: 1
+ },
+ formatters: [actionHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 4
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [
+ <td key={rowData.name[0]}>
+ {rowData.x_origin === null ||
+ rowData.x_origin === undefined ||
+ rowData.x_origin[0].toLowerCase() != "user
defined" ? (
+ <Button
+ onClick={() => {
+
this.props.viewModalHandler(rowData);
+ }}
+ >
+ View Objectclass
+ </Button>
+ ) : (
+ <DropdownButton
+ id={rowData.name[0]}
+ bsStyle="default"
+ title="Choose Action..."
+ className="ds-schema-dropdown"
+ >
+ <MenuItem
+ eventKey="1"
+
className="ds-schema-dropdown"
+ onClick={() => {
+
this.props.editModalHandler(rowData);
+ }}
+ >
+ Edit ObjectClass
+ </MenuItem>
+ <MenuItem divider />
+ <MenuItem
+ eventKey="2"
+
className="ds-schema-dropdown"
+ onClick={() => {
+
this.props.deleteHandler(rowData);
+ }}
+ >
+ Delete ObjectClass
+ </MenuItem>
+ </DropdownButton>
+ )}
+ </td>
+ ];
+ }
+ ]
+ }
+ }
+ ]
+ };
+ this.getColumns = this.getColumns.bind(this);
+ }
+
+ getColumns() {
+ return this.state.columns;
+ }
+
+ render() {
+ return (
+ <div>
+ <DSTable
+ getColumns={this.getColumns}
+ fieldsToSearch={this.state.fieldsToSearch}
+ rowKey="name"
+ rows={this.props.rows}
+ toolBarSearchField="ObjectClasses"
+ toolBarLoading={this.props.loading}
+ />
+ </div>
+ );
+ }
+}
+
+ObjectClassesTable.propTypes = {
+ rows: PropTypes.array,
+ editModalHandler: PropTypes.func,
+ deleteHandler: PropTypes.func,
+ viewModalHandler: PropTypes.func,
+ loading: PropTypes.bool
+};
+
+ObjectClassesTable.defaultProps = {
+ rows: [],
+ editModalHandler: noop,
+ deleteHandler: noop,
+ viewModalHandler: noop,
+ loading: false
+};
+
+class AttributesTable extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ searchFilterValue: "",
+ fieldsToSearch: ["name", "oid"],
+ columns: [
+ {
+ property: "name",
+ header: {
+ label: "Attribute Name",
+ props: {
+ index: 0,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 0
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "oid",
+ header: {
+ label: "OID",
+ props: {
+ index: 1,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 1
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "syntax",
+ header: {
+ label: "Syntax",
+ props: {
+ index: 2,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 2
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [
+ <td key={rowData.name[0]}>
+ {
+ this.props.syntaxes.filter(
+ attr => attr.id === value[0]
+ )[0]["label"]
+ }
+ </td>
+ ];
+ }
+ ]
+ }
+ },
+ {
+ property: "multivalued",
+ header: {
+ label: "Multivalued",
+ props: {
+ index: 3,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 3
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [<td key={rowData.name[0]}>{value ?
"yes" : "no"}</td>];
+ }
+ ]
+ }
+ },
+ {
+ property: "actions",
+ header: {
+ label: "Actions",
+ props: {
+ index: 4,
+ rowSpan: 1,
+ colSpan: 1
+ },
+ formatters: [actionHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 4
+ },
+ formatters: [
+ (value, { rowData }) => {
+ return [
+ <td key={rowData.name[0]}>
+ {rowData.x_origin === null ||
+ rowData.x_origin === undefined ||
+ rowData.x_origin[0].toLowerCase() != "user
defined" ? (
+ <Button
+ onClick={() => {
+
this.props.viewModalHandler(rowData);
+ }}
+ >
+ View Attribute
+ </Button>
+ ) : (
+ <DropdownButton
+ id={rowData.name[0]}
+ bsStyle="default"
+ title="Choose Action..."
+ className="ds-schema-dropdown"
+ >
+ <MenuItem
+ eventKey="1"
+
className="ds-schema-dropdown"
+ onClick={() => {
+
this.props.editModalHandler(rowData);
+ }}
+ >
+ Edit Attribute
+ </MenuItem>
+ <MenuItem divider />
+ <MenuItem
+ eventKey="2"
+
className="ds-schema-dropdown"
+ onClick={() => {
+
this.props.deleteHandler(rowData);
+ }}
+ >
+ Delete Attribute
+ </MenuItem>
+ </DropdownButton>
+ )}
+ </td>
+ ];
+ }
+ ]
+ }
+ }
+ ]
+ };
+ this.getColumns = this.getColumns.bind(this);
+ }
+
+ getColumns() {
+ return this.state.columns;
+ }
+
+ render() {
+ return (
+ <div>
+ <DSTable
+ getColumns={this.getColumns}
+ fieldsToSearch={this.state.fieldsToSearch}
+ rowKey="name"
+ rows={this.props.rows}
+ toolBarSearchField="Attributes"
+ toolBarLoading={this.props.loading}
+ />
+ </div>
+ );
+ }
+}
+
+AttributesTable.propTypes = {
+ rows: PropTypes.array,
+ editModalHandler: PropTypes.func,
+ deleteHandler: PropTypes.func,
+ viewModalHandler: PropTypes.func,
+ syntaxes: PropTypes.array,
+ loading: PropTypes.bool
+};
+
+AttributesTable.defaultProps = {
+ rows: [],
+ editModalHandler: noop,
+ deleteHandler: noop,
+ viewModalHandler: noop,
+ syntaxes: [],
+ loading: false
+};
+
+class MatchingRulesTable extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ searchFilterValue: "",
+ fieldsToSearch: ["name", "oid"],
+ columns: [
+ {
+ property: "name",
+ header: {
+ label: "Matching Rule Name",
+ props: {
+ index: 0,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 0
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "oid",
+ header: {
+ label: "OID",
+ props: {
+ index: 1,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 1
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "syntax",
+ header: {
+ label: "Syntax",
+ props: {
+ index: 2,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 2
+ },
+ formatters: [tableCellFormatter]
+ }
+ },
+ {
+ property: "desc",
+ header: {
+ label: "Description",
+ props: {
+ index: 3,
+ rowSpan: 1,
+ colSpan: 1,
+ sort: true
+ },
+ transforms: [],
+ formatters: [],
+ customFormatters: [sortableHeaderCellFormatter]
+ },
+ cell: {
+ props: {
+ index: 3
+ },
+ formatters: [tableCellFormatter]
+ }
+ }
+ ]
+ };
+ this.getColumns = this.getColumns.bind(this);
+ }
+
+ getColumns() {
+ return this.state.columns;
+ }
+
+ render() {
+ return (
+ <div>
+ <DSTable
+ getColumns={this.getColumns}
+ fieldsToSearch={this.state.fieldsToSearch}
+ rowKey="oid"
+ rows={this.props.rows}
+ toolBarSearchField="Matching Rules"
+ toolBarDisableLoadingSpinner
+ />
+ </div>
+ );
+ }
+}
+
+MatchingRulesTable.propTypes = {
+ rows: PropTypes.array
+};
+
+MatchingRulesTable.defaultProps = {
+ rows: []
+};
+
+export { ObjectClassesTable, AttributesTable, MatchingRulesTable };
diff --git a/src/cockpit/389-console/src/lib/tools.jsx
b/src/cockpit/389-console/src/lib/tools.jsx
index 631135e..7617a78 100644
--- a/src/cockpit/389-console/src/lib/tools.jsx
+++ b/src/cockpit/389-console/src/lib/tools.jsx
@@ -6,7 +6,9 @@ export function searchFilter(searchFilterValue, columnsToSearch, rows) {
if (columnsToSearch && columnsToSearch.length) {
columnsToSearch.forEach(column => {
if (column in row) {
- rowToSearch.push(row[column]);
+ if (row[column] != null) {
+ rowToSearch.push(row[column]);
+ }
}
});
} else {
@@ -53,22 +55,26 @@ export function log_cmd(js_func, desc, cmd_array) {
cmd_list.push(cmd);
}
}
- console.log(
- "CMD: " + js_func + ": " + desc + " ==> " +
cmd_list.join(" ")
- );
+ console.log("CMD: " + js_func + ": " + desc + " ==>
" + cmd_list.join(" "));
}
}
// Convert DS timestamp to a friendly string: 20180921142257Z -> 10/21/2018, 2:22:57
PM
-export function get_date_string (timestamp) {
+export function get_date_string(timestamp) {
let year = timestamp.substr(0, 4);
let month = timestamp.substr(4, 2);
let day = timestamp.substr(6, 2);
let hour = timestamp.substr(8, 2);
let minute = timestamp.substr(10, 2);
let sec = timestamp.substr(12, 2);
- let date = new Date(parseInt(year), (parseInt(month) - 1), parseInt(day),
- parseInt(hour), parseInt(minute), parseInt(sec));
+ let date = new Date(
+ parseInt(year),
+ parseInt(month) - 1,
+ parseInt(day),
+ parseInt(hour),
+ parseInt(minute),
+ parseInt(sec)
+ );
return date.toLocaleString();
}
@@ -81,8 +87,14 @@ export function get_date_diff(start, end) {
let hour = start.substr(8, 2);
let minute = start.substr(10, 2);
let sec = start.substr(12, 2);
- let startDate = new Date(parseInt(year), parseInt(month), parseInt(day),
- parseInt(hour), parseInt(minute), parseInt(sec));
+ let startDate = new Date(
+ parseInt(year),
+ parseInt(month),
+ parseInt(day),
+ parseInt(hour),
+ parseInt(minute),
+ parseInt(sec)
+ );
// Get the servers current date
year = end.substr(0, 4);
@@ -91,17 +103,23 @@ export function get_date_diff(start, end) {
hour = end.substr(8, 2);
minute = end.substr(10, 2);
sec = end.substr(12, 2);
- let currDate = new Date(parseInt(year), parseInt(month), parseInt(day),
- parseInt(hour), parseInt(minute), parseInt(sec));
+ let currDate = new Date(
+ parseInt(year),
+ parseInt(month),
+ parseInt(day),
+ parseInt(hour),
+ parseInt(minute),
+ parseInt(sec)
+ );
// Generate pretty elapsed time string
- let seconds = Math.floor((currDate - (startDate)) / 1000);
+ let seconds = Math.floor((currDate - startDate) / 1000);
let minutes = Math.floor(seconds / 60);
let hours = Math.floor(minutes / 60);
let days = Math.floor(hours / 24);
- hours = hours - (days * 24);
- minutes = minutes - (days * 24 * 60) - (hours * 60);
- seconds = seconds - (days * 24 * 60 * 60) - (hours * 60 * 60) - (minutes * 60);
+ hours = hours - days * 24;
+ minutes = minutes - days * 24 * 60 - hours * 60;
+ seconds = seconds - days * 24 * 60 * 60 - hours * 60 * 60 - minutes * 60;
return `${days} days, ${hours} hours, ${minutes} minutes, and ${seconds} seconds`;
}
@@ -114,7 +132,7 @@ export function bad_file_name(file_name) {
return false;
}
-export function valid_port (val) {
+export function valid_port(val) {
// Validate value is a number and between 1 and 65535
let result = !isNaN(val);
if (result) {
@@ -125,9 +143,9 @@ export function valid_port (val) {
return result;
}
-export function valid_dn (dn) {
+export function valid_dn(dn) {
// Validate value is a valid DN (sanity validation)
- if (dn.endsWith(',')) {
+ if (dn.endsWith(",")) {
return false;
}
let dn_regex = new RegExp("^([A-Za-z]+=.*)");
diff --git a/src/cockpit/389-console/src/schema.html
b/src/cockpit/389-console/src/schema.html
deleted file mode 100644
index cb6baf9..0000000
--- a/src/cockpit/389-console/src/schema.html
+++ /dev/null
@@ -1,377 +0,0 @@
-
-<div id="schema-content">
- <div id="objectclass-page" class="all-pages ds-margin-left"
hidden>
- <h3 class="ds-config-header">Objectclasses</h3>
- <div>
- <input type="checkbox" class="ds-config-checkbox"
id="oc-user-defined"><label
- for="oc-user-defined" class="ds-label">Only
Non-standard Schema (objectClasses with X-ORIGIN: "user defined")</label>
- </div>
- <table id="oc-table" class="display ds-repl-table"
cellspacing="0" width="100%">
- <thead>
- <tr class="ds-table-header">
- <th class="ds-center">Objectclass Name</th>
- <th class="ds-center">OID</th>
- <th class="ds-center">Required Attributes</th>
- <th class="ds-center">Allowed Attributes</th>
- <th class="ds-center">Action</th>
- </tr>
- </thead>
- <tbody>
- </tbody>
- </table>
- <button id="add-oc-button" name="create-oc"
data-toggle="modal" data-target="#add-edit-oc-form" class="btn
btn-primary ds-button">Create Objectclass</button>
- </div>
-
- <div id="attribute-page" class="all-pages ds-margin-left"
hidden>
- <h3 class="ds-config-header">Attributes</h3>
- <div>
- <input type="checkbox" class="ds-config-checkbox"
id="attr-user-defined"><label
- for="attr-user-defined" class="ds-label">Only
Non-standard Schema (attributes with X-ORIGIN: "user defined")</label>
- </div>
- <table id="attr-table" class="display ds-repl-table"
cellspacing="0" width="100%">
- <thead>
- <tr class="ds-table-header">
- <th class="ds-center">Attribute Name</th>
- <th class="ds-center">OID</th>
- <th class="ds-center">Syntax</th>
- <th class="ds-center">Multivalued</th>
- <th class="ds-center">Action</th>
- </tr>
- </thead>
- <tbody>
- </tbody>
- </table>
- <button id="create-attr-button" data-toggle="modal"
data-target="#add-edit-attr-form" class="btn btn-primary
ds-button">Create Attribute</button>
- </div>
-
- <div id="schema-mr" class="all-pages ds-margin-left" hidden>
- <div class="">
- <h3 class="ds-config-header">Matching Rules</h3>
- <table id="schema-mr-table" class="display ds-table"
cellspacing="0" width="100%">
- <thead>
- <tr class="ds-table-header">
- <th>Matching Rule Name</th>
- <th>OID</th>
- <th>Syntax</th>
- <th>Description</th>
- </tr>
- </thead>
- <tbody id="standard-body">
- </tbody>
- </table>
- </div>
- </div>
-
-
- <!-- Modals/Popups/Wizards -->
-
- <!-- View Attribute modal -->
- <div class="modal fade" id="view-attr-form"
data-backdrop="static" tabindex="-1" role="dialog"
aria-labelledby="view-attr-header" aria-hidden="true">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close"
data-dismiss="modal" aria-hidden="true"
aria-label="Close">
- <span class="pficon pficon-close"></span>
- </button>
- <h4 class="modal-title">View Attribute</h4>
- </div>
- <div class="modal-body">
- <div class="ds-inline">
- <div>
- <label for="attr-name-view"
class="ds-config-label-lrg" title="The attribute name"><b
- >Attribute Name</b></label><input
class="ds-input" type="text" id="attr-name-view"
size="40" disabled />
- </div>
- <div>
- <label for="attr-desc-view"
class="ds-config-label-lrg" title="The attribute
description"><b
- >Description</b></label><input
class="ds-input" type="text" id="attr-desc-view"
size="40" disabled />
- </div>
- <div>
- <label for="attr-oid-view"
class="ds-config-label-lrg" title="The attribute name"><b
- >OID</b></label><input
class="ds-input" type="text" id="attr-oid-view"
size="40" disabled />
- </div>
- <div>
- <label for="attr-parent-view"
class="ds-config-label-lrg" title="The parent
attribute"><b>Parent Attribute</b></label><input
- class="ds-input" type="text"
id="attr-parent-view" size="40" disabled />
- </div>
- <div>
- <label for="attr-syntax-view"
class="ds-config-label-lrg" title="The attribute
syntax"><b>Attribute Syntax</b></label><input
- class="ds-input" type="text"
id="attr-syntax-view" size="40" disabled />
- </div>
- <div>
- <label for="attr-usage-view"
class="ds-config-label-lrg" title="The parent
attribute"><b>Attribute Usage</b></label><input
- class="ds-input" type="text"
id="attr-usage-view" size="40" disabled />
- </div>
- <div>
- <input type="checkbox"
class="ds-config-checkbox" id="attr-multivalued-view"
disabled="disabled" /><label
- for="attr-multivalued-view"
class="ds-label"> Attribute Multi-Valued </label>
- </div>
- <div>
- <input type="checkbox"
class="ds-config-checkbox" id="attr-no-user-mod-view"
disabled="disabled" /><label
- for="attr-no-user-mod-view"
class="ds-label"> Read-only (NO-USER-MODIFICATION flag) </label>
- </div>
- <div>
- <label for="attr-alias-view"
class="ds-config-label-lrg" title="The attribute alias list separated by
space"><b
- >Attribute Aliases</b></label><input
class="ds-input" type="text" id="attr-alias-view"
size="40" disabled />
- </div>
- <div class="panel panel-default ds-margin-top">
- <div
class="panel-heading"><strong>Matching
rules</strong></div>
- <div class="panel-body">
- <div>
- <label for="attr-eq-mr-select-view"
class="ds-config-label-lrg"><b>Equality</b></label><input
- class="ds-input"
type="text" id="attr-eq-mr-select-view" size="35" disabled
/>
- </div>
- <div>
- <label for="attr-order-mr-select-view"
class="ds-config-label-lrg"><b>Ordering</b></label><input
- class="ds-input" type="text"
id="attr-order-mr-select-view" size="35" disabled />
- </div>
- <div>
- <label for="attr-sub-mr-select-view"
class="ds-config-label-lrg"><b>Substring</b></label><input
- class="ds-input" type="text"
id="attr-sub-mr-select-view" size="35" disabled />
- </div>
- </div>
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn
btn-default" data-dismiss="modal">Close</button>
- </div>
- </div>
- </div>
- </div>
- </div>
-
- <!-- Add/edit Attribute modal -->
- <div class="modal fade" id="add-edit-attr-form"
data-backdrop="static" tabindex="-1" role="dialog"
aria-labelledby="add-edit-attr-header" aria-hidden="true">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close"
data-dismiss="modal" aria-hidden="true"
aria-label="Close">
- <span class="pficon pficon-close"></span>
- </button>
- <h4 class="modal-title" id="add-edit-attr-header">Add
Attribute</h4>
- </div>
- <div class="modal-body">
- <div class="ds-inline">
- <p class="ds-modal-error"></p>
- <div>
- <label for="attr-name" class="ds-config-label-lrg"
title="The attribute name"><b
- >Attribute Name</b></label><input
class="ds-input" type="text" id="attr-name"
size="40"/>
- </div>
- <div>
- <label for="attr-desc" class="ds-config-label-lrg"
title="The attribute description"><b
- >Description</b></label><input class="ds-input"
type="text" id="attr-desc" size="40"/>
- </div>
- <div>
- <label for="attr-oid" class="ds-config-label-lrg"
title="The attribute name"><b
- >OID</b></label><input class="ds-input"
type="text" id="attr-oid" size="40"/>
- </div>
- <div>
- <label for="attr-parent" class="ds-config-label-lrg"
title="The parent attribute"><b>Parent
Attribute</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown"
id="attr-parent">
- <option value=""></option>
- </select>
- </div>
- <div>
- <label for="attr-syntax" class="ds-config-label-lrg"
title="The attribute syntax"><b>Attribute
Syntax</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown"
id="attr-syntax">
- <option value="">Make a selection</option>
- </select>
- </div>
- <div>
- <label for="attr-usage" class="ds-config-label-lrg"
title="The parent attribute"><b>Attribute
Usage</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown"
id="attr-usage">
- </select>
- </div>
- <div>
- <input type="checkbox" class="ds-config-checkbox"
id="attr-multivalued"><label
- for="attr-multivalued" class="ds-label"> Attribute
Multi-Valued </label>
- </div>
- <div>
- <input type="checkbox" class="ds-config-checkbox"
id="attr-no-user-mod"><label
- for="attr-no-user-mod" class="ds-label">
Read-only (NO-USER-MODIFICATION flag) </label>
- </div>
- <div>
- <label for="attr-alias" class="ds-config-label-lrg"
title="The attribute alias list separated by space"><b
- >Attribute Aliases</b></label><input
class="ds-input" type="text" id="attr-alias"
size="40"/>
- </div>
- <div class="panel panel-default ds-margin-top">
- <div class="panel-heading"><strong>Matching
rules</strong></div>
- <div class="panel-body">
- <div>
- <label for="attr-eq-mr-select"
class="ds-config-label-lrg"><b>Equality</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown"
id="attr-eq-mr-select">
- <option></option>
- </select>
- </div>
- <div>
- <label for="attr-order-mr-select"
class="ds-config-label-lrg"><b>Ordering</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown"
id="attr-order-mr-select">
- <option></option>
- </select>
- </div>
- <div>
- <label for="attr-sub-mr-select"
class="ds-config-label-lrg"><b>Substring</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown"
id="attr-sub-mr-select">
- <option></option>
- </select>
- </div>
- </div>
- </div>
- </div>
- <div id="save-attr-spinner" class="ds-center"
hidden>
- <p></p>
- <p><span class="spinner spinner-xs
spinner-inline"></span> Processing...<p>
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default"
data-dismiss="modal">Cancel</button>
- <button type="button" class="btn btn-primary"
id="save-attr-button">Save</button>
- </div>
- </div>
- </div>
- </div>
-
-
- <!-- View Objectclass -->
- <div class="modal fade" id="view-objectclass-form"
aria-labelledby="view-objectclass-form" data-backdrop="static"
tabindex="-1" role="dialog" aria-hidden="true">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close"
data-dismiss="modal" aria-hidden="true"
aria-label="Close">
- <span class="pficon pficon-close"></span>
- </button>
- <h4 class="modal-title">View Objectclass</h4>
- </div>
- <div class="modal-body">
- <form class="form-horizontal">
- <div class="ds-inline">
- <div>
- <label for="oc-name-view"
class="ds-config-label-lrg" title="The objectclass name"><b
- >Objectclass Name</b></label><input
class="ds-input" type="text" id="oc-name-view"
size="40" disabled />
- </div>
- <div>
- <label for="oc-desc-view"
class="ds-config-label-lrg" title="The objectClass
description"><b
- >Description</b></label><input
class="ds-input" type="text" id="oc-desc-view"
size="40" disabled/>
- </div>
- <div>
- <label for="oc-oid-view"
class="ds-config-label-lrg" title="Objectclass OID
(optional)"><b
- >OID (optional)</b></label><input
class="ds-input" value="" type="text"
id="oc-oid-view" size="40" disabled/>
- </div>
- <div>
- <label for="oc-parent-view"
class="ds-config-label-lrg" title="The parent
objectclass"><b>Parent Objectclass</b></label><input
- class="ds-input" value=""
type="text" id="oc-parent-view" size="40" disabled />
- </div>
- <div>
- <label for="oc-kind-view"
class="ds-config-label-lrg" title="The parent
objectclass"><b>Objectclass Kind</b></label><input
- class="ds-input" value=""
type="text" id="oc-kind-view" size="40" disabled />
- </div>
- <hr>
- <div class="ds-container">
- <div>
- <label class="ds-config-label"
for="oc-required-list-view" title=
- "Attributes allowed by the
objectclass"><b>Required Attributes</b></label>
- <select id="oc-required-list-view"
class="ds-may-must-list" multiple disabled>
- </select>
- </div>
- <div class="ds-divider"></div>
- <div>
- <label class="ds-config-label"
for="oc-allowed-list-view" title=
- "Attributes allowed by the
objectclass"><b>Allowed Attributes</b></label>
- <select id="oc-allowed-list-view"
class="ds-may-must-list" multiple disabled>
- </select>
- </div>
- </div>
- </div>
- </form>
- <div class="modal-footer">
- <button type="button" class="btn
btn-default" data-dismiss="modal">Close</button>
- </div>
- </div>
- </div>
- </div>
- </div>
-
- <!-- Add/Edit Objectclass -->
- <div class="modal fade" id="add-edit-oc-form"
data-backdrop="static" tabindex="-1" role="dialog"
aria-labelledby="add-edit-oc-header" aria-hidden="true">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close"
data-dismiss="modal" aria-hidden="true"
aria-label="Close">
- <span class="pficon pficon-close"></span>
- </button>
- <h4 class="modal-title" id="add-edit-oc-header">Add
Objectclass</h4>
- </div>
- <div class="modal-body">
- <form class="form-horizontal">
- <div class="ds-inline">
- <p class="ds-modal-error"></p>
- <div>
- <label for="oc-name" class="ds-config-label-lrg"
title="The objectclass name"><b
- >Objectclass Name</b></label><input
class="ds-input" type="text" id="oc-name"
size="40" required />
- </div>
- <div>
- <label for="oc-desc" class="ds-config-label-lrg"
title="The objectClass description"><b
- >Description</b></label><input
class="ds-input" type="text" id="oc-desc"
size="40"/>
- </div>
- <div>
- <label for="oc-oid" class="ds-config-label-lrg"
title="Objectclass OID (optional)"><b
- >OID (optional)</b></label><input
class="ds-input" value="" type="text" id="oc-oid"
size="40"/>
- </div>
- <div>
- <label for="oc-parent" class="ds-config-label-lrg"
title="The parent objectclass"><b>Parent
Objectclass</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown"
id="oc-parent">
- </select>
- </div>
- <div>
- <label for="oc-kind" class="ds-config-label-lrg"
title="The parent objectclass"><b>Objectclass
Kind</b></label><select
- class="btn btn-default dropdown ds-oc-dropdown"
id="oc-kind">
- <option value=""></option>
- </select>
- </div>
- <hr>
- <div class="ds-container">
- <div name="available-attrs">
- <label for="schema-list" title="The available
attributes to choose from."><b>Available Attributes</b></label>
- <select id="schema-list" class="ds-oc-form-list"
name="availattrs" multiple>
- </select>
- </div>
-
- <div name="add-remove-buttons">
- <div name="must buttons" class="btn-group
ds-oc-must-buttons">
- <input type="button" class="ds-oc-add-del-btn"
id="oc-must-add-button" value="Add ► ►
► "/>
- <input type="button" class="ds-oc-add-del-btn"
id="oc-must-remove-button" value="◄ ◄ ◄
Remove"/>
- </div>
- <p></p>
- <div name="may buttons" class="btn-group
ds-oc-may-buttons">
- <input type="button" class="ds-oc-add-del-btn"
id="oc-may-add-button" value="Add ► ►
►"/>
- <input type="button" class="ds-oc-add-del-btn"
id="oc-may-remove-button" value="◄ ◄ ◄
Remove"/>
- </div>
- </div>
-
- <div name="may-must-lists">
- <label class="ds-config-label"
for="oc-required-list" title=
- "Attributes required by the
objectclass"><b>Required Attributes</b></label>
- <select id="oc-required-list"
class="ds-may-must-list" name="availattrs" multiple>
- </select>
- <p></p>
- <label class="ds-config-label"
for="oc-allowed-list" title=
- "Attributes allowed by the objectclass"><b>Allowed
Attributes</b></label>
- <select id="oc-allowed-list"
class="ds-may-must-list" name="availattrs" multiple>
- </select>
- </div>
- </div>
- </div>
- </form>
- <div id="save-oc-spinner" class="ds-center" hidden>
- <p></p>
- <p><span class="spinner spinner-xs
spinner-inline"></span> Processing...<p>
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default"
data-dismiss="modal">Cancel</button>
- <button type="button" class="btn btn-primary"
id="save-oc-button">Save</button>
- </div>
- </div>
- </div>
- </div>
-
-</div>
diff --git a/src/cockpit/389-console/src/schema.js
b/src/cockpit/389-console/src/schema.js
deleted file mode 100644
index ea6159b..0000000
--- a/src/cockpit/389-console/src/schema.js
+++ /dev/null
@@ -1,925 +0,0 @@
-var attr_btn_html =
- '<div class="dropdown">' +
- '<button class="btn btn-default dropdown-toggle"
type="button" data-toggle="dropdown">' +
- ' Choose Action...' +
- '<span class="caret"></span>' +
- '</button>' +
- '<ul class="dropdown-menu ds-agmt-dropdown" role="menu"
id="attr-action-btn" aria-labelledby="attr-action-btn">' +
- '<li role=""><a role="menuitem"
tabindex="0" class="attr-edit-btn"
href="#schema-tab">Edit Attribute</a></li>' +
- '<li role=""><a role="menuitem"
tabindex="1" class="attr-del-btn"
href="#schema-tab">Delete Attribute</a></li>' +
- '</ul>' +
- '</div>';
-
-var attr_btn_html_only_view =
- '<button class="btn btn-default attr-view-btn"
type="button"' +
- ' href="#schema-tab" title="Only user-defined attributes can be
modified"> View Attribute' +
- '</button>';
-
-var oc_btn_html =
- '<div class="dropdown">' +
- '<button class="btn btn-default dropdown-toggle"
type="button"data-toggle="dropdown">' +
- ' Choose Action...' +
- '<span class="caret"></span>' +
- '</button>' +
- '<ul class="dropdown-menu ds-agmt-dropdown"
role="menu">' +
- '<li role=""><a role="menuitem"
tabindex="0" class="oc-edit-btn" href="#schema-tab">Edit
Objectclass</a></li>' +
- '<li role=""><a role="menuitem"
tabindex="1" class="oc-del-btn" href="#schema-tab">Delete
Objectclass</a></li>' +
- '</ul>' +
- '</div>';
-
-var oc_btn_html_only_view =
- '<button class="btn btn-default oc-view-btn"
type="button"' +
- ' href="#schema-tab" title="Only user-defined objectClasses can be
modified"> View Objectclass' +
- '</button>';
-
-var schema_oc_table;
-var schema_at_table;
-var schema_mr_table;
-
-var attr_usage_opts = ['userApplications', 'directoryOperation',
'distributedOperation', 'dSAOperation'];
-var oc_kind_opts = ['STRUCTURAL', 'ABSTRACT', 'AUXILIARY'];
-
-function is_x_origin_user_defined(x_origin) {
- if (typeof x_origin === 'string' && x_origin.toLowerCase() !==
'user defined' || x_origin == null) {
- return false;
- } else {
- return true;
- }
-}
-
-// Leave only user defined attributes if the checkbox is crossed
-$.fn.dataTable.ext.search.push(
- function(settings, searchData, index, rowData, counter) {
- var x_origin;
- if ( settings.sTableId == "attr-table" ) {
- if ( $("#attr-user-defined").is(":checked") ) {
- x_origin = rowData[7];
- if (!is_x_origin_user_defined(x_origin)) {
- return false;
- }
- }
- } else {
- if ( $("#oc-user-defined").is(":checked") ) {
- x_origin = rowData[5];
- if (!is_x_origin_user_defined(x_origin)) {
- return false;
- }
- }
- }
- return true;
- }
-);
-
-function clear_oc_form() {
- // Clear input fields and reset dropboxes
- $("#add-edit-oc-header").html('Add Objectclass');
- $(".ds-modal-error").hide();
- $("#oc-name").attr('disabled', false);
- $("#oc-name").val("");
- $("#oc-oid").val("");
- $("#oc-kind").prop('selectedIndex',0);
- $("#oc-desc").val("");
- $("#oc-parent").prop('selectedIndex',0);
- $("#schema-list").prop('selectedIndex',-1);
- $('#oc-required-list').find('option').remove();
- $('#oc-allowed-list').find('option').remove();
- $("#save-oc-button").attr('disabled', false);
-}
-
-function clear_attr_form() {
- // Clear input fields and reset dropboxes
- $("#add-edit-attr-header").html('Add Attribute');
- $(".ds-modal-error").hide();
- $("#attr-name").attr('disabled', false);
- $("#attr-name").val("");
- $("#attr-syntax").val("");
- $("#attr-desc").val("");
- $("#attr-parent").prop('selectedIndex',0);
- $("#attr-usage").prop('selectedIndex',0);
- $("#attr-oid").val("");
- $("#attr-alias").val("");
- $('#attr-multivalued').prop('checked', false);
- $('#attr-no-user-mod').prop('checked', false);
- $("#attr-eq-mr-select").prop('selectedIndex',0);
- $("#attr-order-mr-select").prop('selectedIndex',0);
- $("#attr-sub-mr-select").prop('selectedIndex',0);
- $("#save-attr-button").attr('disabled', false);
-}
-
-function load_schema_objects_to_select(object, select_id, schema_json_select) {
- var data = [];
- for (var i = 0; i < schema_json_select[object].items.length; i++) {
- item = schema_json_select[object].items[i];
- if (item.name) {
- data.push.apply(data, [item.name]);
- } else {
- data.push.apply(data, [item.oid]);
- }
- }
- // Update html select
- $.each(data, function (i, item) {
- $("#" + select_id).append($('<option>', {
- value: item,
- text : item
- }));
- });
-}
-
-function get_and_set_schema_tables() {
- console.log("Loading schema...");
-
- // Set attribute usage select html in attribute's edit window
- $.each(attr_usage_opts, function (i, item) {
- $("#attr-usage").append($('<option>', {
- value: item,
- text : item,
- }));
- });
-
- // Set objectClass kind select html in objectClass's edit window
- $.each(oc_kind_opts, function (i, item) {
- $("#oc-kind").append($('<option>', {
- value: item,
- text : item,
- }));
- });
-
- var cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id +
'.socket', 'schema', 'list'];
- log_cmd('get_and_set_schema_tables', 'Get all schema objects', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message",
"environ": [ENV]}).done(function(schema_data) {
- var schema_json = JSON.parse(schema_data);
- // Setup the tables: standard, custom, and Matching Rules
- var data = [];
- // If objectClass is user defined them the action button is enabled
- for (var i = 0; i < schema_json.objectclasses.items.length; i++) {
- var oc_btn = oc_btn_html_only_view;
- item = schema_json.objectclasses.items[i];
- if (is_x_origin_user_defined(item.x_origin)) {
- oc_btn = oc_btn_html;
- }
- // Validate all params
- if (item.oid === undefined) {
- item.oid = "";
- }
- if (item.must === undefined) {
- item.must = [];
- }
- if (item.may === undefined) {
- item.may = [];
- }
- if (item.x_origin === undefined) {
- item.x_origin = "";
- }
- if (item.kind === undefined) {
- item.kind = "";
- }
- if (item.desc === undefined) {
- item.desc = "";
- }
- if (item.sup === undefined) {
- item.sup = "";
- }
-
- data.push.apply(data, [[
- item.name,
- item.oid,
- item.must.join(" "),
- item.may.join(" "),
- oc_btn,
- item.x_origin,
- oc_kind_opts[item.kind],
- item.desc,
- item.sup
- ]]);
- }
- // Update html table
- schema_oc_table = $('#oc-table').DataTable ({
- "data": data,
- "paging": true,
- "bAutoWidth": false,
- "dom":
'<"pull-left"f><"pull-right"l>tip',
- "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]],
- "language": {
- "emptyTable": "No objectclasses defined",
- "search": "Search Objectclasses"
- },
- "columnDefs": [ {
- "targets": 4,
- "orderable": false
- }, {
- "targets": 5,
- "visible": false
- }]
- });
-
- // Get syntaxes and use the data to populate the attribute's table
- cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id +
'.socket', 'schema', "attributetypes", 'get_syntaxes'];
- cockpit.spawn(cmd, { superuser: true, "err": "message",
"environ": [ENV]}).done(function(syntax_data) {
- var obj = JSON.parse(syntax_data);
- var syntax_list = [];
-
- load_schema_objects_to_select('matchingrules', 'attr-eq-mr-select',
schema_json);
- load_schema_objects_to_select('matchingrules',
'attr-order-mr-select', schema_json);
- load_schema_objects_to_select('matchingrules',
'attr-sub-mr-select', schema_json);
- load_schema_objects_to_select('attributetypes', 'schema-list',
schema_json);
- load_schema_objects_to_select('objectclasses', 'oc-parent',
schema_json);
- load_schema_objects_to_select('attributetypes', 'attr-parent',
schema_json);
-
- for (var i = 0; i < obj.items.length; i++) {
- item = obj.items[i];
- syntax_list.push.apply(syntax_list, [item]);
- }
- // Update syntax select html in attribute's edit window
- $.each(syntax_list, function (i, item) {
- $("#attr-syntax").append($('<option>', {
- value: item.id,
- text : item.name + " (" + item.id + ")"
- }));
- });
-
- var data = [];
- var syntax_name = "";
- for (var i = 0; i < schema_json.attributetypes.items.length; i++) {
- var attr_btn = attr_btn_html_only_view;
- item = schema_json.attributetypes.items[i];
- if (item.single_value) {
- multivalued = 'no';
- } else {
- multivalued = 'yes';
- }
- $.each(syntax_list, function (i, syntax) {
- if (syntax.id === item.syntax) {
- syntax_name = '<div title="' + syntax.name +
'">' + syntax.name + '</div>';
- }
- });
- // If attribute is user defined them the action button is enabled
- if (is_x_origin_user_defined(item.x_origin)) {
- attr_btn = attr_btn_html;
- }
- // Validate all params
- if (item.oid === undefined) {
- item.oid = "";
- }
- if (item.sup === undefined) {
- item.sup = "";
- }
- if (item.x_origin === undefined) {
- item.x_origin = "";
- }
- if (item.no_user_mod === undefined) {
- item.no_user_mod = "";
- }
- if (item.desc === undefined) {
- item.desc = "";
- }
- if (item.usage === undefined) {
- item.usage = "";
- }
- if (item.aliases === undefined) {
- item.aliases = "";
- }
- if (item.equality === undefined) {
- item.equality = "";
- }
- if (item.ordering === undefined) {
- item.ordering = "";
- }
- if (item.substr === undefined) {
- item.substr = "";
- }
-
- data.push.apply(data, [[
- item.name,
- item.oid,
- syntax_name,
- multivalued,
- attr_btn,
- item.desc,
- item.aliases,
- item.x_origin,
- attr_usage_opts[item.usage],
- item.no_user_mod,
- item.sup,
- item.equality,
- item.ordering,
- item.substr,
- ]]);
- }
- // Update html table
- schema_at_table = $('#attr-table').DataTable({
- "data": data,
- "paging": true,
- "bAutoWidth": false,
- "dom":
'<"pull-left"f><"pull-right"l>tip', // Moves the
search box to the left
- "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]],
- "language": {
- "emptyTable": "No attributes defined",
- "search": "Search Attributes"
- },
- "columnDefs": [ {
- "targets": 4,
- "orderable": false
- }, {
- "targets": 5,
- "visible": false
- }]
- });
- update_progress();
- }).fail(function(syntax_data) {
- console.log("Get syntaxes failed: " + syntax_data.message);
- check_inst_alive(1);
- });
-
- var data = [];
- for (var i = 0; i < schema_json.matchingrules.items.length; i++) {
- item = schema_json.matchingrules.items[i];
- data.push.apply(data, [[
- item.name,
- item.oid,
- item.syntax,
- item.desc]]);
- }
- schema_mr_table = $('#schema-mr-table').DataTable({
- "paging": true,
- "data": data,
- "bAutoWidth": false,
- "dom":
'<"pull-left"f><"pull-right"l>tip',
- "language": {
- "emptyTable": "No matching rules defined",
- "search": "Search Matching Rules"
- },
- "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]],
- });
-
- console.log("Finished loading schema.");
- update_progress();
- }).fail(function(oc_data) {
- console.log("Get all schema objects failed: " + oc_data.message);
- check_inst_alive(1);
- });
-}
-
-$(document).ready( function() {
- // Set an interval event to wait for all the pages to load, then load the config
- $("#schema-content").load("schema.html", function (){
- // Sort schema list awhile
- sort_list( $("#schema-list") );
-
- $("#objectclass-btn").on("click", function() {
- $(".all-pages").hide();
- $("#schema-content").show();
- $("#objectclass-page").show();
- });
- $("#attribute-btn").on("click", function() {
- $(".all-pages").hide();
- $("#schema-content").show();
- $("#attribute-page").show();
- });
- $("#schema-mr-btn").on("click", function() {
- $(".all-pages").hide();
- $("#schema-content").show();
- $("#schema-mr").show();
- });
-
- $('#attr-user-defined').change(function() {
- schema_at_table.draw();
- });
- $('#oc-user-defined').change(function() {
- schema_oc_table.draw();
- });
-
- //
- // Modals/Forms
- //
-
- /*
- *
- * Add Objectclass Form
- *
- */
- $("#add-oc-button").on("click", function() {
- clear_oc_form();
- document.getElementById("oc-parent").value = 'top';
- });
-
- $("#save-oc-button").on("click", function() {
- var oc_name = $("#oc-name").val();
- var oc_oid = $("#oc-oid").val();
- var oc_parent = $("#oc-parent").val();
- var oc_kind = $("#oc-kind").val();
- var oc_desc = $("#oc-desc").val();
- var oc_x_origin = "user defined";
- var oc_required_list = $('#oc-required-list option').map(function() {
return $(this).val(); }).get();
- var oc_allowed_list = $('#oc-allowed-list option').map(function() { return
$(this).val(); }).get();
-
- var action = 'add';
- var edit = false;
- if ( $("#add-edit-oc-header").text().indexOf("Edit
Objectclass") != -1){
- edit = true;
- action = 'replace';
- }
- if (oc_name == '') {
- report_err($("#oc-name"), 'You must provide an objectClass
name');
- return;
- }
- var cmd = [DSCONF, server_inst, 'schema', 'objectclasses', action,
oc_name];
- // Process and validate parameters
- if (oc_oid != "") {
- cmd.push.apply(cmd, ["--oid", oc_oid]);
- }
- if (oc_parent != "") {
- cmd.push.apply(cmd, ["--sup", oc_parent]);
- }
- if (oc_kind != "") {
- cmd.push.apply(cmd, ["--kind", oc_kind]);
- }
- if (oc_desc != "") {
- cmd.push.apply(cmd, ["--desc", oc_desc]);
- }
- if (oc_x_origin != "") {
- cmd.push.apply(cmd, ["--x-origin=\"" + oc_x_origin +
"\""]);
- }
- if (oc_required_list.length !== 0) {
- cmd.push.apply(cmd, ["--must"]);
- cmd.push.apply(cmd, oc_required_list);
- }
- if (oc_allowed_list.length !== 0) {
- cmd.push.apply(cmd, ["--may"]);
- cmd.push.apply(cmd, oc_allowed_list);
- }
-
- $("#save-oc-spinner").show();
- log_cmd('#save-oc-button (click)', 'Save objectclasses', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message",
"environ": [ENV]}).
- done(function(data) {
- $("#oc-name").attr('disabled', false);
-
- // Update html table (if edit: delete old then add new)
- if ( edit ) {
- var selector = $('tr:contains(' + oc_name + ')');
- schema_oc_table.row(selector).remove().draw(false);
- }
- var cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id +
'.socket', 'schema', 'objectclasses', 'query', oc_name];
- log_cmd('#save-oc-button (click)', 'Search objectclasses', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message",
"environ": [ENV]}).
- done(function(oc_data) {
- var obj = JSON.parse(oc_data);
- var item = obj.oc;
- schema_oc_table.row.add( [
- item.name,
- item.oid,
- item.must.join(" "),
- item.may.join(" "),
- oc_btn_html,
- item.x_origin,
- oc_kind_opts[item.kind],
- item.desc,
- item.sup
- ] ).draw( false );
- }).
- fail(function(oc_data) {
- popup_err("err", oc_data.message);
- console.log("Search objectclasses failed: " + oc_data.message);
- check_inst_alive(1);
- });
- // Replace the option in 'Edit objectClass' window
- if (!edit) {
- var option = $('<option></option>').attr("value",
oc_name).text(oc_name);
- $("#oc-parent").append(option);
- }
- $("#save-oc-spinner").hide();
- popup_success("The objectClass was saved in DS");
- $("#add-edit-oc-form").modal('toggle');
- }).
- fail(function(data) {
- $("#save-oc-spinner").hide();
- popup_err("Error", "Failed to save the objectClass\n" +
data.message);
- $("#add-edit-oc-form").modal('toggle');
- });
- });
-
- // Required Attributes
- $("#oc-must-add-button").on("click", function () {
- var add_attrs = $("#schema-list").val();
- if (add_attrs && add_attrs != '' && add_attrs.length >
0) {
- for (var i = 0; i < add_attrs.length; i++) {
- if ( $('#oc-required-list option[value="' + add_attrs[i] +
'"]').val() === undefined) {
-
$('#oc-required-list').append($("<option/>").val(add_attrs[i]).text(add_attrs[i]));
- }
- }
- $("#schema-list").find('option:selected').remove();
- }
- });
- $("#oc-must-remove-button").on("click", function () {
- var add_attrs = $("#oc-required-list").find('option:selected');
- if (add_attrs && add_attrs != '' && add_attrs.length >
0) {
- for (var i = 0; i < add_attrs.length; i++) {
- if ( $('#schema-list option[value="' + add_attrs[i].text +
'"]').val() === undefined) {
-
$('#schema-list').append($("<option/>").val(add_attrs[i].text).text(add_attrs[i].text));
- }
- }
- }
- $("#oc-required-list").find('option:selected').remove();
- sort_list( $("#schema-list") );
- });
-
- // Allowed Attributes
- $("#oc-may-add-button").on("click", function () {
- var add_attrs = $("#schema-list").val();
- if (add_attrs && add_attrs != '' && add_attrs.length >
0) {
- for (var i = 0; i < add_attrs.length; i++) {
- if ( $('#oc-allowed-list option[value="' + add_attrs[i] +
'"]').val() === undefined) {
-
$('#oc-allowed-list').append($("<option/>").val(add_attrs[i]).text(add_attrs[i]));
- }
- }
- $("#schema-list").find('option:selected').remove();
- }
- });
- $("#oc-may-remove-button").on("click", function () {
- var add_attrs = $("#oc-allowed-list").find('option:selected');
- if (add_attrs && add_attrs != '' && add_attrs.length >
0) {
- for (var i = 0; i < add_attrs.length; i++) {
- if ( $('#schema-list option[value="' + add_attrs[i].text +
'"]').val() === undefined) {
-
$('#schema-list').append($("<option/>").val(add_attrs[i].text).text(add_attrs[i].text));
- }
- }
- }
- $("#oc-allowed-list").find('option:selected').remove();
- sort_list( $("#schema-list") );
- });
-
- /*
- *
- * Add Attribute Form
- *
- */
- $("#create-attr-button").on("click", function() {
- clear_attr_form();
- });
-
- $("#save-attr-button").on("click", function() {
- var attr_name = $("#attr-name").val();
- var attr_oid = $("#attr-oid").val();
- var attr_syntax = $("#attr-syntax").val();
- var attr_syntax_text = $("#attr-syntax :selected").text();
- var attr_usage = $('#attr-usage').val();
- var attr_desc = $('#attr-desc').val();
- var attr_x_origin = "user defined";
- var attr_parent = $('#attr-parent').val();
- var attr_aliases = $('#attr-alias').val().split(" ");
- var eq_mr= $('#attr-eq-mr-select').val();
- var order_mr = $('#attr-order-mr-select').val();
- var sub_mr = $('#attr-sub-mr-select').val();
- var multiple = 'no';
- if ( $("#attr-multivalued").is(":checked") ) {
- multiple = 'yes';
- }
- var no_user_mod = false;
- if ( $("#attr-no-user-mod").is(":checked") ) {
- no_user_mod = true;
- }
- var action = 'add';
- var edit = false;
- if ( $("#add-edit-attr-header").text().indexOf("Edit
Attribute") != -1){
- edit = true;
- action = 'replace';
- }
-
- if (attr_name == '') {
- report_err($("#attr-name"), 'You must provide an attribute
name');
- return;
- }
- if (attr_syntax == '') {
- report_err($("#attr-syntax"), 'You must provide an attribute
syntax');
- return;
- }
-
- var cmd = [DSCONF, server_inst, 'schema', 'attributetypes', action,
attr_name];
- // Process and validate parameters
- if (attr_aliases) {
- cmd.push.apply(cmd, ["--aliases"]);
- cmd.push.apply(cmd, attr_aliases);
- }
- if (attr_syntax) {
- cmd.push.apply(cmd, ["--syntax", attr_syntax]);
- }
- if (multiple == 'no') {
- cmd.push.apply(cmd, ["--single-value"]);
- } else {
- cmd.push.apply(cmd, ["--multi-value"]);
- }
- if (no_user_mod) {
- cmd.push.apply(cmd, ["--no-user-mod"]);
- } else {
- cmd.push.apply(cmd, ["--user-mod"]);
- }
- cmd.push.apply(cmd, ["--oid", attr_oid]);
- cmd.push.apply(cmd, ["--usage", attr_usage]);
- cmd.push.apply(cmd, ["--sup", attr_parent]);
- cmd.push.apply(cmd, ["--desc", attr_desc]);
- cmd.push.apply(cmd, ["--x-origin", attr_x_origin]);
- cmd.push.apply(cmd, ["--equality"]);
- if (eq_mr) {
- cmd.push.apply(cmd, [eq_mr]);
- } else {
- cmd.push.apply(cmd, [""]);
- }
- cmd.push.apply(cmd, ["--substr"]);
- if (sub_mr) {
- cmd.push.apply(cmd, [sub_mr]);
- } else {
- cmd.push.apply(cmd, [""]);
- }
- cmd.push.apply(cmd, ["--ordering"]);
- if (order_mr) {
- cmd.push.apply(cmd, [order_mr]);
- } else {
- cmd.push.apply(cmd, [""]);
- }
- $("#save-attr-spinner").show();
- log_cmd('#save-attr-button (click)', 'Save attribute', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message",
"environ": [ENV]}).
- done(function(data) {
- var attr_syntax_name = '<div title="' + attr_syntax +
'">' +
- attr_syntax_text.substr(0, attr_syntax_text.indexOf("
(")) + '</div>';
- $("#attr-name").attr('disabled', false);
- // Update html table (if edit: delete old then add new)
- if ( edit ) {
- var selector = $('tr:contains(' + attr_name + ')');
- schema_at_table.row(selector).remove().draw(false);
- }
- var cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id +
'.socket', 'schema', 'attributetypes', 'query',
attr_name];
- log_cmd('#save-oc-button (click)', 'Get attribute', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message",
"environ": [ENV]}).
- done(function(at_data) {
- var obj = JSON.parse(at_data);
- var item = obj.at;
- schema_at_table.row.add( [
- item.name,
- item.oid,
- attr_syntax_name,
- multiple,
- attr_btn_html,
- item.desc,
- item.aliases,
- item.x_origin,
- attr_usage_opts[item.usage],
- item.no_user_mod,
- item.sup,
- item.equality,
- item.ordering,
- item.substr,
-
- ] ).draw( false );
- $("#attr-name").attr('disabled', false);
- }).
- fail(function(at_data) {
- popup_err("err", at_data.message);
- console.log("Query attributes failed: " + at_data.message);
- check_inst_alive(1);
- });
- if (!edit) {
- var option = $('<option></option>').attr("value",
attr_name).text(attr_name);
- $("#schema-list").append(option);
- }
- $("#save-attr-spinner").hide();
- popup_success("The attribute was saved in DS");
- $("#add-edit-attr-form").modal('toggle');
- }).
- fail(function(data) {
- $("#save-attr-spinner").hide();
- popup_err("Error", "Failed to save the attribute: " +
data.message);
- $("#add-edit-attr-form").modal('toggle');
- });
- });
-
- function load_attr_form(element) {
- clear_attr_form();
- var data = schema_at_table.row(element.parents('tr') ).data();
- var edit_attr_name = data[0];
- var edit_attr_oid = data[1];
- var edit_attr_syntax = $.parseHTML(data[2])[0].title;
- var edit_attr_multivalued = data[3];
- var edit_attr_desc = data[5];
- var edit_attr_aliases = data[6];
- var edit_attr_x_origin = data[7];
- var edit_attr_usage = data[8];
- var edit_attr_no_user_mod = data[9];
- var edit_attr_parent = data[10];
- var edit_attr_eq_mr = data[11];
- var edit_attr_order_mr = data[12];
- var edit_attr_sub_mr = data[13];
-
- $("#add-edit-attr-header").html('Edit Attribute: ' +
edit_attr_name);
- $("#attr-name").val(edit_attr_name);
- $("#attr-name").attr('disabled', true);
- $("#attr-oid").val(edit_attr_oid);
- $("#attr-usage")[0].value = edit_attr_usage;
- $("#attr-parent")[0].value = edit_attr_parent;
- $("#attr-desc").val(edit_attr_desc);
- if (edit_attr_aliases) {
- $("#attr-alias").val(edit_attr_aliases.join(" "));
- }
- $("#attr-syntax").val(edit_attr_syntax);
- $("#attr-multivalued").prop('checked', false);
- if (edit_attr_multivalued == "yes") {
- $("#attr-multivalued").prop('checked', true);
- }
- $("#attr-no-user-mod").prop('checked', false);
- if (edit_attr_no_user_mod) {
- $("#attr-no-user-mod").prop('checked', true);
- }
- $("#save-attr-spinner").show();
- $("#attr-eq-mr-select")[0].value = edit_attr_eq_mr;
- $("#attr-order-mr-select")[0].value = edit_attr_order_mr;
- $("#attr-sub-mr-select")[0].value = edit_attr_sub_mr;
- $("#save-attr-spinner").hide();
-
- $("#add-edit-attr-form").modal('toggle');
- }
-
- function load_view_attr_form(element) {
- clear_attr_form();
- var data = schema_at_table.row(element.parents('tr') ).data();
- var edit_attr_name = data[0];
- var edit_attr_oid = data[1];
- var edit_attr_syntax = $.parseHTML(data[2])[0].title;
- var edit_attr_multivalued = data[3];
- var edit_attr_desc = data[5];
- var edit_attr_aliases = data[6];
- var edit_attr_x_origin = data[7];
- var edit_attr_usage = data[8];
- var edit_attr_no_user_mod = data[9];
- var edit_attr_parent = data[10];
- var edit_attr_eq_mr = data[11];
- var edit_attr_order_mr = data[12];
- var edit_attr_sub_mr = data[13];
-
- $("#attr-name-view").val(edit_attr_name);
- $("#attr-oid-view").val(edit_attr_oid);
- $("#attr-usage-view")[0].value = edit_attr_usage;
- $("#attr-parent-view")[0].value = edit_attr_parent;
- $("#attr-desc-view").val(edit_attr_desc);
- if (edit_attr_aliases) {
- $("#attr-alias-view").val(edit_attr_aliases.join(" "));
- }
- $("#attr-syntax-view").val(edit_attr_syntax);
- $("#attr-multivalued-view").prop('checked', false);
- if (edit_attr_multivalued == "yes") {
- $("#attr-multivalued-view").prop('checked', true);
- }
- $("#attr-no-user-mod-view").prop('checked', false);
- if (edit_attr_no_user_mod) {
- $("#attr-no-user-mod-view").prop('checked', true);
- }
- $("#attr-eq-mr-select-view").val(edit_attr_eq_mr);
- $("#attr-order-mr-select-view").val(edit_attr_order_mr);
- $("#attr-sub-mr-select-view").val(edit_attr_sub_mr);
-
- $("#view-attr-form").modal('toggle');
- }
-
- $(document).on('click', '.attr-view-btn', function(e) {
- e.preventDefault();
- load_view_attr_form($(this));
- });
-
- $(document).on('click', '.attr-edit-btn', function(e) {
- e.preventDefault();
- load_attr_form($(this));
- });
-
- $(document).on('click', '.attr-del-btn', function(e) {
- e.preventDefault();
- var data = schema_at_table.row( $(this).parents('tr') ).data();
- var del_attr_name = data[0];
- var at_row = $(this);
- popup_confirm("Are you sure you want to delete attribute: <b>" +
del_attr_name + "</b>", "Confirmation", function (yes) {
- if (yes) {
- var cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id
+ '.socket', 'schema', 'attributetypes', 'remove',
del_attr_name];
- log_cmd('.attr-del-btn (click)', 'Remove attribute', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message",
"environ": [ENV]}).done(function(data) {
- popup_success("Attribute was successfully removed!");
- schema_at_table.row( at_row.parents('tr') ).remove().draw( false );
- $("#schema-list option[value='" + del_attr_name +
"']").remove();
- }).fail(function(data) {
- popup_err("Attribute removal error", del_attr_name + " removal
has failed: " + data.message);
- });
- }
- });
- });
-
- function load_view_oc_form(element) {
- clear_oc_form();
- var data = schema_oc_table.row(element.parents('tr') ).data();
- var edit_oc_name = data[0];
- var edit_oc_oid = data[1];
- var edit_oc_required = data[2].split(" ");
- var edit_oc_allowed = data[3].split(" ");
- var edit_oc_x_origin = data[5];
- var edit_oc_kind = data[6];
- var edit_oc_desc = data[7];
- var edit_oc_parent = data[8];
-
- $("#oc-name-view").val(edit_oc_name);
- $("#oc-oid-view").val(edit_oc_oid);
- $("#oc-kind-view")[0].value = edit_oc_kind;
- $("#oc-desc-view").val(edit_oc_desc);
- $("#oc-parent-view")[0].value = edit_oc_parent;
- $.each(edit_oc_required, function (i, item) {
- if (item) {
- $("#oc-required-list-view").append($('<option>', {
- value: item,
- text : item
- }));
- }
- });
- $.each(edit_oc_allowed, function (i, item) {
- if (item) {
- $("#oc-allowed-list-view").append($('<option>', {
- value: item,
- text : item
- }));
- }
- });
-
- // Update modal html header and fields and show()
- $("#view-objectclass-form").modal('toggle');
- }
-
- function load_oc_form(element) {
- clear_oc_form();
- var data = schema_oc_table.row(element.parents('tr') ).data();
- var edit_oc_name = data[0];
- var edit_oc_oid = data[1];
- var edit_oc_required = data[2].split(" ");
- var edit_oc_allowed = data[3].split(" ");
- var edit_oc_x_origin = data[5];
- var edit_oc_kind = data[6];
- var edit_oc_desc = data[7];
- var edit_oc_parent = data[8];
-
- $("#save-oc-spinner").show();
- $("#add-edit-oc-header").html('Edit Objectclass: ' +
edit_oc_name);
- $("#oc-name").attr('disabled', true);
- $("#oc-name").val(edit_oc_name);
- $("#oc-oid").val(edit_oc_oid);
- $("#oc-kind").val(edit_oc_kind);
- $("#oc-desc").val(edit_oc_desc);
- $("#oc-parent").val(edit_oc_parent);
- $.each(edit_oc_required, function (i, item) {
- if (item) {
- $("#oc-required-list").append($('<option>', {
- value: item,
- text : item
- }));
- }
- });
- $.each(edit_oc_allowed, function (i, item) {
- if (item) {
- $("#oc-allowed-list").append($('<option>', {
- value: item,
- text : item
- }));
- }
- });
- $("#save-oc-spinner").hide();
-
- // Update modal html header and fields and show()
- $("#add-edit-oc-form").modal('toggle');
- }
-
- $(document).on('click', '.oc-view-btn', function(e) {
- e.preventDefault();
- load_view_oc_form($(this));
- });
-
- $(document).on('click', '.oc-edit-btn', function(e) {
- e.preventDefault();
- load_oc_form($(this));
- });
-
- $(document).on('click', '.oc-del-btn', function(e) {
- e.preventDefault();
- var data = schema_oc_table.row( $(this).parents('tr') ).data();
- var del_oc_name = data[0];
- var oc_row = $(this);
-
- popup_confirm("Are you sure you want to delete objectclass: <b>" +
del_oc_name + "</b>", "Confirmation", function (yes) {
- if (yes) {
- var cmd = [DSCONF, '-j', 'ldapi://%2fvar%2frun%2f' + server_id
+ '.socket', 'schema', 'objectclasses', 'remove',
del_oc_name];
- log_cmd('.oc-del-btn (click)', 'Remove objectclass', cmd);
- cockpit.spawn(cmd, { superuser: true, "err": "message",
"environ": [ENV]}).done(function(data) {
- popup_success("ObjectClass was successfully removed!");
- schema_oc_table.row( oc_row.parents('tr') ).remove().draw( false );
- $("#oc-parent option[value='" + del_oc_name +
"']").remove();
- }).fail(function(data) {
- popup_err("Error", del_oc_name + " removal has failed: "
+ data.message);
- });
- }
- });
- });
- // Page is loaded, mark it as so...
- schema_page_loaded = 1;
- });
-});
diff --git a/src/cockpit/389-console/src/schema.jsx
b/src/cockpit/389-console/src/schema.jsx
new file mode 100644
index 0000000..7e6ade6
--- /dev/null
+++ b/src/cockpit/389-console/src/schema.jsx
@@ -0,0 +1,1042 @@
+import cockpit from "cockpit";
+import React from "react";
+import { NotificationController } from "./lib/notifications.jsx";
+import { log_cmd, searchFilter } from "./lib/tools.jsx";
+import {
+ ObjectClassesTable,
+ AttributesTable,
+ MatchingRulesTable
+} from "./lib/schema/schemaTables.jsx";
+import { ObjectClassModal, AttributeTypeModal } from
"./lib/schema/schemaModals.jsx";
+import {
+ Nav,
+ NavItem,
+ Checkbox,
+ TabContainer,
+ TabContent,
+ TabPane,
+ Spinner,
+ Button
+} from "patternfly-react";
+import PropTypes from "prop-types";
+import "./css/ds.css";
+
+export class Schema extends React.Component {
+ componentWillMount() {
+ this.loadSyntaxesFirst();
+ }
+
+ componentDidUpdate(prevProps) {
+ if (this.props.serverId !== prevProps.serverId) {
+ this.loadSyntaxesFirst();
+ }
+ }
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ loading: false,
+ notifications: [],
+ activeKey: 1,
+
+ objectclassRows: [],
+ filteredObjectclassRows: [],
+ attributesRows: [],
+ filteredAttributesRows: [],
+ matchingrulesRows: [],
+ syntaxes: [],
+ attributes: [],
+ objectclasses: [],
+ matchingrules: [],
+
+ ocModalViewOnly: false,
+ ocName: "",
+ ocDesc: "",
+ ocOID: "",
+ ocParent: [],
+ ocKind: "",
+ ocMust: [],
+ ocMay: [],
+ ocUserDefined: false,
+ objectclassModalShow: false,
+ newOcEntry: true,
+ ocTableLoading: false,
+ ocModalLoading: false,
+
+ atName: "",
+ atDesc: "",
+ atOID: "",
+ atParent: [],
+ atSyntax: [],
+ atUsage: "userApplications",
+ atMultivalued: false,
+ atNoUserMod: false,
+ atAlias: [],
+ atEqMr: [],
+ atOrder: [],
+ atSubMr: [],
+ atUserDefined: false,
+ atModalViewOnly: false,
+ attributeModalShow: false,
+ newAtEntry: true,
+ atTableLoading: false,
+ atModalLoading: false
+ };
+
+ this.handleFieldChange = this.handleFieldChange.bind(this);
+ this.addNotification = this.addNotification.bind(this);
+ this.removeNotification = this.removeNotification.bind(this);
+ this.handleNavSelect = this.handleNavSelect.bind(this);
+ this.handleTypeaheadChange = this.handleTypeaheadChange.bind(this);
+ this.loadSchemaData = this.loadSchemaData.bind(this);
+ this.loadSyntaxesFirst = this.loadSyntaxesFirst.bind(this);
+ this.toggleLoading = this.toggleLoading.bind(this);
+
+ this.showViewObjectclassModal = this.showViewObjectclassModal.bind(this);
+ this.showEditObjectclassModal = this.showEditObjectclassModal.bind(this);
+ this.showAddObjectclassModal = this.showAddObjectclassModal.bind(this);
+ this.openObjectclassModal = this.openObjectclassModal.bind(this);
+ this.closeObjectclassModal = this.closeObjectclassModal.bind(this);
+ this.deleteObjectclass = this.deleteObjectclass.bind(this);
+ this.addObjectclass = this.addObjectclass.bind(this);
+ this.editObjectclass = this.editObjectclass.bind(this);
+ this.cmdOperationObjectclass = this.cmdOperationObjectclass.bind(this);
+
+ this.showViewAttributeModal = this.showViewAttributeModal.bind(this);
+ this.showEditAttributeModal = this.showEditAttributeModal.bind(this);
+ this.showAddAttributeModal = this.showAddAttributeModal.bind(this);
+ this.openAttributeModal = this.openAttributeModal.bind(this);
+ this.closeAttributeModal = this.closeAttributeModal.bind(this);
+ this.deleteAttribute = this.deleteAttribute.bind(this);
+ this.addAttribute = this.addAttribute.bind(this);
+ this.editAttribute = this.editAttribute.bind(this);
+ this.cmdOperationAttribute = this.cmdOperationAttribute.bind(this);
+ }
+
+ toggleLoading(item) {
+ if (item == "allSchema") {
+ this.setState(prevState => ({
+ loading: !prevState.loading
+ }));
+ } else if (item == "ocTable") {
+ this.setState(prevState => ({
+ ocTableLoading: !prevState.ocTableLoading
+ }));
+ } else if (item == "ocModal") {
+ this.setState(prevState => ({
+ ocModalLoading: !prevState.ocModalLoading
+ }));
+ } else if (item == "atTable") {
+ this.setState(prevState => ({
+ atTableLoading: !prevState.atTableLoading
+ }));
+ } else if (item == "atModal") {
+ this.setState(prevState => ({
+ atModalLoading: !prevState.atModalLoading
+ }));
+ }
+ }
+
+ loadSyntaxesFirst() {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId +
".socket",
+ "schema",
+ "attributetypes",
+ "get_syntaxes"
+ ];
+ log_cmd("loadSyntaxes", "Get syntaxes for attributetypes",
cmd);
+ cockpit
+ .spawn(cmd, { superuser: true, err: "message" })
+ .done(content => {
+ let myObject = JSON.parse(content);
+ this.setState({
+ syntaxes: myObject.items
+ });
+ this.loadSchemaData(true);
+ })
+ .fail(err => {
+ if (err != 0) {
+ let errMsg = JSON.parse(err);
+ console.log("loadSyntaxes failed: ", errMsg.desc);
+ }
+ });
+ }
+
+ loadSchemaData(initialLoading) {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId +
".socket",
+ "schema",
+ "list"
+ ];
+ if (initialLoading) {
+ this.toggleLoading("allSchema");
+ }
+ log_cmd("loadSchemaData", "Get schema objects in one batch",
cmd);
+ cockpit
+ .spawn(cmd, { superuser: true, err: "message" })
+ .done(content => {
+ let myObject = JSON.parse(content);
+ let attrs = [];
+ let ocs = [];
+ let mrs = [];
+ for (let content of myObject.attributetypes.items) {
+ attrs.push({
+ id: content.name[0],
+ label: content.name[0]
+ });
+ }
+ for (let content of myObject.objectclasses.items) {
+ ocs.push({
+ id: content.name[0],
+ label: content.name[0]
+ });
+ }
+ for (let content of myObject.matchingrules.items) {
+ mrs.push({
+ id: content.name[0],
+ label: content.name[0]
+ });
+ }
+ this.setState({
+ objectclassRows: myObject.objectclasses.items,
+ attributesRows: myObject.attributetypes.items,
+ matchingrulesRows: myObject.matchingrules.items,
+ attributes: attrs,
+ matchingrules: mrs,
+ objectclasses: ocs
+ });
+ if (this.state.ocUserDefined) {
+ this.setState({
+ filteredObjectclassRows: searchFilter(
+ "user defined",
+ ["x_origin"],
+ myObject.objectclasses.items
+ )
+ });
+ } else {
+ this.setState({
+ filteredObjectclassRows: myObject.objectclasses.items
+ });
+ }
+ if (this.state.atUserDefined) {
+ this.setState({
+ filteredAttributesRows: searchFilter(
+ "user defined",
+ ["x_origin"],
+ myObject.attributetypes.items
+ )
+ });
+ } else {
+ this.setState({
+ filteredAttributesRows: myObject.attributetypes.items
+ });
+ }
+ if (initialLoading) {
+ this.toggleLoading("allSchema");
+ }
+ })
+ .fail(err => {
+ if (err != 0) {
+ let errMsg = JSON.parse(err);
+ console.log("loadSchemaData failed: ", errMsg.desc);
+ }
+ if (initialLoading) {
+ this.toggleLoading("allSchema");
+ }
+ });
+ }
+
+ showViewObjectclassModal(rowData) {
+ this.setState({
+ ocModalViewOnly: true
+ });
+ this.openObjectclassModal(rowData.name[0]);
+ }
+
+ showEditObjectclassModal(rowData) {
+ this.setState({
+ ocModalViewOnly: false
+ });
+ this.openObjectclassModal(rowData.name[0]);
+ }
+
+ showAddObjectclassModal(rowData) {
+ this.setState({
+ ocModalViewOnly: false
+ });
+ this.openObjectclassModal();
+ }
+
+ openObjectclassModal(name) {
+ if (!name) {
+ this.setState({
+ ocName: "",
+ ocDesc: "",
+ ocOID: "",
+ ocParent: [],
+ ocKind: "",
+ ocMust: [],
+ ocMay: [],
+ objectclassModalShow: true,
+ newOcEntry: true
+ });
+ } else {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId +
".socket",
+ "schema",
+ "objectclasses",
+ "query",
+ name
+ ];
+
+ this.toggleLoading("ocTable");
+ log_cmd("openObjectclassModal", "Fetch ObjectClass data from
schema", cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ let obj = JSON.parse(content);
+ let item = obj.oc;
+ let ocMustList = [];
+ let ocMayList = [];
+ const kindOpts = ["STRUCTURAL", "ABSTRACT",
"AUXILIARY"];
+ this.setState({
+ objectclassModalShow: true,
+ newOcEntry: false,
+ ocName: item["name"] === undefined ? "" :
item["name"][0],
+ ocDesc: item["desc"] === null ? "" :
item["desc"][0],
+ ocOID: item["oid"] === undefined ? "" :
item["oid"][0],
+ ocKind: item["kind"] === undefined ? "" :
kindOpts[item["kind"]],
+ ocParent:
+ item["sup"].length == 0
+ ? []
+ : [
+ {
+ id: item["sup"][0],
+ label: item["sup"][0]
+ }
+ ]
+ });
+ if (item["must"] === undefined) {
+ this.setState({ ocMust: [] });
+ } else {
+ for (let value of item["must"]) {
+ ocMustList = [...ocMustList, { id: value, label: value
}];
+ }
+ this.setState({
+ ocMust: ocMustList
+ });
+ }
+ if (item["may"] === undefined) {
+ this.setState({ ocMay: [] });
+ } else {
+ for (let value of item["may"]) {
+ ocMayList = [...ocMayList, { id: value, label: value }];
+ }
+ this.setState({
+ ocMay: ocMayList
+ });
+ }
+ this.toggleLoading("ocTable");
+ })
+ .fail(_ => {
+ this.setState({
+ ocName: "",
+ ocDesc: "",
+ ocOID: "",
+ ocParent: [],
+ ocKind: "",
+ ocMust: [],
+ ocMay: [],
+ objectclassModalShow: true,
+ newOcEntry: true
+ });
+ this.toggleLoading("ocTable");
+ });
+ }
+ }
+
+ closeObjectclassModal() {
+ this.setState({ objectclassModalShow: false });
+ }
+
+ deleteObjectclass(rowData) {
+ let name = rowData.name[0];
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId +
".socket",
+ "schema",
+ "objectclasses",
+ "remove",
+ name
+ ];
+
+ this.toggleLoading("ocTable");
+ log_cmd("deleteObjectclass", "Delete ObjectClass from
schema", cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ console.info("deleteObjectclass", "Result",
content);
+ this.addNotification("success", `ObjectClass ${name} was
successfully deleted`);
+ this.loadSchemaData();
+ this.toggleLoading("ocTable");
+ })
+ .fail(err => {
+ let errMsg = JSON.parse(err);
+ this.addNotification(
+ "error",
+ `Error during ObjectClass removal operation - ${errMsg.desc}`
+ );
+ this.loadSchemaData();
+ this.toggleLoading("ocTable");
+ });
+ }
+
+ addObjectclass() {
+ this.cmdOperationObjectclass("add");
+ }
+
+ editObjectclass() {
+ this.cmdOperationObjectclass("replace");
+ }
+
+ cmdOperationObjectclass(action) {
+ const { ocName, ocDesc, ocOID, ocParent, ocKind, ocMust, ocMay } = this.state;
+ if (ocName == "") {
+ this.addNotification("warning", "ObjectClass Name is
required.");
+ } else {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId +
".socket",
+ "schema",
+ "objectclasses",
+ action,
+ ocName
+ ];
+ // Process and validate parameters
+ if (ocOID != "") {
+ cmd = [...cmd, "--oid", ocOID];
+ }
+ if (ocParent.length != 0) {
+ cmd = [...cmd, "--sup", ocParent[0].label];
+ }
+ if (ocKind != "") {
+ cmd = [...cmd, "--kind", ocKind];
+ }
+ if (ocDesc != "") {
+ cmd = [...cmd, "--desc", ocDesc];
+ }
+ if (ocMust.length != 0) {
+ cmd = [...cmd, "--must"];
+ for (let value of ocMust) {
+ cmd = [...cmd, value.label];
+ }
+ }
+ if (ocMay.length != 0) {
+ cmd = [...cmd, "--may"];
+ for (let value of ocMay) {
+ cmd = [...cmd, value.label];
+ }
+ }
+
+ this.toggleLoading("ocModal");
+ log_cmd("cmdOperationObjectclass", `Do the ${action} operation on
ObjectClass`, cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ console.info("cmdOperationObjectclass",
"Result", content);
+ this.addNotification(
+ "success",
+ `ObjectClass ${ocName} - ${action} operation was
successfull`
+ );
+ this.loadSchemaData();
+ this.closeObjectclassModal();
+ this.toggleLoading("ocModal");
+ })
+ .fail(err => {
+ let errMsg = JSON.parse(err);
+ this.addNotification(
+ "error",
+ `Error during the ObjectClass ${action} operation -
${errMsg.desc}`
+ );
+ this.loadSchemaData();
+ this.closeObjectclassModal();
+ this.toggleLoading("ocModal");
+ });
+ }
+ }
+
+ showViewAttributeModal(rowData) {
+ this.setState({
+ atModalViewOnly: true
+ });
+ this.openAttributeModal(rowData.name[0]);
+ }
+
+ showEditAttributeModal(rowData) {
+ this.setState({
+ atModalViewOnly: false
+ });
+ this.openAttributeModal(rowData.name[0]);
+ }
+
+ showAddAttributeModal(rowData) {
+ this.setState({
+ atModalViewOnly: false
+ });
+ this.openAttributeModal();
+ }
+
+ openAttributeModal(name) {
+ if (!name) {
+ this.setState({
+ atName: "",
+ atDesc: "",
+ atOID: "",
+ atParent: [],
+ atSyntax: [],
+ atUsage: "userApplications",
+ atMultivalued: false,
+ atNoUserMod: false,
+ atAlias: [],
+ atEqMr: [],
+ atOrder: [],
+ atSubMr: [],
+ attributeModalShow: true,
+ newAtEntry: true
+ });
+ } else {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId +
".socket",
+ "schema",
+ "attributetypes",
+ "query",
+ name
+ ];
+
+ this.toggleLoading("atTable");
+ log_cmd("openAttributeModal", "Fetch Attribute data from
schema", cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ let obj = JSON.parse(content);
+ let item = obj.at;
+ let atAliasList = [];
+ const atUsageOpts = [
+ "userApplications",
+ "directoryOperation",
+ "distributedOperation",
+ "dSAOperation"
+ ];
+ this.setState({
+ attributeModalShow: true,
+ newAtEntry: false,
+ atName: item["name"] === undefined ? "" :
item["name"][0],
+ atDesc: item["desc"] === null ? "" :
item["desc"][0],
+ atOID: item["oid"] === undefined ? "" :
item["oid"][0],
+ atParent:
+ item["sup"].length == 0
+ ? []
+ : [
+ {
+ id: item["sup"][0],
+ label: item["sup"][0]
+ }
+ ],
+ atSyntax:
+ item["syntax"] === undefined
+ ? []
+ : [
+ {
+ id: item["syntax"][0],
+ label: this.state.syntaxes.filter(
+ attr => attr.id ===
item["syntax"][0]
+ )[0]["label"]
+ }
+ ],
+ atUsage: item["usage"] === undefined ? ""
: atUsageOpts[item["usage"]],
+ atMultivalued: !item["single_value"],
+ atNoUserMod: item["no_user_mod"],
+ atEqMr:
+ item["equality"] === null
+ ? []
+ : [
+ {
+ id: item["equality"][0],
+ label: item["equality"][0]
+ }
+ ],
+ atOrder:
+ item["ordering"] === null
+ ? []
+ : [
+ {
+ id: item["ordering"][0],
+ label: item["ordering"][0]
+ }
+ ],
+ atSubMr:
+ item["substr"] === null
+ ? []
+ : [
+ {
+ id: item["substr"][0],
+ label: item["substr"][0]
+ }
+ ]
+ });
+ if (item["aliases"] === null) {
+ this.setState({ atAlias: [] });
+ } else {
+ for (let value of item["aliases"]) {
+ atAliasList = [...atAliasList, { id: value, label: value
}];
+ }
+ this.setState({
+ atAlias: atAliasList
+ });
+ }
+ this.toggleLoading("atTable");
+ })
+ .fail(_ => {
+ this.setState({
+ atName: "",
+ atDesc: "",
+ atOID: "",
+ atParent: [],
+ atSyntax: [],
+ atUsage: "userApplications",
+ atMultivalued: false,
+ atNoUserMod: false,
+ atAlias: [],
+ atEqMr: [],
+ atOrder: [],
+ atSubMr: [],
+ attributeModalShow: true,
+ newAtEntry: true
+ });
+ this.toggleLoading("atTable");
+ });
+ }
+ }
+
+ closeAttributeModal() {
+ this.setState({ attributeModalShow: false });
+ }
+
+ deleteAttribute(rowData) {
+ let name = rowData.name[0];
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId +
".socket",
+ "schema",
+ "attributetypes",
+ "remove",
+ name
+ ];
+
+ this.toggleLoading("atTable");
+ log_cmd("deleteAttribute", "Delete Attribute from schema",
cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ console.info("deleteAttribute", "Result",
content);
+ this.addNotification("success", `Attribute ${name} was
successfully deleted`);
+ this.loadSchemaData();
+ this.toggleLoading("atTable");
+ })
+ .fail(err => {
+ let errMsg = JSON.parse(err);
+ this.addNotification(
+ "error",
+ `Error during Attribute removal operation - ${errMsg.desc}`
+ );
+ this.loadSchemaData();
+ this.toggleLoading("atTable");
+ });
+ }
+
+ addAttribute() {
+ this.cmdOperationAttribute("add");
+ }
+
+ editAttribute() {
+ this.cmdOperationAttribute("replace");
+ }
+
+ cmdOperationAttribute(action) {
+ const {
+ atName,
+ atDesc,
+ atOID,
+ atParent,
+ atSyntax,
+ atUsage,
+ atMultivalued,
+ atNoUserMod,
+ atAlias,
+ atEqMr,
+ atOrder,
+ atSubMr
+ } = this.state;
+
+ if (atName == "" || atSyntax.length == 0) {
+ this.addNotification("warning", "Attribute Name and Syntax are
required.");
+ } else {
+ let cmd = [
+ "dsconf",
+ "-j",
+ "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId +
".socket",
+ "schema",
+ "attributetypes",
+ action,
+ atName
+ ];
+ cmd = [...cmd, "--syntax", atSyntax[0].id];
+ if (atAlias.length != 0) {
+ cmd = [...cmd, "--aliases"];
+ for (let value of atAlias) {
+ cmd = [...cmd, value.label];
+ }
+ }
+ if (atMultivalued) {
+ cmd = [...cmd, "--multi-value"];
+ } else {
+ cmd = [...cmd, "--single-value"];
+ }
+ if (atNoUserMod) {
+ cmd = [...cmd, "--no-user-mod"];
+ } else {
+ cmd = [...cmd, "--user-mod"];
+ }
+ cmd = [...cmd, "--oid", atOID];
+ cmd = [...cmd, "--usage", atUsage];
+ cmd = [...cmd, "--desc", atDesc];
+
+ cmd = [...cmd, "--sup"];
+ if (atParent != "") {
+ cmd = [...cmd, atParent[0].label];
+ } else {
+ cmd = [...cmd, ""];
+ }
+
+ cmd = [...cmd, "--equality"];
+ if (atEqMr != "") {
+ cmd = [...cmd, atEqMr[0].label];
+ } else {
+ cmd = [...cmd, ""];
+ }
+
+ cmd = [...cmd, "--substr"];
+ if (atSubMr != "") {
+ cmd = [...cmd, atSubMr[0].label];
+ } else {
+ cmd = [...cmd, ""];
+ }
+
+ cmd = [...cmd, "--ordering"];
+ if (atOrder != "") {
+ cmd = [...cmd, atOrder[0].label];
+ } else {
+ cmd = [...cmd, ""];
+ }
+
+ this.toggleLoading("atModal");
+ log_cmd("cmdOperationAttribute", `Do the ${action} operation on
Attribute`, cmd);
+ cockpit
+ .spawn(cmd, {
+ superuser: true,
+ err: "message"
+ })
+ .done(content => {
+ console.info("cmdOperationAttribute",
"Result", content);
+ this.addNotification(
+ "success",
+ `Attribute ${atName} - ${action} operation was successfull`
+ );
+ this.loadSchemaData();
+ this.closeAttributeModal();
+ this.toggleLoading("atModal");
+ })
+ .fail(err => {
+ let errMsg = JSON.parse(err);
+ this.addNotification(
+ "error",
+ `Error during the Attribute ${action} operation -
${errMsg.desc}`
+ );
+ this.loadSchemaData();
+ this.closeAttributeModal();
+ this.toggleLoading("atModal");
+ });
+ }
+ }
+
+ 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
+ )
+ });
+ }
+
+ handleNavSelect(key) {
+ this.setState({
+ activeKey: key
+ });
+ }
+
+ handleTypeaheadChange(state, values) {
+ this.setState({
+ [state]: values
+ });
+ }
+
+ handleFieldChange(e) {
+ const value = e.target.type === "checkbox" ? e.target.checked :
e.target.value;
+ if (e.target.id == "ocUserDefined" && value) {
+ this.setState({
+ filteredObjectclassRows: searchFilter(
+ "user defined",
+ ["x_origin"],
+ this.state.objectclassRows
+ )
+ });
+ } else {
+ this.setState({
+ filteredObjectclassRows: this.state.objectclassRows
+ });
+ }
+ if (e.target.id == "atUserDefined" && value) {
+ this.setState({
+ filteredAttributesRows: searchFilter(
+ "user defined",
+ ["x_origin"],
+ this.state.attributesRows
+ )
+ });
+ } else {
+ this.setState({
+ filteredAttributesRows: this.state.attributesRows
+ });
+ }
+ this.setState({
+ [e.target.id]: value
+ });
+ }
+
+ render() {
+ let schemaPage = "";
+ if (this.state.loading) {
+ schemaPage = (
+ <div className="ds-loading-spinner ds-center">
+ <p />
+ <h4>Loading schema information ...</h4>
+ <Spinner loading size="md" />
+ </div>
+ );
+ } else {
+ schemaPage = (
+ <div className="container-fluid">
+ <NotificationController
+ notifications={this.state.notifications}
+ removeNotificationAction={this.removeNotification}
+ />
+ <div className="ds-tab-table">
+ <TabContainer
+ id="basic-tabs-pf"
+ onSelect={this.handleNavSelect}
+ activeKey={this.state.activeKey}
+ >
+ <div>
+ <Nav bsClass="nav nav-tabs nav-tabs-pf">
+ <NavItem eventKey={1}>
+ <div
+ dangerouslySetInnerHTML={{ __html:
"Objectclasses" }}
+ />
+ </NavItem>
+ <NavItem eventKey={2}>
+ <div dangerouslySetInnerHTML={{ __html:
"Attributes" }} />
+ </NavItem>
+ <NavItem eventKey={3}>
+ <div
+ dangerouslySetInnerHTML={{ __html:
"Matching Rules" }}
+ />
+ </NavItem>
+ </Nav>
+ <TabContent>
+ <TabPane eventKey={1}>
+ <div className="ds-margin-top-xlg
ds-indent">
+ <Checkbox
+ id="ocUserDefined"
+ checked={this.state.ocUserDefined}
+ title="Show only the objectclasses
that are defined by a user"
+ onChange={this.handleFieldChange}
+ >
+ Only Non-standard Schema (objectClasses
with
+ X-ORIGIN: "user defined")
+ </Checkbox>
+ <hr />
+ <ObjectClassesTable
+
rows={this.state.filteredObjectclassRows}
+
viewModalHandler={this.showViewObjectclassModal}
+
editModalHandler={this.showEditObjectclassModal}
+ deleteHandler={this.deleteObjectclass}
+ loading={this.state.ocTableLoading}
+ />
+ <Button
+ className="ds-margin-top"
+ bsStyle="primary"
+ onClick={this.showAddObjectclassModal}
+ >
+ Add ObjectClass
+ </Button>
+ <ObjectClassModal
+ addHandler={this.addObjectclass}
+ editHandler={this.editObjectclass}
+ newOcEntry={this.state.newOcEntry}
+
ocModalViewOnly={this.state.ocModalViewOnly}
+
handleTypeaheadChange={this.handleTypeaheadChange}
+
handleFieldChange={this.handleFieldChange}
+ objectclasses={this.state.objectclasses}
+ attributes={this.state.attributes}
+ ocName={this.state.ocName}
+ ocDesc={this.state.ocDesc}
+ ocOID={this.state.ocOID}
+ ocParent={this.state.ocParent}
+ ocKind={this.state.ocKind}
+ ocMust={this.state.ocMust}
+ ocMay={this.state.ocMay}
+ objectclassModalShow={
+ this.state.objectclassModalShow
+ }
+ closeModal={this.closeObjectclassModal}
+ loading={this.state.ocModalLoading}
+ />
+ </div>
+ </TabPane>
+
+ <TabPane eventKey={2}>
+ <div className="ds-margin-top-xlg
ds-indent">
+ <Checkbox
+ id="atUserDefined"
+ checked={this.state.atUserDefined}
+ title="Show only the attributes that
are defined by a user"
+ onChange={this.handleFieldChange}
+ >
+ Only Non-standard Schema (attributes with
X-ORIGIN:
+ "user defined")
+ </Checkbox>
+ <hr />
+ <AttributesTable
+ rows={this.state.filteredAttributesRows}
+
viewModalHandler={this.showViewAttributeModal}
+
editModalHandler={this.showEditAttributeModal}
+ deleteHandler={this.deleteAttribute}
+ syntaxes={this.state.syntaxes}
+ loading={this.state.atTableLoading}
+ />
+ <Button
+ className="ds-margin-top"
+ bsStyle="primary"
+ onClick={this.showAddAttributeModal}
+ >
+ Add Attribute
+ </Button>
+ <AttributeTypeModal
+ addHandler={this.addAttribute}
+ editHandler={this.editAttribute}
+ newAtEntry={this.state.newAtEntry}
+
atModalViewOnly={this.state.atModalViewOnly}
+
handleTypeaheadChange={this.handleTypeaheadChange}
+
handleFieldChange={this.handleFieldChange}
+ objectclasses={this.state.objectclasses}
+ attributes={this.state.attributes}
+ matchingrules={this.state.matchingrules}
+ syntaxes={this.state.syntaxes}
+ atName={this.state.atName}
+ atDesc={this.state.atDesc}
+ atOID={this.state.atOID}
+ atParent={this.state.atParent}
+ atSyntax={this.state.atSyntax}
+ atUsage={this.state.atUsage}
+ atMultivalued={this.state.atMultivalued}
+ atNoUserMod={this.state.atNoUserMod}
+ atAlias={this.state.atAlias}
+ atEqMr={this.state.atEqMr}
+ atOrder={this.state.atOrder}
+ atSubMr={this.state.atSubMr}
+
attributeModalShow={this.state.attributeModalShow}
+ closeModal={this.closeAttributeModal}
+ loading={this.state.atModalLoading}
+ />
+ </div>
+ </TabPane>
+
+ <TabPane eventKey={3}>
+ <div className="ds-margin-top-xlg
ds-indent">
+ <MatchingRulesTable
+ rows={this.state.matchingrulesRows}
+ />
+ </div>
+ </TabPane>
+ </TabContent>
+ </div>
+ </TabContainer>
+ </div>
+ </div>
+ );
+ }
+ return <div>{schemaPage}</div>;
+ }
+}
+
+// Props and defaultProps
+
+Schema.propTypes = {
+ serverId: PropTypes.string
+};
+
+Schema.defaultProps = {
+ serverId: ""
+};
+
+export default Schema;
diff --git a/src/cockpit/389-console/webpack.config.js
b/src/cockpit/389-console/webpack.config.js
index f32e518..d3d766b 100644
--- a/src/cockpit/389-console/webpack.config.js
+++ b/src/cockpit/389-console/webpack.config.js
@@ -30,8 +30,6 @@ var info = {
"fonts",
"images",
"index.html",
- "schema.html",
- "schema.js",
"servers.html",
"servers.js",
"static",
diff --git a/src/lib389/lib389/schema.py b/src/lib389/lib389/schema.py
index 2a29a01..00443ff 100755
--- a/src/lib389/lib389/schema.py
+++ b/src/lib389/lib389/schema.py
@@ -110,7 +110,7 @@ class Schema(DSLdapObject):
if json:
attr_syntaxes_list = []
for id, name in ATTR_SYNTAXES.items():
- attr_syntaxes_list.append({'name': name, 'id': id})
+ attr_syntaxes_list.append({'label': name, 'id': id})
result = {'type': 'list', 'items':
attr_syntaxes_list}
else:
result = ATTR_SYNTAXES
@@ -129,7 +129,7 @@ class Schema(DSLdapObject):
obj_i = vars(object_model(obj))
if len(obj_i["names"]) == 1:
obj_i['name'] = obj_i['names'][0].lower()
- obj_i['aliases'] = ""
+ obj_i['aliases'] = None
elif len(obj_i["names"]) > 1:
obj_i['name'] = obj_i['names'][0].lower()
obj_i['aliases'] = obj_i['names'][1:]
@@ -153,6 +153,12 @@ class Schema(DSLdapObject):
object_insts.append(obj_i)
object_insts = sorted(object_insts, key=itemgetter('name'))
+ # Ensure that the string values are in list so we can use React filter
component with it
+ for obj_i in object_insts:
+ for key, value in obj_i.items():
+ if isinstance(value, str):
+ obj_i[key] = (value, )
+
return {'type': 'list', 'items': object_insts}
else:
object_insts = [object_model(obj_i) for obj_i in results]
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.