Browse Source

Fixes #5 class container style

isundil 1 year ago
parent
commit
00b368d33e
7 changed files with 199 additions and 166 deletions
  1. 173 157
      public/javascripts/entity.js
  2. 4 0
      routes/entity.ts
  3. 8 0
      src/LDAPSchema.ts
  4. 3 1
      views/category.pug
  5. 7 4
      views/entity.pug
  6. 2 2
      views/index.pug
  7. 2 2
      views/layout.pug

+ 173 - 157
public/javascripts/entity.js

@@ -1,180 +1,196 @@
 ((dn, schema, inputs, ldifOutput, classContainer, addClassSelect, addClassBtn) => {
-	let changes = [],
-		multipleValues = {},
-		maxInputId = 0,
-		newClasses = {},
-		attributeCount = {};
+    let changes = [],
+        multipleValues = {},
+        maxInputId = 0,
+        newClasses = {},
+        attributeCount = {};
 
-	function ComputeChanges() {
-		let classChanges = [];
-		let actualChanges = [];
+    function ComputeChanges() {
+        let classChanges = [];
+        let actualChanges = [];
 
-		for (let i in newClasses)
-			classChanges.push(`add: objectClass\nobjectClass: ${i}`);
-		for (let i = 0; i < changes.length; ++i) {
-			let ch = changes[i];
-			if (!ch)
-				continue;
-			if (ch.initialValue.length && ch.newValue.length && (multipleValues[ch.attrName] || 0) === 1) {
-				actualChanges.push(`replace: ${ch.attrName}\n${ch.attrName}: ${ch.newValue}`);
-			} else {
-				if (ch.initialValue.length) {
-					if ((multipleValues[ch.attrName] || 0) === 1)
-						actualChanges.push(`delete: ${ch.attrName}`);
-					else
-						actualChanges.push(`delete: ${ch.attrName}\n${ch.attrName}: ${ch.initialValue}`);
-				}
-				if (ch.newValue.length)
-					actualChanges.push(`add: ${ch.attrName}\n${ch.attrName}: ${ch.newValue}`);
-			}
-		}
-		let totalChanges = classChanges.concat(actualChanges.sort((a, b) => b.localeCompare(a)));
-		if (!totalChanges.length)
-			return "";
-		return `dn: ${dn}\nchangetype: modify\n` + totalChanges.join("\n-\n");
-	}
-	function UpdateLdif() {
-		ldifOutput.textContent = ComputeChanges();
-		ldifOutput.style.height = ldifOutput.scrollHeight + "px"
-	}
+        for (let i in newClasses)
+            classChanges.push(`add: objectClass\nobjectClass: ${i}`);
+        for (let i = 0; i < changes.length; ++i) {
+            let ch = changes[i];
+            if (!ch)
+                continue;
+            if (ch.initialValue.length && ch.newValue.length && (multipleValues[ch.attrName] || 0) === 1) {
+                actualChanges.push(`replace: ${ch.attrName}\n${ch.attrName}: ${ch.newValue}`);
+            } else {
+                if (ch.initialValue.length) {
+                    if ((multipleValues[ch.attrName] || 0) === 1)
+                        actualChanges.push(`delete: ${ch.attrName}`);
+                    else
+                        actualChanges.push(`delete: ${ch.attrName}\n${ch.attrName}: ${ch.initialValue}`);
+                }
+                if (ch.newValue.length)
+                    actualChanges.push(`add: ${ch.attrName}\n${ch.attrName}: ${ch.newValue}`);
+            }
+        }
+        let totalChanges = classChanges.concat(actualChanges.sort((a, b) => b.localeCompare(a)));
+        if (!totalChanges.length)
+            return "";
+        return `dn: ${dn}\nchangetype: modify\n` + totalChanges.join("\n-\n");
+    }
+    function UpdateLdif() {
+        ldifOutput.textContent = ComputeChanges();
+        ldifOutput.style.height = ldifOutput.scrollHeight + "px"
+    }
 
-	function onValueChanged(input) {
-		let initialValue = input.dataset.initialValue || "",
-			inputId = input.dataset.inputId,
-			newValue = input.value || "",
-			attrName = input.dataset.attributeName;
-		if (initialValue === newValue)
-			changes[inputId] = undefined;
-		else
-			changes[inputId] = { initialValue: initialValue, newValue: newValue, attrName: attrName };
-		UpdateLdif();
-	}
+    function onValueChanged(input) {
+        let initialValue = input.dataset.initialValue || "",
+            inputId = input.dataset.inputId,
+            newValue = input.value || "",
+            attrName = input.dataset.attributeName;
+        if (initialValue === newValue)
+            changes[inputId] = undefined;
+        else
+            changes[inputId] = { initialValue: initialValue, newValue: newValue, attrName: attrName };
+        UpdateLdif();
+    }
 
-	let prevItem = null; // input field
+    let prevItem = null; // input field
     function removeButtonHandler(input, li) {
         return (e) => {
-			e?.preventDefault();
+            e?.preventDefault();
             input.value = "";
             onValueChanged(input);
+            li.bsTooltip.hide();
             li.parentNode.removeChild(li);
         };
     }
-	function addAddButton(input, li) {
-		let addButton = document.createElement("a");
-		addButton.innerText = "";
+    function addAddButton(input, li) {
+        let addButton = document.createElement("a");
+        addButton.innerText = "";
         addButton.className = "button button-add bi bi-plus-circle";
-		addButton.src = "#";
-		addButton.parentInput = input;
-		addButton.addEventListener("click", (e) => {
-			e.preventDefault();
-			let line = addButton.parentInput.parentNode.parentNode;
-			let copy = line.cloneNode(true);
-			line.parentNode.insertBefore(copy, line);
-			let input = copy.querySelector("label > input");
-			input.value = "";
-			input.dataset.initialValue = "";
-			input.addEventListener("change", e => onValueChanged(e.currentTarget));
-			input.dataset.inputId = ++maxInputId;
+        addButton.src = "#";
+        addButton.parentInput = input;
+        addButton.addEventListener("click", (e) => {
+            e.preventDefault();
+            let line = addButton.parentInput.parentNode.parentNode;
+            let copy = line.cloneNode(true);
+            line.parentNode.insertBefore(copy, line);
+            let input = copy.querySelector("label > input");
+            input.value = "";
+            input.dataset.initialValue = "";
+            input.addEventListener("change", e => onValueChanged(e.currentTarget));
+            input.dataset.inputId = ++maxInputId;
             copy.querySelector(".button-remove")?.addEventListener("click", removeButtonHandler(input, copy));
-			let button = copy.querySelector("label > span > .button-add");
-			button.parentNode.removeChild(button);
-		});
-		li.querySelector(".LDAPAttribute > span").appendChild(addButton);
-	}
-	function addRemoveButton(input, li) { // item is the input field
+            let button = copy.querySelector("label > span > .button-add");
+            button.parentNode.removeChild(button);
+            setTooltipFromInput(input);
+        });
+        li.querySelector(".LDAPAttribute > span").appendChild(addButton);
+    }
+    function addRemoveButton(input, li) { // item is the input field
         if (input.parentNode.children[0].classList.contains("mandatory"))
             return;
-		let button = document.createElement("a");
-		button.innerText = "";
+        let button = document.createElement("a");
+        button.innerText = "";
         button.className = "button button-remove bi bi-dash-circle";
-		button.src = "#";
-		button.addEventListener("click", removeButtonHandler(input, li));
-		li.querySelector(".LDAPAttribute > span").appendChild(button);
-	}
-	function manageDuplicateAttributes(li, input) {
-		attributeCount[input.dataset.attributeName] = (attributeCount[input.dataset.attributeName] || {});
-		attributeCount[input.dataset.attributeName][input.dataset.klass] = true;
-		if (Object.keys(attributeCount[input.dataset.attributeName]).length > 1)
-			li.style.display = "none";
-	}
-	inputs.forEach(i => {
-		maxInputId = Math.max(i.dataset.inputId, maxInputId);
-		let attrName = i.dataset.attributeName;
-		if ((i.dataset.initialValue || "").length)
-			multipleValues[attrName] = (multipleValues[attrName] || 0) + 1;
-		i.addEventListener("change", e => onValueChanged(e.currentTarget))
-		if (prevItem != null &&
-			prevItem.dataset.attributeName !== i.dataset.attributeName) {
-			addAddButton(prevItem, prevItem.parentNode.parentNode);
-		}
+        button.src = "#";
+        button.addEventListener("click", removeButtonHandler(input, li));
+        li.querySelector(".LDAPAttribute > span").appendChild(button);
+    }
+    function manageDuplicateAttributes(li, input) {
+        attributeCount[input.dataset.attributeName] = (attributeCount[input.dataset.attributeName] || {});
+        attributeCount[input.dataset.attributeName][input.dataset.klass] = true;
+        if (Object.keys(attributeCount[input.dataset.attributeName]).length > 1)
+            li.style.display = "none";
+    }
+    function setTooltip(li, description) {
+        if (!description)
+            return;
+        li.dataset.bsTitle = description;
+        li.dataset.bsToggle = "tooltip";
+        li.bsTooltip = new bootstrap.Tooltip(li);
+    }
+    function setTooltipFromInput(input) {
+        setTooltip(input.parentNode.parentNode, schema[input.dataset.klass]?.descriptions?.[input.dataset.attributeName]);
+    }
+    inputs.forEach(i => {
+        maxInputId = Math.max(i.dataset.inputId, maxInputId);
+        let attrName = i.dataset.attributeName;
+        if ((i.dataset.initialValue || "").length)
+            multipleValues[attrName] = (multipleValues[attrName] || 0) + 1;
+        i.addEventListener("change", e => onValueChanged(e.currentTarget))
+        if (prevItem != null &&
+            prevItem.dataset.attributeName !== i.dataset.attributeName) {
+            addAddButton(prevItem, prevItem.parentNode.parentNode);
+        }
         addRemoveButton(i, i.parentNode.parentNode);
-		prevItem = i;
-		manageDuplicateAttributes(i.parentElement.parentElement, i);
-	});
-	prevItem && addAddButton(prevItem, prevItem.parentNode.parentNode);
+        prevItem = i;
+        manageDuplicateAttributes(i.parentElement.parentElement, i);
+        setTooltipFromInput(i);
+    });
+    prevItem && addAddButton(prevItem, prevItem.parentNode.parentNode);
 
-	function CreateClassAttributeDom(className, name, init, isMandatory) {
-		let li = document.createElement("li");
-		let label = document.createElement("label");
-		label.classList.add("LDAPAttribute");
-		label.classList.add("form-label");
-		li.appendChild(label);
-		let span = document.createElement("span");
-		if (isMandatory)
-			span.classList.add("mandatory");
-		span.innerText = name;
-		let input = document.createElement("input");
-		input.type = "text";
-		input.value = init;
-		input.dataset.initialValue = init;
-		input.dataset.inputId = ++maxInputId;
-		input.dataset.name = name;
-		input.dataset.klass = className;
-		input.dataset.attributeName = name;
-		input.required = isMandatory;
+    function CreateClassAttributeDom(className, name, init, isMandatory) {
+        let li = document.createElement("li");
+        let label = document.createElement("label");
+        label.classList.add("LDAPAttribute");
+        label.classList.add("form-label");
+        li.appendChild(label);
+        let span = document.createElement("span");
+        if (isMandatory)
+            span.classList.add("mandatory");
+        span.innerText = name;
+        let input = document.createElement("input");
+        input.type = "text";
+        input.value = init;
+        input.dataset.initialValue = init;
+        input.dataset.inputId = ++maxInputId;
+        input.dataset.name = name;
+        input.dataset.klass = className;
+        input.dataset.attributeName = name;
+        input.required = isMandatory;
         input.className = "form-control";
-		input.addEventListener("change", e => onValueChanged(e.currentTarget))
-		label.appendChild(span);
-		label.appendChild(input);
-		addAddButton(input);
-		manageDuplicateAttributes(li, input);
-		return li;
-	}
+        input.addEventListener("change", e => onValueChanged(e.currentTarget))
+        label.appendChild(span);
+        label.appendChild(input);
+        addAddButton(input, li);
+        if (!isMandatory)
+            addRemoveButton(input, li);
+        manageDuplicateAttributes(li, input);
+        setTooltipFromInput(input);
+        return li;
+    }
 
-	function CreateClassDom(schema, className) {
-		let classDom = document.createElement("fieldset");
-		classDom.classList.add("LDAPClass");
-		let legend = document.createElement("legend");
-		let legendInner = document.createElement("h3");
-		legendInner.innerText = className +' (' +schema["type"] +')';
-		legend.appendChild(legendInner);
-		classDom.appendChild(legend);
-		let list = document.createElement("ul");
-		for (let i of schema["must"])
-			list.appendChild(CreateClassAttributeDom(className, i, "", true));
-		for (let i of schema["may"])
-			list.appendChild(CreateClassAttributeDom(className, i, "", false));
-		classDom.appendChild(list);
-		return classDom;
-	}
+    function CreateClassDom(schema, className) {
+        let classDom = document.createElement("fieldset");
+        classDom.classList.add("LDAPClass");
+        let legend = document.createElement("legend");
+        let legendInner = document.createElement("h3");
+        legendInner.innerText = className +' (' +schema["type"] +')';
+        legend.appendChild(legendInner);
+        classDom.appendChild(legend);
+        let list = document.createElement("ul");
+        for (let i of schema["must"])
+            list.appendChild(CreateClassAttributeDom(className, i, "", true));
+        for (let i of schema["may"])
+            list.appendChild(CreateClassAttributeDom(className, i, "", false));
+        classDom.appendChild(list);
+        return classDom;
+    }
 
-	addClassBtn.addEventListener("click", () => {
-		let targetClass = addClassSelect.value;
-		if (!schema[targetClass])
-			return;
-		for (let i of addClassSelect.children) {
-			if (i.value === targetClass) {
-				addClassSelect.removeChild(i);
-				break;
-			}
-		}
-		newClasses[targetClass] = true;
-		let dom = CreateClassDom(schema[targetClass], targetClass);
-		classContainer.appendChild(dom);
-		UpdateLdif();
-	});
+    addClassBtn.addEventListener("click", () => {
+        let targetClass = addClassSelect.value;
+        if (!schema[targetClass])
+            return;
+        for (let i of addClassSelect.children) {
+            if (i.value === targetClass) {
+                addClassSelect.removeChild(i);
+                break;
+            }
+        }
+        newClasses[targetClass] = true;
+        let dom = CreateClassDom(schema[targetClass], targetClass);
+        classContainer.appendChild(dom);
+        UpdateLdif();
+    });
 })(
-	window['dn'], window['schema'],
-	document.querySelectorAll(".LDAPAttribute > input"), document.getElementById("ldifOutput"),
-	document.getElementById("classContainer"),
-	document.getElementById("addClassSelect"), document.getElementById("addClassBtn"));
+    window['dn'], window['schema'],
+    document.querySelectorAll(".LDAPAttribute > input"), document.getElementById("ldifOutput"),
+    document.getElementById("classContainer"),
+    document.getElementById("addClassSelect"), document.getElementById("addClassBtn"));

