entity.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. ((dn, schema, inputs, ldifOutput, classContainer, addClassSelect, addClassBtn) => {
  2. let changes = [],
  3. multipleValues = {},
  4. maxInputId = 0,
  5. newClasses = {},
  6. attributeCount = {};
  7. function ComputeChanges() {
  8. let classChanges = [];
  9. let actualChanges = [];
  10. for (let i in newClasses)
  11. classChanges.push(`add: objectClass\nobjectClass: ${i}`);
  12. for (let i = 0; i < changes.length; ++i) {
  13. let ch = changes[i];
  14. if (!ch)
  15. continue;
  16. if (ch.initialValue.length && ch.newValue.length && (multipleValues[ch.attrName] || 0) === 1) {
  17. actualChanges.push(`replace: ${ch.attrName}\n${ch.attrName}: ${ch.newValue}`);
  18. } else {
  19. if (ch.initialValue.length) {
  20. if ((multipleValues[ch.attrName] || 0) === 1)
  21. actualChanges.push(`delete: ${ch.attrName}`);
  22. else
  23. actualChanges.push(`delete: ${ch.attrName}\n${ch.attrName}: ${ch.initialValue}`);
  24. }
  25. if (ch.newValue.length)
  26. actualChanges.push(`add: ${ch.attrName}\n${ch.attrName}: ${ch.newValue}`);
  27. }
  28. }
  29. let totalChanges = classChanges.concat(actualChanges.sort((a, b) => b.localeCompare(a)));
  30. if (!totalChanges.length)
  31. return "";
  32. return `dn: ${dn}\nchangetype: modify\n` + totalChanges.join("\n-\n");
  33. }
  34. function UpdateLdif() {
  35. ldifOutput.textContent = ComputeChanges();
  36. ldifOutput.style.height = ldifOutput.scrollHeight + "px"
  37. }
  38. function onValueChanged(input) {
  39. let initialValue = input.dataset.initialValue || "",
  40. inputId = input.dataset.inputId,
  41. newValue = input.value || "",
  42. attrName = input.dataset.attributeName;
  43. if (initialValue === newValue)
  44. changes[inputId] = undefined;
  45. else
  46. changes[inputId] = { initialValue: initialValue, newValue: newValue, attrName: attrName };
  47. UpdateLdif();
  48. }
  49. function getEditLink(className, attrName) {
  50. for (var i in window.editlinks) {
  51. if (window.editlinks[i].indexOf(`${className}.${attrName}`) >= 0)
  52. return i;
  53. }
  54. return null;
  55. }
  56. function manageEditLink(input) {
  57. const editLink = getEditLink(input.dataset.klass, input.dataset.attributeName);
  58. if (!editLink)
  59. return;
  60. let linkWrapper = document.createElement("div");
  61. let link = document.createElement("a");
  62. input.disabled = true;
  63. linkWrapper.className = "editlink";
  64. link.textContent = editLink;
  65. link.href = editLink;
  66. link.target = "_blank";
  67. linkWrapper.appendChild(link);
  68. input.parentNode.appendChild(linkWrapper);
  69. }
  70. let prevItem = null; // input field
  71. function removeButtonHandler(input, li) {
  72. return (e) => {
  73. e?.preventDefault();
  74. if (multipleValues[input.dataset.attributeName])
  75. multipleValues[input.dataset.attributeName]--;
  76. if (!multipleValues[input.dataset.attributeName] && input.dataset.mandatory) {
  77. // remove last remove button
  78. }
  79. input.value = "";
  80. onValueChanged(input);
  81. li.bsTooltip.hide();
  82. li.parentNode.removeChild(li);
  83. };
  84. }
  85. function addAddButton(input, li) {
  86. let addButton = document.createElement("a");
  87. addButton.innerText = "";
  88. addButton.className = "button button-add bi bi-plus-circle";
  89. addButton.src = "#";
  90. addButton.parentInput = input;
  91. addButton.addEventListener("click", (e) => {
  92. e.preventDefault();
  93. let line = addButton.parentInput.parentNode.parentNode;
  94. let copy = line.cloneNode(true);
  95. line.parentNode.insertBefore(copy, line);
  96. let input = copy.querySelector("label input");
  97. input.value = "";
  98. input.dataset.initialValue = "";
  99. input.addEventListener("change", e => onValueChanged(e.currentTarget));
  100. input.dataset.inputId = ++maxInputId;
  101. multipleValues[input.dataset.attributeName] = (multipleValues[input.dataset.attributeName] || 1) + 1;
  102. if (!copy.querySelector(".button-remove")) {
  103. addRemoveButton(line.querySelector("label > input"), line);
  104. addRemoveButton(input, copy);
  105. } else {
  106. copy.querySelector(".button-remove")?.addEventListener("click", removeButtonHandler(input, copy));
  107. }
  108. let button = copy.querySelector("label > span > .button-add");
  109. button.parentNode.removeChild(button);
  110. setTooltipFromInput(input);
  111. });
  112. li.querySelector(".LDAPAttribute > span").appendChild(addButton);
  113. }
  114. function addRemoveButton(input, li) {
  115. if (input.dataset.isMandatory == "true" && (multipleValues[input.dataset.attributeName] || 1) <= 1)
  116. return;
  117. let button = document.createElement("a");
  118. button.innerText = "";
  119. button.className = "button button-remove bi bi-dash-circle";
  120. button.src = "#";
  121. button.addEventListener("click", removeButtonHandler(input, li));
  122. li.querySelector(".LDAPAttribute > span").appendChild(button);
  123. }
  124. function manageDuplicateAttributes(li, input) {
  125. attributeCount[input.dataset.attributeName] = (attributeCount[input.dataset.attributeName] || {});
  126. attributeCount[input.dataset.attributeName][input.dataset.klass] = true;
  127. if (Object.keys(attributeCount[input.dataset.attributeName]).length > 1)
  128. li.style.display = "none";
  129. }
  130. function setTooltip(li, description) {
  131. if (!description)
  132. return;
  133. li.dataset.bsTitle = description;
  134. li.dataset.bsToggle = "tooltip";
  135. li.bsTooltip = new bootstrap.Tooltip(li, { trigger: "hover" });
  136. }
  137. function setTooltipFromInput(input) {
  138. setTooltip(input.parentNode.parentNode, schema[input.dataset.klass]?.descriptions?.[input.dataset.attributeName]);
  139. }
  140. inputs.forEach(i => {
  141. maxInputId = Math.max(i.dataset.inputId, maxInputId);
  142. i.dataset.isMandatory = i.parentNode.children[0].classList.contains("mandatory");
  143. let attrName = i.dataset.attributeName;
  144. if ((i.dataset.initialValue || "").length)
  145. multipleValues[attrName] = (multipleValues[attrName] || 0) + 1;
  146. i.addEventListener("change", e => onValueChanged(e.currentTarget))
  147. if (prevItem != null &&
  148. prevItem.dataset.attributeName !== i.dataset.attributeName) {
  149. addAddButton(prevItem, prevItem.parentNode.parentNode);
  150. }
  151. prevItem = i;
  152. manageDuplicateAttributes(i.parentElement.parentElement.parentElement, i);
  153. setTooltipFromInput(i);
  154. manageEditLink(i);
  155. });
  156. inputs.forEach(i => {
  157. addRemoveButton(i, i.parentNode.parentNode);
  158. });
  159. prevItem && addAddButton(prevItem, prevItem.parentNode.parentNode);
  160. function CreateClassAttributeDom(className, name, init, isMandatory) {
  161. let li = document.createElement("li");
  162. let label = document.createElement("label");
  163. label.classList.add("LDAPAttribute");
  164. label.classList.add("form-label");
  165. li.appendChild(label);
  166. let span = document.createElement("span");
  167. if (isMandatory)
  168. span.classList.add("mandatory");
  169. span.innerText = name;
  170. let inputWrapper = document.createElement("span");
  171. let input = document.createElement("input");
  172. inputWrapper.className = "form-input-wrapper";
  173. input.type = "text";
  174. input.value = init;
  175. input.dataset.initialValue = init;
  176. input.dataset.inputId = ++maxInputId;
  177. input.dataset.name = name;
  178. input.dataset.klass = className;
  179. input.dataset.attributeName = name;
  180. input.required = isMandatory;
  181. input.className = "form-control";
  182. input.addEventListener("change", e => onValueChanged(e.currentTarget))
  183. label.appendChild(span);
  184. label.appendChild(inputWrapper);
  185. inputWrapper.appendChild(input);
  186. addAddButton(input, li);
  187. if (!isMandatory)
  188. addRemoveButton(input, li);
  189. manageDuplicateAttributes(li, input);
  190. manageEditLink(input);
  191. setTooltipFromInput(input);
  192. return li;
  193. }
  194. function CreateClassDom(schema, className) {
  195. let classDom = document.createElement("fieldset");
  196. classDom.classList.add("LDAPClass");
  197. let legend = document.createElement("legend");
  198. let legendInner = document.createElement("h3");
  199. legendInner.innerText = className +' (' +schema["type"] +')';
  200. legend.appendChild(legendInner);
  201. classDom.appendChild(legend);
  202. let list = document.createElement("ul");
  203. for (let i of schema["must"])
  204. list.appendChild(CreateClassAttributeDom(className, i, "", true));
  205. for (let i of schema["may"])
  206. list.appendChild(CreateClassAttributeDom(className, i, "", false));
  207. classDom.appendChild(list);
  208. return classDom;
  209. }
  210. addClassBtn.addEventListener("click", () => {
  211. let targetClass = addClassSelect.value;
  212. if (!schema[targetClass])
  213. return;
  214. for (let i of addClassSelect.children) {
  215. if (i.value === targetClass) {
  216. addClassSelect.removeChild(i);
  217. break;
  218. }
  219. }
  220. newClasses[targetClass] = true;
  221. let dom = CreateClassDom(schema[targetClass], targetClass);
  222. classContainer.appendChild(dom);
  223. UpdateLdif();
  224. });
  225. })(
  226. window['dn'], window['schema'],
  227. document.querySelectorAll(".LDAPAttribute input"), document.getElementById("ldifOutput"),
  228. document.getElementById("classContainer"),
  229. document.getElementById("addClassSelect"), document.getElementById("addClassBtn"));