Prechádzať zdrojové kódy

Refs #5 main window UI/UX

isundil 1 rok pred
rodič
commit
3caff7d7aa

+ 32 - 9
public/javascripts/entity.js

@@ -22,7 +22,7 @@
 					if ((multipleValues[ch.attrName] || 0) === 1)
 						actualChanges.push(`delete: ${ch.attrName}`);
 					else
-						actualChanges.push(`delete: ${ch.attrName}\nattribute: ${ch.initialValue}`);
+						actualChanges.push(`delete: ${ch.attrName}\n${ch.attrName}: ${ch.initialValue}`);
 				}
 				if (ch.newValue.length)
 					actualChanges.push(`add: ${ch.attrName}\n${ch.attrName}: ${ch.newValue}`);
@@ -51,25 +51,45 @@
 	}
 
 	let prevItem = null; // input field
-	function addAddButton(item) { // item is the input field
+    function removeButtonHandler(input, li) {
+        return (e) => {
+			e?.preventDefault();
+            input.value = "";
+            onValueChanged(input);
+            li.parentNode.removeChild(li);
+        };
+    }
+	function addAddButton(input, li) {
 		let addButton = document.createElement("a");
-		addButton.innerText = "Add";
+		addButton.innerText = "";
+        addButton.className = "button button-add bi bi-plus-circle";
 		addButton.src = "#";
-		addButton.parentInput = item;
+		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.querySelectorAll("label > input")[0];
+			let input = copy.querySelector("label > input");
 			input.value = "";
 			input.dataset.initialValue = "";
 			input.addEventListener("change", e => onValueChanged(e.currentTarget));
 			input.dataset.inputId = ++maxInputId;
-			let button = copy.querySelectorAll("label > span > a")[0];
+            copy.querySelector(".button-remove")?.addEventListener("click", removeButtonHandler(input, copy));
+			let button = copy.querySelector("label > span > .button-add");
 			button.parentNode.removeChild(button);
 		});
-		item.parentNode.children[0].appendChild(addButton);
+		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 = "";
+        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] || {});
@@ -85,17 +105,19 @@
 		i.addEventListener("change", e => onValueChanged(e.currentTarget))
 		if (prevItem != null &&
 			prevItem.dataset.attributeName !== i.dataset.attributeName) {
-			addAddButton(prevItem);
+			addAddButton(prevItem, prevItem.parentNode.parentNode);
 		}
+        addRemoveButton(i, i.parentNode.parentNode);
 		prevItem = i;
 		manageDuplicateAttributes(i.parentElement.parentElement, i);
 	});
-	prevItem && addAddButton(prevItem);
+	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)
@@ -110,6 +132,7 @@
 		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);

+ 7 - 3
public/javascripts/tree.js

@@ -1,17 +1,21 @@
+
+const CLASSNAME_EXPANDED = "bi bi-chevron-down";
+const CLASSNAME_COLLAPSED = "bi bi-chevron-up";
+
 window["makeTree"] = function (ulRoot) {
 	let makeTree = (li) => {
 		let button = li.children[0];
 		let list = li.children[1];
 		if (button && list && button.nodeName == 'SPAN' && list.nodeName == 'UL') {
-			button.innerText = "-" + button.dataset["name"];
+			button.className = CLASSNAME_COLLAPSED;
 			list.style.display = 'block';
 			button.addEventListener("click", (e) => {
 				let visible = list.style.display === 'block';
 				if (visible) {
-					button.innerText = "+" + button.dataset["name"];
+					button.className = CLASSNAME_EXPANDED;
 					list.style.display = "none";
 				} else {
-					button.innerText = "-" + button.dataset["name"];
+					button.className = CLASSNAME_COLLAPSED;
 					list.style.display = "block";
 				}
 			});

+ 61 - 4
public/stylesheets/main.css

@@ -37,7 +37,7 @@ a {
 #menuBar {
     display: inline-block;
     min-width: 200px;
-    width: min(100%, 350px);
+    width: min(100%, 300px);
     height: 100vh;
     border-right: 1px solid gray;
     overflow: auto;
@@ -47,16 +47,56 @@ a {
     margin: 2em;
 }
 .treeroot {
-    padding: 0 1.5em;
+    padding: 0;
+}
+.treeroot li {
+    list-style-type: none;
+    user-select: none;
+}
+.treeroot li > span::before {
+    font-weight: bold !important;
+    padding-right: 5px;
 }
 iframe#page {
     display: inline-flex;
     flex: 1;
     border: none;
 }
+#entity-page,#home-page {
+    min-height: 100vh;
+}
 #entity-page {
     background: url("/img/OIG3.png") no-repeat center 22vh /44vh;
 }
+#entity-page #classContainer {
+    background: rgba(255, 255, 255, 0.33);
+    background: linear-gradient(to right, rgba(255, 255, 255, 0.45), 66%, rgba(255, 255, 255, 0.45), rgba(255, 255, 255, 0));
+    backdrop-filter: blur(2px);
+}
+#home-page {
+    background: #edf6fb;
+    margin: 0;
+    display: flex;
+}
+#home-page .logo-big {
+    margin: auto;
+    position: relative;
+}
+#home-page .logo-big > img {
+    max-height: 44vh;
+    max-width: 44vw;
+}
+#home-page .logo-big::before {
+    position: absolute;
+    display: inline-flex;
+    top: -10px;
+    bottom: -10px;
+    left: -10px;
+    right: -10px;
+    content: ' ';
+    border: solid 25px rgba(237,246,251, 0.75);
+    filter: blur(30px);
+}
 div.page {
     margin: 0 1em;
 }