+ 4 - 0
routes/entity.ts

@@ -32,11 +32,15 @@ function StructifySchema(schema: Map<string, LDAPSchemaObjectClass>): any {
     for (let [key, oc] of schema) {
         if (oc.GetType() === ClassType.eAbstract)
             continue;
+        let description: any = {};
+        for (let [key, val] of oc.ListDescriptions())
+            description[key] = val;
         let obj = {
             may: oc.ListMayAttributes().filter(i => i.toLowerCase() !== 'objectclass'),
             must: oc.ListMustAttributes().filter(i => i.toLowerCase() !== 'objectclass'),
             structural: oc.GetType() === ClassType.eStructural,
             auxiliary: oc.GetType() === ClassType.eAuxiliary,
+            descriptions: description,
             type: getType(schema, key)
         };
         result[key] = obj;

+ 8 - 0
src/LDAPSchema.ts

@@ -134,6 +134,13 @@ export class LDAPSchemaObjectClass extends LDAPSchemaItem {
 		return this.fMustAttributes.has(attr);
 	}
 
+    public ListDescriptions(): Map<string, string> {
+        let result = new Map();
+        for (let [key, data] of this.fMayAttributes) result.set(key, data.GetDescription());
+        for (let [key, data] of this.fMustAttributes) result.set(key, data.GetDescription());
+        return result;
+    }
+
 	public ListMayAttributes(): string[] {
 		let result = new Array();
 		for (let [key, _] of this.fMayAttributes) result.push(key);
@@ -163,3 +170,4 @@ export class LDAPSchemaObjectClass extends LDAPSchemaItem {
 	private fMayAttributes: Map<string, LDAPSchemaAttribute> = new Map();
 	private fMustAttributes: Map<string, LDAPSchemaAttribute> = new Map();
 }
+

+ 3 - 1
views/category.pug

@@ -35,4 +35,6 @@ block content
                 td (empty)
           td
             a(data-dn=item.GetAddress() href="#" class="action-remove") del
-    script(src='/javascripts/category.js', language='javascript')
+
+block append scripts
+  script(src='/javascripts/category.js', language='javascript')

+ 7 - 4
views/entity.pug

@@ -1,9 +1,6 @@
 extends layout
 
 block content
-  script.
-    window['dn']="#{dn}";
-    window['schema']=!{JSON.stringify(schema)};
   div(id="entity-page",class="page",data-dn=dn)
     h1=dn
     div(id="classContainer")
@@ -29,4 +26,10 @@ block content
     fieldset(class="changes")
       textarea(id="ldifOutput",readonly,class="form-control")
       input(type="button",value="Submit")
-  script(src="../javascripts/entity.js")
+
+
+block append scripts
+  script.
+    window['dn']="#{dn}";
+    window['schema']=!{JSON.stringify(schema)};
+  script(src="/javascripts/entity.js")

+ 2 - 2
views/index.pug

@@ -3,14 +3,14 @@ include ../templates/tree.pug
 
 block append scripts
   script(src='/javascripts/tree.js', language='javascript')
+  script.
+    $(() => makeTree(document.querySelectorAll("#menuBar>div>ul.treeroot")[0]));
 
 block content
   div(class='page-index')
     div(id="menuBar")
       div
         +treeroot(tree)
-        script.
-          $(() => makeTree(document.querySelectorAll("#menuBar>div>ul.treeroot")[0]));
       a(href="/logout")
         p Logout
     iframe(id="page",name="page",src="home")

+ 2 - 2
views/layout.pug

@@ -8,7 +8,7 @@ html
     link(rel='icon', type='image/x-icon', href='/img/OIG3.png')
     meta(name='viewport', content='width=device-width, initial-scale=1')
   body
+    block content
     block scripts
-      script(src='https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js', integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz", crossorigin="anonymous")
       script(src='https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js', integrity="sha384-1H217gwSVyLSIfaLxHbE7dRb3v4mYCKbpQvzx0cegeju1MVsGrX5xXxAvs/HgeFs", crossorigin="anonymous")
-    block content
+      script(src='https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js', integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz", crossorigin="anonymous")