|
| 1 | +/** @odoo-module QWeb **/ |
| 2 | +/* global document, window, console */ |
| 3 | +import {_t} from "@web/core/l10n/translation"; |
| 4 | + |
| 5 | +export function offset(el) { |
| 6 | + const box = el.getBoundingClientRect(); |
| 7 | + const docElem = document.documentElement; |
| 8 | + return { |
| 9 | + top: box.top + window.scrollY - docElem.clientTop, |
| 10 | + left: box.left + window.scrollY - docElem.clientLeft, |
| 11 | + }; |
| 12 | +} |
| 13 | + |
| 14 | +/** |
| 15 | + * Starts the sign item navigator |
| 16 | + * @param { SignablePDFIframe } parent |
| 17 | + * @param { HTMLElement } target |
| 18 | + * @param { Object } types |
| 19 | + * @param { Environment } env |
| 20 | + */ |
| 21 | +export function startSignItemNavigator(parent, target, types, env) { |
| 22 | + console.log("types", types); |
| 23 | + console.log("env", env); |
| 24 | + |
| 25 | + const state = { |
| 26 | + started: false, |
| 27 | + isScrolling: false, |
| 28 | + }; |
| 29 | + |
| 30 | + const navigator = document.createElement("div"); |
| 31 | + navigator.classList.add("o_sign_sign_item_navigator"); |
| 32 | + const navLine = document.createElement("div"); |
| 33 | + navLine.classList.add("o_sign_sign_item_navline"); |
| 34 | + |
| 35 | + // Function _scrollToSignItemPromise(item) { |
| 36 | + // if (env.isSmall) { |
| 37 | + // return new Promise((resolve) => { |
| 38 | + // state.isScrolling = true; |
| 39 | + // item.scrollIntoView({ |
| 40 | + // behavior: "smooth", |
| 41 | + // block: "center", |
| 42 | + // inline: "center", |
| 43 | + // }); |
| 44 | + // resolve(); |
| 45 | + // }); |
| 46 | + // } |
| 47 | + // State.isScrolling = true; |
| 48 | + // const viewer = parent.iframe.el.contentDocument.getElementById("viewer"); |
| 49 | + // const containerHeight = target.offsetHeight; |
| 50 | + // const viewerHeight = viewer.offsetHeight; |
| 51 | + |
| 52 | + // const scrollOffset = containerHeight / 4; |
| 53 | + // Const scrollTop = offset(item).top - offset(viewer).top - scrollOffset; |
| 54 | + // if (scrollTop + containerHeight > viewerHeight) { |
| 55 | + // scrollOffset += scrollTop + containerHeight - viewerHeight; |
| 56 | + // } |
| 57 | + // if (scrollTop < 0) { |
| 58 | + // scrollOffset += scrollTop; |
| 59 | + // } |
| 60 | + // scrollOffset += |
| 61 | + // offset(target).top - |
| 62 | + // navigator.offsetHeight / 2 + |
| 63 | + // item.getBoundingClientRect().height / 2; |
| 64 | + |
| 65 | + // const duration = Math.max( |
| 66 | + // Math.min( |
| 67 | + // 500, |
| 68 | + // 5 * |
| 69 | + // (Math.abs(target.scrollTop - scrollTop) + |
| 70 | + // Math.abs(navigator.getBoundingClientRect().top) - |
| 71 | + // scrollOffset) |
| 72 | + // ), |
| 73 | + // 100 |
| 74 | + // ); |
| 75 | + |
| 76 | + // return new Promise((resolve) => { |
| 77 | + // target.scrollTo({top: scrollTop, behavior: "smooth"}); |
| 78 | + // target.scrollTo({behavior: "smooth"}); |
| 79 | + // const an = navigator.animate( |
| 80 | + // {top: `${scrollOffset}px`}, |
| 81 | + // {duration, fill: "forwards"} |
| 82 | + // ); |
| 83 | + // const an2 = navLine.animate( |
| 84 | + // {top: `${scrollOffset}px`}, |
| 85 | + // {duration, fill: "forwards"} |
| 86 | + // ); |
| 87 | + // Promise.all([an.finished, an2.finished]).then(() => resolve()); |
| 88 | + // }); |
| 89 | + |
| 90 | + // return new Promise((resolve, reject) => { |
| 91 | + // setTimeout(() => { |
| 92 | + // resolve("Promise resolved! ✅"); |
| 93 | + // }, 2000); // Simulates an async task |
| 94 | + // }); |
| 95 | + // } |
| 96 | + |
| 97 | + function setTip(text) { |
| 98 | + navigator.style.fontFamily = "Helvetica"; |
| 99 | + navigator.innerText = text; |
| 100 | + } |
| 101 | + |
| 102 | + // /** |
| 103 | + // * Sets the entire radio set on focus. |
| 104 | + // * @param {Number} radio_set_id |
| 105 | + // */ |
| 106 | + // function highligtRadioSet(radio_set_id) { |
| 107 | + // parent |
| 108 | + // .checkSignItemsCompletion() |
| 109 | + // .filter((item) => item.data.radio_set_id === radio_set_id) |
| 110 | + // .forEach((item) => { |
| 111 | + // item.el.classList.add("ui-selected"); |
| 112 | + // }); |
| 113 | + // } |
| 114 | + |
| 115 | + function scrollToSignItem({el: item, data}) { |
| 116 | + console.log("item", item); |
| 117 | + console.log("data", data); |
| 118 | + |
| 119 | + // _scrollToSignItemPromise(item).then(() => { |
| 120 | + // Const type = types[data.type_id]; |
| 121 | + // if (type.item_type === "text" && item.querySelector("input")) { |
| 122 | + // item.value = item.querySelector("input").value; |
| 123 | + // item.focus = () => item.querySelector("input").focus(); |
| 124 | + // } |
| 125 | + // // Maybe store signature in data rather than in the dataset |
| 126 | + // if (item.value === "" && !item.dataset.signature) { |
| 127 | + // setTip(type.tip); |
| 128 | + // } |
| 129 | + // // parent.refreshSignItems(); |
| 130 | + // if (data.type === "radio") { |
| 131 | + // // We need to highligt the entire radio set items |
| 132 | + // highligtRadioSet(data.radio_set_id); |
| 133 | + // } else { |
| 134 | + // item.focus(); |
| 135 | + // item.classList.add("ui-selected"); |
| 136 | + // } |
| 137 | + // if (["signature", "initial"].includes(type.item_type)) { |
| 138 | + // if (item.dataset.hasFocus) { |
| 139 | + // const clickableElement = data.isSignItemEditable |
| 140 | + // ? item.querySelector(".o_sign_item_display") |
| 141 | + // : item; |
| 142 | + // clickableElement.click(); |
| 143 | + // } else { |
| 144 | + // item.dataset.hasFocus = true; |
| 145 | + // } |
| 146 | + // } |
| 147 | + // state.isScrolling = false; |
| 148 | + // }); |
| 149 | + } |
| 150 | + |
| 151 | + function goToNextSignItem() { |
| 152 | + if (!state.started) { |
| 153 | + state.started = true; |
| 154 | + // Parent.refreshSignItems(); |
| 155 | + goToNextSignItem(); |
| 156 | + return false; |
| 157 | + } |
| 158 | + const selectedElements = target.querySelectorAll(".ui-selected"); |
| 159 | + selectedElements.forEach((selectedElement) => { |
| 160 | + selectedElement.classList.remove("ui-selected"); |
| 161 | + }); |
| 162 | + |
| 163 | + // I am using this function to return all fields to be signed |
| 164 | + // but in EE it returns an array of objects |
| 165 | + const signItemsToComplete2 = parent.checkSignItemsCompletion().sort((a, b) => { |
| 166 | + return ( |
| 167 | + 100 * (a.data.page - b.data.page) + |
| 168 | + 10 * (a.data.posY - b.data.posY) + |
| 169 | + (a.data.posX - b.data.posX) |
| 170 | + ); |
| 171 | + }); |
| 172 | + const signItemsToComplete = [ |
| 173 | + {data: {page: 1, posY: 10, posX: 20}}, |
| 174 | + {data: {page: 2, posY: 5, posX: 30}}, |
| 175 | + {data: {page: 1, posY: 15, posX: 25}}, |
| 176 | + ]; |
| 177 | + |
| 178 | + if (signItemsToComplete.length > 0) { |
| 179 | + const first_target_field = signItemsToComplete2[0][0]; |
| 180 | + |
| 181 | + console.log("first_target_field", typeof first_target_field); |
| 182 | + console.log("first_target_field", first_target_field); |
| 183 | + |
| 184 | + scrollToSignItem(signItemsToComplete[0]); |
| 185 | + first_target_field.append(navigator); |
| 186 | + } |
| 187 | + } |
| 188 | + |
| 189 | + navigator.addEventListener("click", goToNextSignItem); |
| 190 | + |
| 191 | + goToNextSignItem(); |
| 192 | + // Target.append(navigator); |
| 193 | + navigator.before(navLine); |
| 194 | + |
| 195 | + setTip(_t("Click to start")); |
| 196 | + navigator.focus(); |
| 197 | + |
| 198 | + function toggle(force) { |
| 199 | + navigator.style.display = force ? "" : "none"; |
| 200 | + navLine.style.display = force ? "" : "none"; |
| 201 | + } |
| 202 | + |
| 203 | + return { |
| 204 | + setTip, |
| 205 | + goToNextSignItem, |
| 206 | + toggle, |
| 207 | + state, |
| 208 | + }; |
| 209 | +} |
0 commit comments