NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name xa_designer_overlay // @description Overlay with quality of life improvements // @version 1.0 // @require https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js // @require https://raw.githubusercontent.com/JDMcKinstry/jQuery.winFocus/master/jquery.winFocus.js // @require https://cdnjs.cloudflare.com/ajax/libs/chosen/1.8.7/chosen.jquery.min.js // @include /^https://.*-des\.f.v..d\.com// // @license MIT // @updateURL https://openuserjs.org/meta/ford.lambert/xa_designer_overlay.meta.js // @downloadURL https://openuserjs.org/install/ford.lambert/xa_designer_overlay.user.js // ==/UserScript== // ==OpenUserJS== // @author ford.lambert // ==/OpenUserJS== // jshint esversion: 6 // jshint jquery: true // globals $, jQuery (function (jQuery) { "use strict"; jQuery.noConflict(); // do not use $ because it's also used by Prototype console.log(`%c Loading XA overlay`, "color: #38C4CC"); console.log( `%c Enable or disable XA overlay modules in it's menu on the top of the screen`, "color: #38C4CC" ); let tabIsActive = true; const modules = { regenMonitor: { active: getCookie("xa_regen_monitor").length ? getCookie("xa_regen_monitor") == "true" || getCookie("xa_regen_monitor") == true ? true : false : true, cookie: "xa_regen_monitor", label: "Regen monitor", title: "IceBlue Style required - Show production monitor infos with a colored logo on top left corner, green: done, yellow: running. Go inactive/active when tab loose/gain focus", }, shortcuts: { active: getCookie("xa_shortcuts").length ? getCookie("xa_shortcuts") == "true" || getCookie("xa_shortcuts") == true ? true : false : true, cookie: "xa_shortcuts", label: "Keyboard shortcuts", title: "Enable some keyboard shortcuts: ctrl + shift + f -> global fv search, ctrl + shift + s -> save and quit, ctrl + s -> save and continue", }, editorQol: { active: getCookie("xa_editor_qol").length ? getCookie("xa_editor_qol") == "true" || getCookie("xa_editor_qol") == true ? true : false : true, cookie: "xa_editor_qol", label: "Editor QOL", title: "Add some quality of life display when editing something, status, spec reference and level of sharing", }, generalLisibility: { active: getCookie("xa_lisibility").length ? getCookie("xa_lisibility") == "true" || getCookie("xa_lisibility") == true ? true : false : true, cookie: "xa_lisibility", label: "General lisibility", title: "Add some little things to boost lisibility: partial names are colored, always show lightened lightbulbs, show scss var colors", }, flash: { active: getCookie("xa_flash").length ? getCookie("xa_flash") == "true" || getCookie("xa_flash") == true ? true : false : true, cookie: "xa_flash", label: "Flash expire", title: "Remove flash messages after 5sec of display", }, fieldPresence: { active: getCookie("xa_field_presence").length ? getCookie("xa_field_presence") == "true" || getCookie("xa_field_presence") == true ? true : false : true, cookie: "xa_field_presence", label: "Field presence alert", title: "Display a warning if a model does not have a created_at and updated_at", }, userStory: { active: getCookie("xa_user_story").length ? getCookie("xa_user_story") == "true" || getCookie("xa_user_story") == true ? true : false : false, cookie: "xa_user_story", label: "User story warning", title: "Experimental, display a warning if you have no user story assigned", }, editorSize: { active: getCookie("xa_editor_size").length ? getCookie("xa_editor_size") == "true" || getCookie("xa_editor_size") == true ? true : false : false, cookie: "xa_editor_size", label: "Ace editor default size", title: "Save your last editor height and set it on load", }, regenButton: { active: getCookie("xa_regen_button").length ? getCookie("xa_regen_button") == "true" || getCookie("xa_regen_button") == true ? true : false : true, cookie: "xa_regen_button", label: "Add a regen button", title: "Add a regen button on top of models pages next to the Maveoc name, does exactly like the drag and drop of fields without the risk of missclick.", }, dragDropLocker: { active: getCookie("xa_drag_drop_locker").length ? getCookie("xa_drag_drop_locker") == "true" || getCookie("xa_drag_drop_locker") == true ? true : false : true, cookie: "xa_drag_drop_locker", label: "Add a drag and drop locking button", title: "Add a button to 'lock' model and graphical views therefore avoiding missdrop. Locked by default. Also move the reminders away from this area to avoid their removing", }, qualityFramework: { active: getCookie("xa_quality_framework").length ? getCookie("xa_quality_framework") == "true" || getCookie("xa_quality_framework") == true ? true : false : false, cookie: "xa_quality_framework", label: "Experimental - Quality framework", title: "Experimental, add functionnalities to force the use of quality tools around the app (status / description...)", }, experimentalInterface: { active: getCookie("xa_experimental_interface").length ? getCookie("xa_experimental_interface") == "true" || getCookie("xa_experimental_interface") == true ? true : false : false, cookie: "xa_experimental_interface", label: "Experimental - Apply UI improvements", title: "The functionnality in this section will be merged elsewhere after user review. Currently: change certain select into chosens", }, }; console.log({ modules }); const initOverlay = () => { setXaMenu(); addKeybordShortcuts(); limitFlashDuration(); displayRequiredFieldNotice(); displayUserStoryWarning(); displayEditorInfos(); displayVisibilityBoost(); resizeEditor(); addRegenButton(); addDragDropLocker(); initQualityFramework(); initExperimentalUi(); delay(1000).then(() => addRegenWatcher()); }; // XA Menu ------> const setXaMenu = () => { const $xaMenuButton = jQuery("<button></button>") .attr("id", "xa-menu-button") .text("XA - Menu") .css("margin", "0 20px"); const $xaMenuBox = jQuery("<div></div>") .attr("id", "xa-menu") .css("position", "fixed") .css("top", "20vh") .css("left", "42vw") .css("padding", "10px") .css("box-shadow", "0px 0px 900px 50px black") .css("z-index", "9000") .css("background-color", "white") .css("color", "black") .css("visibility", "hidden") .css("max-height", "60vh") .css("overflow", "auto"); const $xaMenu = jQuery("<form></form>").attr("method", "dialog"); const $info = jQuery("<p></p>") .css("width", "350px") .css("font-size", "1.2em") .css("font-style", "italic") .text( "Changing the value a checkbox immediatly update a related cookie for enabling/disabling the module. Reload needed to apply effect (consider your background work before doing so...)." ); $xaMenuBox.append($info); for (const [key, module] of Object.entries(modules)) { const $xaMenuEntrie = jQuery("<div></div>") .css("display", "flex") .css("justify-content", "center") .css("align-items", "center") .css("margin-bottom", "10px") .css("border-bottom", "1px solid grey"); const $label = jQuery("<label></label>") .text(module.label) .css("width", "150px") .css("font-size", "1.2em") .attr("for", `xa-${module.cookie}-input`); const $input = jQuery("<input />") .attr("type", "checkbox") .prop("checked", module.active) .css("margin", "5px 10px") .attr("id", `xa-${module.cookie}-input`); $input.on("change", function () { setLocalCookie(module.cookie, this.checked); }); const $info = jQuery("<img />") .attr("src", "/images/std/help.png?1199643545") .attr("alt", "Help") .attr("title", module.title); $xaMenuEntrie.append($label); $xaMenuEntrie.append($input); $xaMenuEntrie.append($info); $xaMenu.append($xaMenuEntrie); $xaMenuBox.append($xaMenu); } const $menu = jQuery("<menu></menu>") .css("padding", "0") .css("display", "flex") .css("justify-content", "center"); const $closeButton = jQuery("<button></button>") .attr("value", "cancel") .text("Cancel") .css("margin", "10px"); const $reloadButton = jQuery("<button></button>") .text("Reload to apply") .css("margin", "10px") .attr("onClick", "location.reload()"); $menu.append($closeButton); $menu.append($reloadButton); $xaMenu.append($menu); jQuery("#header-elts").append($xaMenuBox); jQuery("#header-elts").prepend($xaMenuButton); $xaMenuButton.on("click", () => { toggleModal(jQuery("#xa-menu")); }); $closeButton.on("click", () => { toggleModal(jQuery("#xa-menu")); }); }; const toggleModal = ($modal) => { if ($modal.css("visibility") == "visible") { $modal.css("visibility", "hidden"); } else { $modal.css("visibility", "visible"); } }; // XA Menu <------ // Regen watcher ------> const addRegenWatcher = () => { if ( modules.regenMonitor.active && !window.location.href.includes("/tasks") ) { const hasCustomStyle = jQuery("#title").find("h1").css("display") == "none"; displayLogo(hasCustomStyle); pollRegen(); let monitor_pu = new Ajax.PeriodicalUpdater( "production_monitor", "/changes/current_tasks", { method: "post", frequency: 3, decay: 2 } ); jQuery.winFocus({ // will only fire when current tab loses focus blur: () => { disableRegenWatcher(monitor_pu); tabIsActive = false; }, // will only fire when current tab gains focus focus: () => { tabIsActive = true; monitor_pu = new Ajax.PeriodicalUpdater( "production_monitor", "/changes/current_tasks", { method: "post", frequency: 3, decay: 2 } ); pollRegen(); }, }); } }; const disableRegenWatcher = (monitor_pu) => { monitor_pu.stop(); monitor_pu = undefined; }; const pollRegen = () => { const inactiveLogo = "https://i.imgur.com/qU5tlox.png"; const doneLogo = "https://i.imgur.com/2ZV6gAJ.png"; const processingLogo = "https://i.imgur.com/35esLp6.png"; let text = ""; jQuery("#production_monitor") .find("td") .each(function () { text += jQuery(this).text().trim(); }); const isProcessing = text.length > 0; if (isProcessing) { changeLogo(processingLogo); } else { changeLogo(doneLogo); } setTimeout(function () { if (tabIsActive) { pollRegen(); } else { changeLogo(inactiveLogo); } }, 2000); }; const changeLogo = (logoPath) => { jQuery("#header") .find("#title") .css("background-image", "url(" + logoPath + ")"); }; const displayLogo = (hasCustomStyle) => { const logoPath = hasCustomStyle ? "https://storage.gra.cloud.ovh.net/v1/AUTH_0b4eb0b702894162b8bcdc31088fb7dd/hexa-public/designer-script/default.png" : "/images/logo/logo.png"; const $header = jQuery("#header"); const $title = $header.find("#title"); $title.css("background-image", "url(" + logoPath + ")"); const $titleInfos = jQuery("<span></span>") .addClass("sub-title") .text($title.text()); $header.append($titleInfos); }; // Regen watcher <------ // KEYBOARD SHORTCUTS ------> const addKeybordShortcuts = () => { if (modules.shortcuts.active) { jQuery(document).on("keydown", (e) => { const isMac = navigator.platform.match("Mac"); const ctrlLikeKey = isMac ? e.metaKey : e.ctrlKey; const saveKeyCode = 83; const searchKeyCode = 70; if (isMac) { if (ctrlLikeKey && e.shiftKey && e.keyCode == saveKeyCode) { e.preventDefault(); // prevent "save html page" default event submitEditor(); } } else { if (ctrlLikeKey && e.keyCode == saveKeyCode) { e.preventDefault(); // prevent "save html page" default event submitEditor(); } } if (ctrlLikeKey && e.shiftKey && e.keyCode == searchKeyCode) { jQuery("#global_search_field").focus(); } }); } }; const submitEditor = () => { // const $saveContinue = jQuery('#new_create_form_submit').length ? jQuery('#new_create_form_submit') : jQuery('#continue_editing_form_submit'); // stayOnPage ? $saveContinue.click() : jQuery('#update_form_submit').click(); jQuery("#continue_editing_form_submit").click(); }; // <------ KEYBOARD SHORTCUTS // Info display ------> const limitFlashDuration = () => { if (modules.flash.active) { // After reload on save, a sticky flash stay on the top left, remove it after some time. setTimeout(function () { jQuery("#flash").hide(); }, 5000); } }; // <------ Info display // ------> Alert for basic fields presence (created_at, updated_at) // This script is brought to you by Aloïs, thanks to him and his amazing cat :) const displayRequiredFieldNotice = () => { if (modules.fieldPresence.active) { const created_at = document.querySelector("[title^='created_at']"); const updated_at = document.querySelector("[title^='updated_at']"); const sidebarNotes = document.querySelector("#field_types span"); const maveocName = document.querySelector("#content h2").innerText; const existingStorage = JSON.parse( JSON.parse(window.localStorage.getItem("disabled_notices")) ); const disableButtons = document.querySelectorAll(".disable-notice"); if (created_at && updated_at) return; if (sidebarNotes) { if ( (!created_at && existingStorage == null) || (!created_at && existingStorage !== null && !existingStorage.includes(maveocName)) ) { sidebarNotes.innerHTML += '<p class="date_fields_warning" style="color:red">You do not have a created_at field! <img alt="Del" class="disable-notice" style="cursor:pointer;" title="Disable ALL notice messages!" src="/images/faveod/del.png?1596181992"></p>'; } if ( (!updated_at && existingStorage == null) || (!updated_at && existingStorage !== null && !existingStorage.includes(maveocName)) ) { sidebarNotes.innerHTML += '<p class="date_fields_warning" style="color:red">You do not have an updated_at field! <img alt="Del" class="disable-notice" style="cursor:pointer;" title="Disable ALL notice messages!" src="/images/faveod/del.png?1596181992"></p>'; } } disableButtons.forEach((button) => button.addEventListener("click", removeNotices) ); } }; const removeRequiredFieldNotice = () => { const notices = document.querySelectorAll(".date_fields_warning"); notices.forEach((notice) => notice.hide()); let value = ""; if (existingStorage !== null) { existingStorage.push(maveocName); value = JSON.stringify(existingStorage); } else { value = JSON.stringify([maveocName]); } window.localStorage.setItem(`disabled_notices`, value); }; // <------ Alert for basic fields presence // ------> User Story warning const displayUserStoryWarning = () => { // Initially started this one to encourage always working with a user story // Enable or not depending of the project, disabled by default if (modules.userStory.active) { const $userStoryIndicator = jQuery("#working_on"); if (!$userStoryIndicator.length) { const $userStoryWarning = jQuery("<span></span>") .attr("id", "user-story-warning") .text("WARNING ! You are currently working without any User story !") .css("color", "#D04158") .css("font-weight", "bold") .css("font-size", "1.1em"); const $warningLogo = jQuery("<span></span>") .attr("id", "user-story-warning-logo") .css("background-image", "url(https://i.imgur.com/JW2wKDs.png)") .css("height", "20px") .css("width", "20px") .css("display", "inline-block") .css("background-position", "center") .css("background-size", "contain") .css("margin-bottom", "-4px") .css("margin-right", "4px"); jQuery("#header-elts").prepend($userStoryWarning); $userStoryWarning.prepend($warningLogo); let counter = 1; const isOdd = (x) => { return x & 1; }; setInterval(function () { if (isOdd(counter) == 1) { $warningLogo.css( "background-image", "url(https://i.imgur.com/JW2wKDs.png)" ); counter += 1; } else { $warningLogo.css( "background-image", "url(https://i.imgur.com/iqfdJGd.png)" ); counter += 1; } }, 1000); } } }; // <------ User stroy warning // ------> Editor QOL const displayEditorInfos = () => { if (modules.editorQol.active) { displayStatus(); displaySpecReference(); displaySharing(); } }; const displayStatus = () => { const $originalStatus = jQuery("select[id$='_status']"); if (!$originalStatus.length) { return; } const $newStatus = $originalStatus.clone(); $newStatus .attr("id", "new-select") .val($originalStatus.val()) .css("margin-right", "10px") .css("border-radius", "5px"); $newStatus.on("change", function () { $originalStatus.val(jQuery(this).val()); }); $originalStatus.on("change", function () { $newStatus.val(jQuery(this).val()); }); jQuery("#content h2.title").prepend($newStatus); }; const displaySpecReference = () => { const $originalSpecRef = jQuery("input[id$='_spec_ref']"); if (!$originalSpecRef.length) { return; } const $newSpecRef = $originalSpecRef.clone(); $newSpecRef .attr("id", "new-specref") .attr("placeholder", "US Reference") .css("text-align", "center") .css("border-radius", "5px") .css("margin-left", "10px") .css("display", "inline-block"); $newSpecRef.on("change", function () { $originalSpecRef.val(jQuery(this).val()); }); $originalSpecRef.on("change", function () { $newSpecRef.val(jQuery(this).val()); }); jQuery("#content h2.title").append($newSpecRef); }; const displaySharing = () => { const currentAvailability = jQuery("select[id$='_shared_for']").val(); const label = jQuery("select[id$='_shared_for'] option:selected").text(); if (!jQuery("select[id$='_shared_for']").length) { return; } const $wrapper = jQuery("<p></p>"); const $availability = jQuery("<span></span>") .text(`Available for ${label}`) .css("border", "1px solid black") .css("background-color", "grey") .css("color", "white") .css("padding", "3px") .css("border-radius", "5px") .css("margin-left", "10px"); if (currentAvailability == 3) { $wrapper.text("This code need manual regeration to be applied"); const $warningSign = jQuery("<i />") .addClass("muted glyphicon glyphicon-exclamation-sign") .css("color", "orange") .css("margin-right", "5px"); $wrapper.prepend($warningSign); } $wrapper.append($availability); jQuery("#content h2.title").append($wrapper); }; // <------ Editor QOL // ------> General lisibility const displayVisibilityBoost = () => { if (modules.generalLisibility.active) { /* ----- Always show lightened lightbulbs ----- */ const wantedSrc = "/images/page_icons/lightbulb.png?1199643502"; jQuery("td") .find(`img[src="${wantedSrc}"]`) .parents("td") .css("opacity", "1"); /*------- Add a color if a view is a partial ------*/ jQuery(".partial").find("a").css("color", "rgba(233, 96, 42, 0.7)"); /* show color for scss variables */ const $variableTable = jQuery("#style_variables_table"); if ($variableTable.length) { $variableTable .find("tbody") .find("tr") .each(function () { jQuery(this) .find("td:nth-child(2)") .css( "background-color", jQuery(this).find("td:nth-child(4)").text() ); }); } /* Add separator in search */ document .getElementById("global_search_field") .addEventListener("input", () => { setTimeout(function () { const separatorStyle = "1px dashed black"; const resultBox = document.getElementById("gs_results"); const entries = []; entries.push(resultBox.querySelector(".config_initializers")); entries.push(resultBox.querySelector(".cfg_dependencies")); entries.push(resultBox.querySelector(".use_cases")); entries.push(resultBox.querySelector(".style_variables")); entries.push(resultBox.querySelector(".javascripts")); entries.push(resultBox.querySelector(".js_frameworks")); entries.push(resultBox.querySelector(".js_functions")); entries.push(resultBox.querySelector(".styles")); entries.push(resultBox.querySelector(".layouts")); entries.push(resultBox.querySelector(".notifications")); entries.push(resultBox.querySelector(".aktions")); entries.push(resultBox.querySelector(".field_actions")); entries.push( resultBox.querySelector(".action_attribute_definitions") ); entries.push(resultBox.querySelector(".field_formatters")); entries.push(resultBox.querySelector(".field_behaviours")); entries.push(resultBox.querySelector(".field_styles")); entries.push(resultBox.querySelector(".field_views")); entries.push(resultBox.querySelector(".view_helpers")); entries.push(resultBox.querySelector(".views")); entries.push(resultBox.querySelector(".model_tests")); entries.push(resultBox.querySelector(".model_logics")); entries.push(resultBox.querySelector(".fields")); entries.map((entry) => { if (entry != null) { entry.parentNode.style.borderTop = separatorStyle; } }); }, 1000); }); } }; // <------ General lisibility // ------> Editor Size const resizeEditor = () => { if (modules.editorSize.active) { let height = getCookie("text_editor_height").length ? getCookie("text_editor_height") : "454px"; const $editor = jQuery(".ace_editor"); $editor.css("height", height); window.addEventListener("beforeunload", function () { setLocalCookie("text_editor_height", $editor.css("height")); }); } }; // <------ Editor Size // ------> Regen Button const addRegenButton = () => { // This script is brought to you by Thibault, thanks to him :) if (modules.regenButton.active && location.href.includes("/model/")) { const titles = document.querySelectorAll("h2.title"); console.log(titles); const title = titles[titles.length - 1]; console.log(title); title.insertAdjacentHTML( "beforeend", `<span id="regen">${String.fromCodePoint(0x1f504)}</span>` ); const regen = document.querySelector("#regen"); console.log(regen); regen.style.cursor = "pointer"; let divs = document.querySelectorAll("fieldset div.moved_field_objects"); console.log(divs); let maveocId = document.querySelector("#content").dataset["in_use"]; console.log(maveocId); let fields = []; divs.forEach((mfo, i) => { if (divs[i + 1] == mfo.nextElementSibling && fields.length < 2) { fields.push(mfo.id.split("_")[1]); fields.push(divs[i + 1].id.split("_")[1]); } return fields; }); regen.addEventListener("click", () => { if (!confirm("Do you want to regen this Maveoc ?")) return; fetch("https://datx-bsolutions-des.faveod.com/fields/move_dropped", { credentials: "include", headers: { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:127.0) Gecko/20100101 Firefox/127.0", Accept: "text/javascript, text/html, application/xml, text/xml, */*", "Accept-Language": "en-GB,en;q=0.5", "X-Requested-With": "XMLHttpRequest", "X-Prototype-Version": "1.6.1", "Content-type": "application/x-www-form-urlencoded; charset=UTF-8", "X-CSRF-Token": "XkQQ715zzX7MXgiqZQMzkFCOox4TiI3VtJ3Vvcsfq5M=", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-origin", Priority: "u=1", Pragma: "no-cache", "Cache-Control": "no-cache", }, referrer: "https://datx-bsolutions-des.faveod.com/maveocs/model/502?tab=model", body: `model=${maveocId}&receiver=${fields[0]}&id=${fields[1]}`, method: "POST", mode: "cors", }).then(console.log(`%c Starting Maveoc regen...`, "color: #38C4CC")); }); } }; // <------ Regen Button // ------> DragDrop Locker const addDragDropLocker = () => { if (modules.dragDropLocker.active) { const addLocker = () => { return new Promise((resolve, reject) => { // add html button const titles = document.querySelectorAll("h2.title"); const title = titles[titles.length - 1]; const lockerBox = document.createElement("div"); lockerBox.classList.add("locker-box"); lockerBox.style.display = "flex"; lockerBox.style.alignItems = "center"; lockerBox.style.justifyContent = "center"; const lockerInput = document.createElement("input"); lockerInput.id = "js-dragdrop-input"; lockerInput.setAttribute("type", "checkbox"); lockerInput.style.display = "none"; const lockerButton = document.createElement("label"); lockerButton.classList.add("btn"); lockerButton.id = "js-dragdrop-label"; lockerButton.innerHTML = "DragDrop Lock"; lockerButton.setAttribute("for", "js-dragdrop-input"); lockerButton.style.border = "1px solid darkblue"; lockerButton.style.cursor = "pointer"; lockerButton.style.padding = "5px"; lockerBox.append(lockerInput); lockerBox.append(lockerButton); title.append(lockerBox); // If we set it manually or by default anyway const isLocked = getCookie("dragDropLock") == "true" || getCookie("dragDropLock") == ""; lockerInput.checked = isLocked; lockerInput.addEventListener("change", (e) => { const label = document.getElementById("js-dragdrop-label"); e.target.checked ? lock(label) : unlock(label, true); }); resolve(isLocked); }); }; const lock = (label) => { label.innerHTML = "Drag&Drop locked, click to unlock"; setLocalCookie("dragDropLock", "true", 365, location.pathname); const fields = document.querySelectorAll(".moved_field_objects"); const dragDropPanel = document.querySelector("td.drag_objects"); dragDropPanel.remove(); // const rows = document.querySelectorAll('#view_parts_table fieldset') Array.from(fields).map((field) => { const newElement = field.cloneNode(true); field.parentNode.replaceChild(newElement, field); }); const actions = document.querySelectorAll(".field_actions"); Array.from(actions).map((action) => (action.style.display = "block")); Array.from( document.querySelectorAll('[data-indicator="model_indicator"]') ).map((arrow) => (arrow.style.display = "none")); }; const unlock = (label, reload = false) => { if (reload && !confirm("This will reload current page, proceed ?")) return; label.innerHTML = "Drag&Drop unlocked, click to lock"; setLocalCookie("dragDropLock", "false", 365, location.pathname); if (reload) window.location.reload(); }; const moveReminders = () => { const tabBox = document.getElementById("mvc_tabs"); const helpButton = document.querySelector( '#field_types img[alt="Help"]' ).parentNode; const infoButton = document.querySelector( '#field_types img[alt="Information"]' ).parentNode; helpButton.querySelector("img").style.marginRight = "5px"; infoButton.querySelector("img").style.marginRight = "5px"; const helpTab = document.createElement("li"); helpTab.classList.add("help-tab"); helpTab.style.float = "right"; const helpLabel = document.createElement("span"); helpLabel.innerText = "Help"; const infoTab = document.createElement("li"); infoTab.classList.add("info-tab"); infoTab.style.float = "right"; const infoLabel = document.createElement("span"); infoLabel.innerText = "Infos"; helpButton.appendChild(helpLabel); infoButton.appendChild(infoLabel); helpTab.appendChild(helpButton); infoTab.appendChild(infoButton); tabBox.appendChild(infoTab); tabBox.appendChild(helpTab); }; if (location.href.includes("/model/")) { moveReminders(); addLocker().then((isLocked) => { const label = document.getElementById("js-dragdrop-label"); isLocked ? lock(label) : unlock(label); }); } } }; // <------ DragDrop Locker // ------> Quality Framework const initQualityFramework = () => { if ( modules.qualityFramework.active && !window.location.pathname.includes("/use_cases/") ) { const initDevalidationWarning = () => { const submitButtons = [ ...document.querySelectorAll('input[type="submit"]'), ]; const originalStatus = document.querySelector("select[id$='_status']"); if (!submitButtons || !originalStatus) return; const isValidated = originalStatus.value == 8; const isDraft = originalStatus.value == 1; if (isDraft) { setTimeout(function () { initDevalidationWarning(); return; }, 800); } if (!isValidated) { return; } submitButtons.map((button) => { button.addEventListener("click", function (e) { if (!button.classList.contains("confirmed")) { e.preventDefault(); if ( !confirm( 'Saving a "validated" code will make it regress to "waiting for validation". Continue ?' ) ) return; originalStatus.value = 7; button.classList.add("confirmed"); button.click(); } }); }); }; const initFieldsRequired = () => { const description = document.querySelector( "textarea[id$='_description']" ); // const commit = document.querySelector("textarea[id$='_commit_message']") const submitButtons = [ ...document.querySelectorAll('input[type="submit"]'), ]; if (!submitButtons || !description) return; if (description.value.trim().length < 10) { submitButtons.map((button) => { disableElement( button, "A description of at least 10 characters is required" ); }); } description.addEventListener("input", () => { handleRequiredFields(submitButtons, description); }); // commit.addEventListener('input', () => { // handleRequiredFields(submitButtons, description, commit) // }) }; const handleRequiredFields = (buttons, description) => { if (description.value.trim().length < 10) { buttons.map((button) => { disableElement( button, "A description and a commit message of at least 10 characters is required" ); }); } else { buttons.map((button) => { button.removeAttribute("disabled"); button.removeAttribute("title"); button.removeAttribute("style"); }); } }; initDevalidationWarning(); initFieldsRequired(); } }; // <------ Quality Framework // ------> Experimental UI const initExperimentalUi = () => { if (modules.experimentalInterface.active) { console.log("%c Loading experimental interface", "color: #38C4CC"); const link = document.createElement("link"); link.type = "text/css"; link.rel = "stylesheet"; document.head.appendChild(link); link.href = "https://cdnjs.cloudflare.com/ajax/libs/chosen/1.8.7/chosen.css"; jQuery('select[multiple="multiple"]').chosen(); // jQuery("select[id*='field_format_views_matching_']").chosen() jQuery(".chosen-container-multi").css("width", "100%"); jQuery(".chosen-choices") .css("overflow", "auto") .css("max-height", "35vh"); console.log("test", jQuery("#review_filters").find("select")); jQuery("#review_filters").find("select").chosen(); } }; // <----- Experimental UI jQuery(document).ready(function () { setTimeout(function () { initOverlay(); }, 800); }); })(jQuery); // ------> HELPERS (overlay global) function setLocalCookie(name, value, days, path = "/") { let expires = ""; if (days) { const date = new Date(); date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); expires = "; expires=" + date.toUTCString(); } document.cookie = name + "=" + (value || "") + expires + `; path=${path}`; } function getCookie(cname) { const decodedCookie = decodeURIComponent(document.cookie); const ca = decodedCookie.split(";"); const match = ca.filter((cookie) => { return cookie.includes(cname); }); return match[0] ? match[0].replace(`${cname}=`, "").trim() : ""; } function disableElement(element, title = "") { element.setAttribute("disabled", "disabled"); element.setAttribute("title", title); element.style.color = "grey"; element.style.borderColor = "grey"; element.style.cursor = "not-allowed"; } function delay(time) { return new Promise((resolve) => setTimeout(resolve, time)); } // <------ HELPERS