@@ -74,8 +114,25 @@ label.LDAPAttribute > span {
     display: inline-block;
     width: 250px;
 }
-label.LDAPAttribute > span.mandatory:after {
-    content: " (*)"
+label.LDAPAttribute > span > .button {
+    margin-left: 7px;
+}
+label.LDAPAttribute > span > .button-add {
+    color: var(--bs-success);
+}
+label.LDAPAttribute > span > .button-remove {
+    color: var(--bs-danger);
+}
+label.LDAPAttribute > span.mandatory {
+    font-weight: bold;
+}
+label.LDAPAttribute > span.mandatory::before {
+    content: "*";
+    color: red;
+    font-weight: bold;
+}
+label.LDAPAttribute .button::before {
+    cursor: pointer;
 }
 label.LDAPAttribute > input {
     display: inline-block;

+ 1 - 1
routes/index.ts

@@ -39,7 +39,7 @@ router.get('/', (req: express.Request, res: express.Response) => {
 router.get('/home', (req, res) => {
     if (!req.isUserLogged)
         return RouterUtils.Redirect(res, "/login");
-    res.send("Hello, world");
+    res.render('homePage', {});
 });
 
 export default router;

+ 1 - 1
templates/tree.pug

@@ -2,7 +2,7 @@
 mixin tree(item)
   li(class="treeitem",alt=item.FullName(),data-fullname=item.FullName())
     if item.HasChildren()
-      span(data-name=item.GetName())
+      span(data-name=item.GetName())=item.GetName()
       ul(class="treebranch")
         for i in item.GetChildren()
           +tree(i)

+ 3 - 3
views/entity.pug

@@ -16,10 +16,10 @@ block content
             each valArr, key in attributes[className]
               for val in valArr
                 li
-                  label(class="LDAPAttribute")
+                  label(class="LDAPAttribute form-label")
                     -mandatory=isMandatory(key)
                     span(class=mandatory ? "mandatory": "")=key
-                    input(type="text",value=val,data-initial-value=val,data-input-id=id,data-attribute-name=key,required=mandatory,data-klass=className)
+                    input(type="text",value=val,data-initial-value=val,data-input-id=id,data-attribute-name=key,required=mandatory,data-klass=className,class="form-control")
                     -id++
     div
       select(id="addClassSelect")
@@ -27,6 +27,6 @@ block content
           option=unusedClass
       input(type="submit",value="Add Class",id="addClassBtn")
     fieldset(class="changes")
-      textarea(id="ldifOutput",readonly)
+      textarea(id="ldifOutput",readonly,class="form-control")
       input(type="button",value="Submit")
   script(src="../javascripts/entity.js")

+ 6 - 0
views/homePage.pug

@@ -0,0 +1,6 @@
+extends layout
+
+block content
+  div(id="home-page",class="page",data-dn=dn)
+    div(class="logo-big")
+      img(src="/img/OIG3.jpg")

+ 2 - 0
views/index.pug

@@ -11,4 +11,6 @@ block content
         +treeroot(tree)
         script.
           $(() => makeTree(document.querySelectorAll("#menuBar>div>ul.treeroot")[0]));
+      a(href="/logout")
+        p Logout
     iframe(id="page",name="page",src="home")

+ 1 - 0
views/layout.pug

@@ -4,6 +4,7 @@ html
     title= title
     link(rel='stylesheet', href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css', integrity='sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH', crossorigin='anonymous')
     link(rel='stylesheet', href='/stylesheets/main.css')
+    link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css")
     link(rel='icon', type='image/x-icon', href='/img/OIG3.png')
     meta(name='viewport', content='width=device-width, initial-scale=1')
   body